当你使用passwd给linux设置自己的用户密码时候, 如果密码不够复杂, linux是不让你使用的.
可是有时候你就是想用一个简单的密码, 比如我只是装个虚拟机用用而已, 怎么办呢?
用这个命令就可以了

sudo passwd <username>

这时候提示输入的密码不再会检查密码强度.

以前有一个颇受欢迎的替代"我的电脑"和"资源管理器"的软件Totalcommander, 不过是收费的. 这儿推荐免费软件FreeCommander(以下简称FC),同样十分强大.

1. 中文

原生支持数十种语言. 默认安装是英文的? 并不需要担心. 在Tools>Settings->General->Language中选择Chinese_s.lng即可.

2. 快速调用CMD命令行.

软件开发经常需要在当前目录使用命令行. 虽然windows自带Win+R -> cmd回车的方式, 不过调出的命令行是在用户根目录下.
在FC中按Ctrl+D就可以调出当前目录下的命令行, 十分方便.

3. 快速编辑文本

软件开发经常需要打开各种文本格式的代码文件查看, 选中指定文件按F4即可调出默认编辑器, 哦, 默认的是notepad? 没关系, 可以在 "工具>设置>程序>编辑器"中更改. 我用的是Sumlime Text, 将程序改为C:\Program Files\Sublime Text 3\sublime_text.exe即可. 注意不需要加双引号.

4. 收藏目录

Windows有快捷键Win+E调出资源管理器,可是要进入常用目录还需要自己点点点. 最新的Win10做了改进, 可以添加"快速访问"并从左侧进入. 不过,如果用FC替代呢?在地址栏右侧有一个图标是带有❤标志的文件夹, 点击就可以收藏了.

5. 复制目录路径

常常需要在其他软件中, 打开指定路径下的某个文件, 这时候文件路径复制粘贴可能是最快的方式之一. 资源管理器是选中->Ctrl+C的方式, 在FC中, 可以点击地址栏最右侧的小图标即可复制.

1. 快速开始

通过electron quick start项目开始是个不错的主意. 需要注意的是, electron体积巨大, 100M~200M, 在我朝使用主意用镜像, 或者使用淘宝的cnpm,替代下面的npm install.

# Clone the Quick Start repository
$ git clone https://github.com/electron/electron-quick-start

# Go into the repository
$ cd electron-quick-start

# Install the dependencies and run
$ npm install && npm start

这时候你应该能看到一个helloworld 和一个打开的chrome dev tools.

2. 最主要的文件和关系

在根目录下, 有main.js ,index.html, renderer.js几个文件,以及node_modules文件夹,还有package.json文件.
首先, electron主要有两块:

a) 与操作系统的一些原生API通讯, 这主要通过main.js调用系统的一些方法和界面.比如显示个菜单, 调起一个打开文件对话框之类的.
b) 建立软件的界面和逻辑, 这主要通过index.html,renderer.js以及其他html架构的文件(以下简称为html架构). 但在这儿不能直接调用系统的资源, 如逆向调起一个打开文件对话框就不行.

是否以main.js为入口, 在package.json中配置, 里面有一行:

 "main": "main.js",

当然, 也只有这一个文件,不涉及复杂的文件管理的话, 这个一般也不会去改它.

是否以index.html为入口, 在main.js调起window的时候定义:

    mainWindow.loadURL(url.format({
        pathname: path.join(__dirname, 'index.html'),
        protocol: 'file:',
        slashes: true
    }))

上面的index.html可以使用相对路径调起其他的html文件, 相对路径的起点为main.js所在的目录.
至于renderer.js, 是通过index.html中的script标签引用的, 这个就熟悉了,不多说了.

3. 在html架构中调用系统资源的第一种方式: 发送事件消息

前面说了html架构中不能直接调用系统资源,调用需要通过main.js进行. 和main.js通讯主要是通过发送event消息.
整个过程是:
* renderer.js中ipc.send()发送事件A
* main.js中ipcMain.on()监听事件A, 监听到后,
* main.js中event.sender.send()发送事件B和附加信息
* renderer.js中ipc.on()监听返回的事件B,处理发回的信息

举例如下: 在main.js中通过ipcMain.on()监听html架构中的renderer.js发来的open-file-dialog事件, 并在监听后调用系统事件,如dialog, 然后通过event.sender.send()回馈selected-directory事件,并携带文件路径:

const { ipcMain } = require('electron')
const { dialog } = require('electron')
ipcMain.on('open-file-dialog', function(event) {
    dialog.showOpenDialog({
        properties: ['openFile', 'openDirectory']
    }, function(files) {
        if (files) event.sender.send('selected-directory', files)
    })
})

在renderer.js中, 通过ipc.send()发送open-file-dialog事件, 通过ipc.on()监听返回事件selected-directory, 并可以对返回的文件路径做进一步的处理.

const ipc = require('electron').ipcRenderer
ipc.send('open-file-dialog')
ipc.on('selected-directory', function(event, path) {
    alert(path)
})

4. 在html架构中调用系统资源的第二种方式. remote

上面的简化写法, 可以直接使用remote调用main.js中才能提供的系统资源.
在renderer.js中:

const remote = require('electron').remote    
remote.dialog.showOpenDialog({
    properties: ['openFile', 'openDirectory']
}, function(files) {
    alert(files)
})

哦,好像感觉好用多了...

5. 在main.js中主动发送事件给html框架

这时候没有renderer.js发过来的事件, 也就没有event.sender.send()提供, 可以用mainWindow, 前提是mainWindow已经创建.

mainWindow.send('some-event')

7. 打包软件

首先要有一份electron的可运行文件包, node_modules\electron\dist中可以找到electron.exe, 这个文件夹就是了.打包这个文件夹发布就可以了.
只要把main.js,package.json, node_modules中你用到的模块,以及其他index.html等html框架下的文件复制到上面文件Resources/app目录下. 然后把electron.exe所在的文件夹打包发布就可以了.

8. 更改图标

windows下有个免费软件resource hacker, 下载来可以用来修改图标.
mac下比较简单. 查看electron.app的信息, 里面的图标可以通过'拷贝'/'粘贴'进行修改的.
mac下打包成dmg, 需要预先把electron.app放到一个文件夹里面, 然后可以通过系统自带的'磁盘工具',点击菜单>文件>新建影像>来自文件夹的影像>选择这个文件夹进行打包.

下面是坑

1号坑 使用第三方npm模块

在html框架中最强大的一个地方就是,不但可以通过script标签引入第三方js使用, 可以通过require使用node.js中提供的模块. 但是注意, 要使用npm install安装,不要使用cnpm install安装, 否则打包后的文件会找不到模块. 原因请看前一篇文章.

2号坑 使用asar打包

可以通过npm install -g asar安装asar打包工具, 对app目录进行打包,这样就不会有一大把的分散文件列在哪儿了, 也避免windows复制node_modules总会出现的长文件名问题.
在resource目录下,命令行执行:

asar pack app app.asar

即可, 执行完后asar包使用起来大多数时候像一个普通目录, 但在如下时候会与普通目录不同

  • asar包在运行时是只读的, 所以不能再在运行时修改asar包,比如修改其中的文件, 新建一个文件等,否则你会遇到permission的拒绝的错误.
  • 在windows下,asar包中的文件和文件夹可以复制出来, 并粘贴到系统的某处(使用node模块ncp测试过), 但在mac下却不行,原因也是未知啊. 变通的方式是, 你要复制的文件夹就不要放在asar包里面了.

3号坑 菜单

建立的多个一级菜单, 如果有的一级菜单没有子菜单submenu, 而是直接在一级菜单上触发功能, 那么在windows下将显示正常并且触发正常. 但是在mac下只能显示有submenu的.
因此建议所有的一级菜单都要有submenu, 并且不要在一级菜单上触发功能.
另外, mac下面无论什么样的菜单, 第一个菜单都是挂在系统名称下面的.

4号坑 复制粘贴

在Windows下, input和textarea使用Ctrl+C/Ctrl+V复制粘贴正常, 在mac下使用COMMAND+C/V却没有反应. 原因是mac下必须显式定义复制粘贴. 解题思路在这儿
定义的方式是在菜单中添加复制/粘贴选项.

在我朝, 因为伟大的wall的存在, 什么git npm pip之类的原生源都不怎么好用, 必须要找个什么镜像之类的.npm最好的镜像当然就是淘宝了. 并且淘宝贴心地推出了cnpm工具, 替代npm安装.
以前真以为npm和cnpm除了源不一样其他都以一样一样的, 结果在用electron+asar打包的时候被坑了一天... 安装的包使用死活找不到.我要装的包是ncp. 情况是这样的:
0. 首先简化的目录结构是:

rootdir
|-electron.exe
|-resources
  |-app
    |-main.js
    |-index.html
    |-renderer.js
  1. 在electron开发源码目录下(app目录, 也就是main.js所在目录)使用
    cnpm install --save ncp
    安装, 并在renderer.js文件中
    var ncp = require('ncp')

  2. 在此目录下运行
    electron .
    注意: 这个electron是使用npm install -g electron安装的全局electron, 与前面目录结构中的electron.exe不是同一个.
    一切正常.

  3. resources目录下用asar pack app app.asar 打包

  4. 在外层目录下运行electron.exe 发现console提示找不到ncp!

问题产生, 以为是electron的问题, 沿着这个方向查了好久...直到刚刚才发现, cnpm安装的目录结构和npm不一样!

* 建立一个空目录,运行npm install --save ncp,结果如下:

C:\r\vueproj\nhproj\nhpedev\test>npm install --save ncp
npm WARN saveError ENOENT: no such file or directory, open 'C:\r\vueproj\nhproj\nhpedev\test\package.json'
C:\r\vueproj\nhproj\nhpedev\test
`-- ncp@2.0.0

npm WARN enoent ENOENT: no such file or directory, open 'C:\r\vueproj\nhproj\nhpedev\test\package.json'
npm WARN test No description
npm WARN test No repository field.
npm WARN test No README data
npm WARN test No license field.

是的,空目录里面没有package.json, 找不到也正常. tree一下,看看结构:

C:.
└─node_modules
    ├─.bin
    └─ncp
        ├─bin
        ├─lib
        └─test
            ├─modified-files
            │  ├─out
            │  └─src
            ├─regular-fixtures
            │  └─src
            │      └─sub
            └─symlink-fixtures
                └─src
                    └─dir

可以看到ncp直接装在node_modules下面.
再dir确认一下:

2016/11/25  11:25    <DIR>          .
2016/11/25  11:25    <DIR>          ..
2016/11/25  11:25    <DIR>          node_modules

进入node_modules确认一下ncp的目录类型,不是一个链接而是一个真的目录:

2016/11/25  11:25    <DIR>          .
2016/11/25  11:25    <DIR>          ..
2016/11/25  11:25    <DIR>          .bin
2016/11/25  11:25    <DIR>          ncp

* 然后另外建立一个空目录, 使用cnpm install --save ncp输出如下:

C:\r\vueproj\nhproj\nhpedev\testcnpm>cnpm install --save ncp
[ncp@*] installed at node_modules\.npminstall\ncp\2.0.0\ncp (0 packages, use 540ms, speed 7.23kB/s, json 3.93kB, tarball 0B)
All packages installed (1 packages installed from npm registry, use 572ms, speed 6.87kB/s, json 1(3.93kB), tarball 0B)

并没有报任何错误, dir看一下,连package.json都贴心的生成了:

2016/11/25  11:26    <DIR>          .
2016/11/25  11:26    <DIR>          ..
2016/11/25  11:26    <DIR>          node_modules
2016/11/25  11:26                47 package.json

看一下package.json的内容,没有问题:

{
  "dependencies": {
    "ncp": "^2.0.0"
  }
}

用tree命令看看目录结构

└─node_modules
    ├─.bin
    ├─.npminstall
    │  ├─ncp
    │  │  └─2.0.0
    │  │      └─ncp
    │  │          ├─bin
    │  │          ├─lib
    │  │          └─test
    │  │              ├─modified-files
    │  │              │  ├─out
    │  │              │  └─src
    │  │              ├─regular-fixtures
    │  │              │  └─src
    │  │              │      └─sub
    │  │              └─symlink-fixtures
    │  │                  └─src
    │  │                      └─dir
    │  └─node_modules
    │      └─ncp
    │          ├─bin
    │          ├─lib
    │          └─test
    │              ├─modified-files
    │              │  ├─out
    │              │  └─src
    │              ├─regular-fixtures
    │              │  └─src
    │              │      └─sub
    │              └─symlink-fixtures
    │                  └─src
    │                      └─dir
    └─ncp
        ├─bin
        ├─lib
        └─test
            ├─modified-files
            │  ├─out
            │  └─src
            ├─regular-fixtures
            │  └─src
            │      └─sub
            └─symlink-fixtures
                └─src
                    └─dir

可以看到结构是完全不同的, 除了node_modules/ncp是和npm install结构相同以外, 还多出了node_modules/.npminstall/ncp/2.0.0/ncp 以及node_modules/.npminstall/node_modules/ncp
进入顶层的node_modules使用dir:

 C:\r\vueproj\nhproj\nhpedev\testcnpm\node_modules 的目录

2016/11/25  11:26    <DIR>          .
2016/11/25  11:26    <DIR>          ..
2016/11/25  11:26    <DIR>          .bin
2016/11/25  11:26    <DIR>          .npminstall
2016/11/25  11:26    <JUNCTION>     ncp [C:\r\vueproj\nhproj\nhpedev\testcnpm\node_modules\.npminstall\ncp\2.0.0\ncp]

这一层的ncp目录不是真实目录,而是一个JUNCTION!这是与npm install最大的不同,并且也导致了后面electron asar包的找不到的问题
进到node_modules/node_modules/ncp中, dir:

 C:\r\vueproj\nhproj\nhpedev\testcnpm\node_modules\.npminstall\node_modules 的目录

2016/11/25  11:26    <DIR>          .
2016/11/25  11:26    <DIR>          ..
2016/11/25  11:26    <JUNCTION>     ncp [C:\r\vueproj\nhproj\nhpedev\testcnpm\node_modules\.npminstall\ncp\2.0.0\ncp]

ncp仍然是一个JUNCTION
进最后一个目录node_modules/.npminstall/ncp/2.0.0/进行dir:

 C:\r\vueproj\nhproj\nhpedev\testcnpm\node_modules\.npminstall\ncp\2.0.0 的目录

2016/11/25  11:26    <DIR>          .
2016/11/25  11:26    <DIR>          ..
2016/11/25  11:26    <DIR>          ncp

这是一个真实的ncp目录. 也是其他JUNCTION指向的目录.

  • 回到electron,解决问题的方式是, 删除掉node_modules下面的JUNCTION的ncp目录, 将真实的ncp目录复制到此, .npm_install目录可以删除. 再运行electron.exe就没有问题了.
    或者使用npm install而不是cnpm安装

主要是webkit内核浏览器支持.包括如下css名:

::-webkit-scrollbar              { /* 1 */ }
::-webkit-scrollbar-button       { /* 2 */ }
::-webkit-scrollbar-track        { /* 3 */ }
::-webkit-scrollbar-track-piece  { /* 4 */ }
::-webkit-scrollbar-thumb        { /* 5 */ }
::-webkit-scrollbar-corner       { /* 6 */ }
::-webkit-resizer                { /* 7 */ }

举例如下:

::-webkit-scrollbar {
    width: 12px;
}

::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); 
    border-radius: 10px;
}

::-webkit-scrollbar-thumb {
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5); 
}

参考这篇文章

微软明年将发布自己的VR硬件,并且会在win10中集成VR软件环境。这是个VR时代即将到来的强烈信号。
目前VR有两大阵营,台式电脑加头显,手机加VR盒子。前者价格较高并且效果更好,问题是你得像使用台式电脑一样,不能乱跑。后者有任意移动的自由,你可以躺在沙发上,床上,走在路上或者其他什么地方使用。
但我认为目前VR的移动场景并不见得比固定场景更广。因为VR重在提供完全的沉浸体验,它的优势是虚拟世界与现实世界的隔离。而与现实场景的结合是AR的优势。当然也有可能出现以VR技术提供AR体验的方式,那是另一个主题了。因此,VR的大发展很可能是从固定平台而不是移动平台上,这有可能将人们从手机屏幕重新带回到电脑桌前。
软件两大类,工具和游戏。目前VR的一大主要吸引点是在游戏上,但VR在工具类特别是办公应用上相信也大有可为。因为工具类应用对于操作面积也很大,想象一下没有空间限制的屏幕,我可以把所有窗口平铺出来,而不需要去在任务栏一个一个切换了。
配合手势识别,VR同时会带来输入方式的革新,相当于发明和制造新一代的键盘鼠标,看看现在鼠标键盘的普及程度和品牌数量,未来必将爆发一大批的输入硬件制造商。

asar打包

当你使用asar打包app目录

asar app app.asar

打包后的app.asar目录结构中是没有顶级目录app的. 也就是说, app下面的文件和文件夹直接在app.asar的根目录内;你可以用asar list app.asar查看

main.js

main.js是特殊的js, 其中的所有函数,变量,在网页中的js都是不能访问的. 两者之间通讯是通过ipcMain和ipcRenderer互相发送和监听消息.

asar包

在electron中, asar包表现的像是一个真正的目录, 但最重要的是,它是只读的, 你不能向其中写入和修改文件.

position定位四属性: fixed, absolute, relative, static.
前三个属性属于定位属性,static是非定位属性,也是默认值.
fixed是脱离整个文档,相对于屏幕定位, 貌似无论在文档的什么位置/什么嵌套深度里面fixed都一样.
absolute是相对于最近的前代定位元素进行定位的. 意味着并不会相对于前代是static的元素定位.
relative和static的区别,如果没有加上left/top参数的话, 可能也就是在"是否是定位属性"这一点上.
如果本级absolute元素没有像想象的那样定位,那就要看前代的元素哪一个不是定位元素了.

官网上Node.js已经到了7.1.0, 去年8月才发的v4,才一年多一点就v7了...这是什么节奏, 追chrome吗?
尝鲜主义者我就赶快把本机的v5升级到最新的v7.1.0, 然后...我勒个去, 去electron的项目npm install 都失败了...
赶快降级回到v5, 这才成功啊

npm install的时候常常会文件夹深度远超过windows限制(貌似只有200多个字符), 要干掉这个文件夹的时候, 直接删除就会遇到文件夹深度太深的无法删除的问题.
两个方法解决:
1. npm uninstall
不过这种方式有时候也不奏效, 那就另一个大法:
2. robocopy
robocopy居然是windows的自带命令, 从来不知道哦.
比如你想干掉的目录叫node_modules, 在它同级建立一个空目录,如empty

mkdir empty
robocopy empty node_modules /mir
rd node_modules
rd empty

绝大多数情况可以搞定.

近期在产品中发现JS获取不同浏览器的尺寸, 返回结果大不一样, 主要问题出现在华为浏览器(甚至最新的P9)和UC浏览器(11.0.8版本)上.
测试的尺寸包括:

  • document.documentElement.clientWidth /Height
  • document.body.clientWidth /Height
  • window.innerWidth /Height
  • window.outerWidth /Height
  • screen.Width /Height

通过调整viewport的两个属性看尺寸是否有相应的变化, 一种scale为1.0:

<meta id="vp" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

另一种scale为0.5:

<meta id="vp" name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, user-scalable=no">

下表中加粗标出了的尺寸.

huawei chrome mobile huawei 360 mobile huawei QQ mobile browser
scale = 1.0
document.documentElement.clientW/H 360 x 559 360 x 526 360 x 511
document.body.clientW/H 344 x 359 344 x 359 344 x 322
window.innerW/H 360 x 559 360 x 526 360 x 511
window.outerW/H 360 x 559 360 x 526 360 x 511
screen.W/H 360 x 640 360 x 640 360 x 640
UA, scale=1 Mozilla/5.0 (Linux; Android 4.4.2; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2913.5 Mobile Safari/537.36 Mozilla/5.0 (Linux; Android 4.4.2; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36 Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36
scale = 0.5
document.documentElement.clientW/H 720 x 1118 720 x 1052 720 x 1022
document.body.clientW/H 704 x 359 704 x 359 704 x 322
window.innerW/H 720 x 1118 720 x 1052 720 x 1022
window.outerW/H 360 x 559 360 x 526 360 x 511
screen.W/H 360 x 640 360 x 640 360 x 640
UA, scale=0.5 Mozilla/5.0 (Linux; Android 4.4.2; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2913.5 Mobile Safari/537.36 Mozilla/5.0 (Linux; Android 4.4.2; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.94 Mobile Safari/537.36 Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/37.0.0.0 MQQBrowser/7.1 Mobile Safari/537.36
huawei browser huawei UC mobile chrome desktop simulator galaxy s5
scale = 1.0
document.documentElement.clientW/H 360 x 508 360 x 518 360 x 640
document.body.clientW/H 344 x 325 344 x 318 344 x 310
window.innerW/H 360 x 508 360 x 518 360 x 640
window.outerW/H 720 x 1112 360 x 518 360 x 640
screen.W/H 720 x 1280 360 x 640 360 x 640
UA, scale=1 Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.3 Mobile Safari/537.36 Mozilla/5.0 (Linux; U; Android 4.4.2; zh-CN; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.2.0.880 Mobile Safari/537.36 Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.23 Mobile Safari/537.36
scale = 0.5
document.documentElement.clientW/H 720 x 1016 720 x 1036 720 x 1280
document.body.clientW/H 704 x 325 704 x 318 704 x 310
window.innerW/H 720 x 1016 720 x 1036 720 x 1280
window.outerW/H 720 x 1112 360 x 518 360 x 640
screen.W/H 720 x 1280 360 x 640 360 x 640
UA, scale=0.5 Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.3 Mobile Safari/537.36 Mozilla/5.0 (Linux; U; Android 4.4.2; zh-CN; CHM-UL00 Build/HonorCHM-UL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.2.0.880 Mobile Safari/537.36 Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.23 Mobile Safari/537.36
chrome desktop hongmi 1s UC 11.0.8 hongmi 1s UC 11.2
scale = 1.0
document.documentElement.clientW/H 1920 x 990 360 x 518 360 x 518
document.body.clientW/H 1904 x 310 344 x 316 344 x 318
window.innerW/H 1920 x 990 360 x 518 360 x 518
window.outerW/H 1920 x 1080 720 x 1134 360 x 518
screen.W/H 1920 x 1080 720 x 1280 360 x 640
UA, scale=1 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 Mozilla/5.0 (Linux; U; Android 4.4.4; zh-CN; HM 1S Build/KTU84P) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/11.0.8.858 U3/0.8.0 Mobile Safari/534.30 Mozilla/5.0 (Linux; U; Android 4.4.4; zh-CN; HM 1S Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.2.0.880 Mobile Safari/537.36
scale = 0.5
document.documentElement.clientW/H 1920 x 990 360 x 518 720 x 1036
document.body.clientW/H 1904 x 310 344 x 316 704 x 318
window.innerW/H 1920 x 990 360 x 518 720 x 1036
window.outerW/H 1920 x 1080 720 x 1134 360 x 518
screen.W/H 1920 x 1080 720 x 1280 360 x 640
UA, scale=0.5 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36 Mozilla/5.0 (Linux; U; Android 4.4.4; zh-CN; HM 1S Build/KTU84P) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/11.0.8.858 U3/0.8.0 Mobile Safari/534.30 Mozilla/5.0 (Linux; U; Android 4.4.4; zh-CN; HM 1S Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.2.0.880 Mobile Safari/537.36
iOS 10.1 iPhone5 safari iOS 9.3.4 iPhone6 Safari iOS 10.1 iPhone5 Wechat
scale = 1.0
document.documentElement.clientW/H 320 x 460 375 x 559 320 x 504
document.body.clientW/H 304 x 440 359 x 440 304 x 440
window.innerW/H 640 x 920 375 x 559 320 x 504
window.outerW/H 0 x 0 0 x 0 0 x 0
screen.W/H 320 x 568 375 x 667 320 x 568
UA, scale=1 Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1 Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_4 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13G35 Safari/601.1 Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Mobile/14B100 MicroMessenger/6.3.30 NetType/WIFI Language/zh_CN
scale = 0.5
document.documentElement.clientW/H 640 x 920 750 x 1118 640 x 1008
document.body.clientW/H 624 x 346 734 x 346 624 x 346
window.innerW/H 640 x 920 375 x 559 640 x 1007
window.outerW/H 0 x 0 0 x 0 0 x 0
screen.W/H 320 x 568 375 x 667 320 x 568
UA, scale=0.5 Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1 Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_4 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13G35 Safari/601.1 Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Mobile/14B100 MicroMessenger/6.3.30 NetType/WIFI Language/zh_CN

上表中有一个现象是, iphone5 safari中的小时高度是最小的, 只有460. iphone6 换算为320宽度时, 高度为477.

使用了weinre进行测试. 通过width()函数输出到console, 测试的页面如下:

<!DOCTYPE html>
<html>

<head>
    <title>test</title>
    <meta charset="utf-8">
    <meta id="vp" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <script src="http://192.168.0.143:8888/target/target-script-min.js"></script>
</head>

<body>
    <button style="font-size: 50px" onclick="width()">width</button>
    <script type="text/javascript">
        function changevp(scale) {
            document.getElementById("vp").setAttribute("content", "width=device-width, initial-scale=" + scale + ", maximum-scale=" + scale + ", user-scalable=no")

        }

        function getOutput(scale) {
            return document.documentElement.clientWidth + " x " + document.documentElement.clientHeight + "\t: document.documentElement.clientW/H\n" +
                document.body.clientWidth + " x " + document.body.clientHeight + "\t: document.body.clientW/H\n" +
                window.innerWidth + " x " + window.innerHeight + "\t: window.innerW/H\n" +
                window.outerWidth + " x " + window.outerHeight + "\t: window.outerW/H\n" +
                screen.width + " x " + screen.height + "\t: screen.W/H\n" +
                navigator.userAgent + "\t: UA, scale=" + scale
        }

        function width() {
            var scale = 1
            changevp(scale)
            var str = getOutput(scale)

            console.log(str)
            var scale = 0.5
            changevp(scale)
            var str = getOutput(scale)

            console.log(str)

        }
    </script>
</body>

</html>

1) android chrome浏览器(含微信)

移动浏览器如果是基于chrome的, 比较简单, 以Windows作为调试端,如下:

android端

USB连接android和电脑,
打开chrome,进入网页

调试端

打开chrome, 输入 chrome://inspect
应该可以看到android chrome打开的网页,点击inspect调试

2) IOS safari浏览器

以MAC上的safari作为调试端

IOS端

USB lightning线连接iphone和mac, 点击"信任"此电脑
打开"设置->safari->高级->WEB检查器"
打开safari,进入网页

MAC端

打开safari, 菜单进入并勾选"Safari->偏好设置->高级->在菜单栏显示"开发"菜单"
点击"开发->[你的iphone名称]->开启调试"
再次点击"开发->[你的iphone名称]",应该就能看到IOS上打开的页面,点击对应的页面进行调试

3) 调试任意移动浏览器

主要看这一篇介绍,因为调试android 里面提及到三种不同的方式:

weinre

weinre是在上面方式都无效的情况下, 我比较推荐这一种.
* 使用NPM安装
npm install -g weinre
* weinre可以用命令行加参数运行,不过为了方便起见, 在用户根目录下建立一个配置文件更好(用户根目录,在windows下面可能是是 C:\Users\Username, 在Linux下是~).
建立文件夹.weinre ,建立文件server.properties , 文件内容如下:

boundHost:    -all-
httpPort:     8888
reuseAddr:    true
readTimeout:  1
deathTimeout: 5

释义: boundHost是绑定到的主机,默认是localhost, 不过如果是这样就不能远程访问了. -all-允许一切访问, 也可以改为本机真实ip, httpPort是访问的端口.
命令行运行:
weinre
假如说你的调试端ip是a.b.c.d, 在需要调试的页面插入如下script

在手机端打开http://a.b.c.d:8888 ,先看一下能不能访问. 可以的话, 在手机浏览器打开上面要调试的页面.
在调试端浏览器打开http://a.b.c.d:8888/client ,就可以进行调试了.
需要注意的是, 调试期间, 手机屏幕不能关闭, 否则调试会断掉, 并且在刷新前无法恢复. android手机可以在"设置->辅助功能->开发者选项"中, 打开不锁定屏幕, 并把android手机插上电.

jsconsole.com

这个更简单一些, jsconsole.com这个网站相当于搭建好了调试服务器和客户端. 在被调试端的pages嵌入一段