标签:查询参数 nec 企业 else 列表 查询 注销 roi 允许
做移动开发大多数的时候跟手机界面打交道,也就是说你只能在电脑上开发写代码,最终效果是确是在另外一个终端看到的。虽然各种浏览器为开发者提供了很多模拟手机设备的功能,这些功能总体来说基本可以满足我们对于调试移动设备的需求,但是模拟毕竟是模拟,它不能真正做到实现真机一样的效果。经常遇到在chrome模拟器上样式显示正常,在手机上却出现样式错误的情况,在PC端模拟器运行正常,在真机上却报错的情况。所以,必须在想办法在真实的机子上测试我们的代码最终的执行效果。移动端真机调试有几个刚需:看log、看error信息、看网络请求。其它的如实时修改html/css/javascipt代码, 查看timeline,cookie,localstorage,网络资源和断点调试就不是那么频繁。可以沿着两条思路解决这个问题:第一,自己写一个简单的调试工具,第二:寻找专业的调试工具。
先介绍一下容易理解的移动端调试方法吧,比如自己写一个打印输出的信息框。
/* * 移动端打印 * */ function debug(msg) { msg=new printTree().dump(msg); var div = document.querySelector("#logField"); if (div) { div.innerHTML += msg; } else { div = document.createElement(‘div‘); div.id = "logField"; div.classList.add(‘debug‘); // div.style[‘position‘] = ‘fixed‘; // div.style[‘top‘] = 0; // div.style[‘left‘] = 0; div.style[‘width‘] = ‘100%‘; div.style[‘background-color‘] = ‘rgba(0,0,0,.8)‘; div.style[‘font-size‘] = ‘1.4rem‘; div.style[‘color‘] = ‘yellow‘; div.style[‘word-break‘] = ‘break-all‘; div.style[‘line-height‘] = ‘1.3‘; div.style[‘padding‘] = ‘10px 20px‘; div.innerHTML = msg; var first=document.body.firstChild; document.body.insertBefore(div,first); // document.body.appendChild(div); } }
printTree源代码如下所示:
1 ;(function(window){ 2 3 // Constructor 4 printTree = function (config){ 5 6 config=config ? config : {}; 7 8 this.tabKey= config.tabKey ? config.tabKey : " "; 9 10 }; 11 12 // Prototype 13 printTree.prototype = { 14 15 /** 16 * 17 * Private methods 18 * 19 */ 20 21 /** 22 * [对函数进行格式化处理] 23 * @param {[类型不确定]} obj [数据内容] 24 * @param {[Number]} indent [缩进Tab键数量] 25 * @param {[Boolean]} addComma [是否需要在行尾加逗号] 26 * @param {[Boolean]} isArray [是不是数组] 27 * @param {[Boolean]} isPropertyContent [是不是属性内容] 28 * @return {[String]} print [格式化后的对象字符串] 29 */ 30 _printObject:function(obj, indent, addComma, isArray, isPropertyContent){ 31 32 var print = ""; 33 34 // 是否需要加逗号 35 var comma = (addComma) ? "," : ""; 36 37 // 判断对象类型 38 var type = Object.prototype.toString.call(obj); 39 40 // 数组的处理 41 if( type == "[object Array]"){ 42 43 // 44 if(obj.length == 0){ 45 // isPropertyContent如果为真,说明是属性内容,不用加tab键,否则要在前面加tab键 46 print += this._getRow(indent, "[ ]"+comma, isPropertyContent); 47 48 }else{ 49 50 // 打印数组前面的中括号 51 print += this._getRow(indent, "[", isPropertyContent); 52 53 for(var i = 0; i < obj.length; i++){ 54 // _printObject 数组中可能嵌套这其它对象 55 // indent + 1 每递归一次,加一个缩进符 56 // i < (obj.length - 1) 不是数组的最后一个元素,都要加逗号 57 print += this._printObject(obj[i], indent + 1, i < (obj.length - 1), true, false); 58 59 } 60 61 // 打印数组后面的中括号 62 print += this._getRow(indent, "]"+comma); 63 64 } 65 66 }else if(type == "[object Object]"){ 67 68 if(obj == null){ 69 print += this._formatLiteral("null", "", comma, indent, isArray); 70 } 71 else{ 72 73 var numProps = 0; 74 75 for(var prop in obj) numProps++; 76 77 if(numProps == 0){ 78 79 print += this._getRow(indent, "{ }"+comma, isPropertyContent); 80 81 }else{ 82 83 print += this._getRow(indent, "{", isPropertyContent); 84 85 var j = 0; 86 87 for(var prop in obj){ 88 89 print += this._getRow(indent + 1, prop+‘:‘+this._printObject(obj[prop], indent + 1, ++j < numProps, false, true)); 90 91 } 92 93 print += this._getRow(indent, "}"+comma); 94 95 } 96 } 97 98 }else if(type == "[object Number]"){ 99 100 print += this._formatLiteral(obj,comma,indent, isArray); 101 102 }else if(type == "[object Boolean]"){ 103 104 print += this._formatLiteral(obj, comma, indent, isArray); 105 106 }else if(type == "[object Function]"){ 107 108 obj = this._formatFunction(obj); 109 110 print += this._formatLiteral(obj, comma, indent, isArray); 111 112 }else if(type == "[object Undefined]"){ 113 114 print += this._formatLiteral("undefined",comma, indent, isArray); 115 116 }else{ 117 118 print += this._formatLiteral(obj, comma, indent, isArray); 119 120 } 121 122 return print; 123 124 }, 125 126 /** 127 * [对文本内容进行格式化处理] 128 * @param {[String]} literal [字符内容] 129 * @param {[String]} comma [是否加逗号] 130 * @param {[Number]} indent [缩进的Tab键数量] 131 * @param {[Boolean]} isArray [是否为数组] 132 * @return {[String]} str [格式化后的函数字符串] 133 */ 134 _formatLiteral:function(literal, comma, indent, isArray){ 135 136 var str=literal+comma; 137 138 if(isArray){ 139 str = this._getRow(indent, str); 140 } 141 142 return str; 143 144 }, 145 146 /** 147 * [对函数进行格式化处理] 148 * @param {[Function]} obj [函数内容] 149 * @return {[String]} str [格式化后的函数字符串] 150 */ 151 _formatFunction:function(obj){ 152 153 154 var str = ""; 155 // 以换行符对每行进行分割 156 var funcStrArray = obj.toString().split("\n"); 157 158 if(funcStrArray.length){ 159 160 // 重组每行内容,除末尾行之外,每行加上换行符 161 for(var i = 0; i < funcStrArray.length-1; i++){ 162 str += funcStrArray[i] + "\n"; 163 } 164 return str+funcStrArray[i]; 165 }else{ 166 return str; 167 } 168 169 }, 170 171 172 /** 173 * [给每行加上缩进和换行] 174 * @param {[Number]} indent [每行需要缩进的TAB数量] 175 * @param {[String]} data [属性名] 176 * @param {[Boolean]} isPropertyContent [是否为属性内容] 177 * @return {[String]} tabs+data [格式化后的行内容] 178 */ 179 _getRow:function(indent, data, isPropertyContent){ 180 181 var tabs = ""; 182 183 // 计算属性名称前面的tab键数量 184 for(var i = 0; i < indent && !isPropertyContent; i++){ 185 tabs += this.tabKey; 186 } 187 188 // 给属性名加上换行(内容不为空且末尾不含换行符) 189 if(data != null && data.length > 0 && data.charAt(data.length-1) != "\n"){ 190 data = data+"\n"; 191 } 192 193 return tabs+data; 194 195 }, 196 /** 197 * 198 * Public methods 199 * 200 */ 201 dump:function(object){ 202 203 try{ 204 return this._printObject(object, 0, false, false, false) ; 205 }catch(e){ 206 alert("object语法错误,不能格式化,错误信息:\n"+e.message); 207 } 208 209 }, 210 211 }; 212 213 if (typeof exports !== ‘undefined‘){ 214 exports.printTree = printTree; 215 }else{ 216 window.printTree = printTree; 217 } 218 219 })(window);
这个方法有个缺点是无法打印[HTML DOM Element],
比如一个实际的DOM 元素为
<input type="email" name="email" id="email" placeholder="请输入企业邮箱账号">
通过上述方式打印出来的效果为图2所示。类似的工具还有vconsole
安装方法
npm install vconsole
使用方法---在需要调试的页面引入下面的js文件
<script src="path/to/vconsole.min.js"></script>
<script>
console.log(‘Hello world‘);
</script>
这个工具的实现原理,是很简单的函数劫持。其大概原理是创建一个和现有函数同名的函数(当然首先要把原来的函数给保存下来),以覆盖掉他原本的引用,然后在函数体内先针对参数做一些自己想要实现的功能,最后再调用之前保存的原函数,实现原本的功能。
vconsole工具重写了window.XMLHttpRequest和window.console方法
使用专业的工具
weinre全称是web insperctor remote,是一种远程调试工具,可以在PC上调试运行在移动设备上的远程页面。
Weinre 是一个相当简单好用的调试工具。它会在你本地创建一个监听服务器,并提供一个 JavaScript脚本,你只需要在需要测试的页面中加载这段 JS,就可以被 Weinre 监听到,在 inspect 面板中调试你这个页面。
如上图, Weinre由三部分组成,第一部分是运行在PC上的Debug Server, 它会与其他两部分交互,在测试页引入的那个target.js文件就存在于这个Server里
?第二部分是Debug Client, 这个就是我们上面一直在使用的运行在chrome中的调试客户端,它与Debug Server进行连接,并提供调试接口给用户。
?第三部分是Debug Target, 也就是运行在我们远程设备浏览器中的target.js, 它通过XHR与Server连接交互,将我们的代码暴露给Server, 来实现DOM Inspection与修改。
在命令行启动weinre就开启了Debug Server, 然后在浏览器中输入http://ip:weinre端口就打开了Debug Client, 在调试页面中嵌入target.js代码, 在手机中打开页面, 就开启Debug Target。
weinre 的具体使用方法如下:
首先全局安装 weinre:
npm install -g weinre
安装完成之后,在命令行下启动weinre监听服务器,启动监听服务器之前,需要获取本机的局域网地址:
ipconfig getifaddr en0
命令。ipconfig
命令。这时候拿到本机IP,比如我的机器IP 为 192.168.201.54,这时候执行:
weinre --boundHost 192.168.201.54 --httpPort 10000
weinre支持的参数有:
--help : 显示Weinre的Help
--httpPort [portNumber] : 设置Weinre使用的端口号, 默认是8080
--boundHost [hostname | ip address | -all-] : 默认是‘localhost‘, 这个参数是为了限制可以访问Weinre Server的设备, 设置为-all-或者指定ip, 那么任何设备都可以访问Weinre Server。
--verbose [true | false] : 如果想看到更多的关于Weinre运行情况的输出, 那么可以设置这个选项为true, 默认为false;
--debug [true | false] : 这个选项与--verbose类似, 会输出更多的信息。默认为false。
--readTimeout [seconds] : Server发送信息到Target/Client的超时时间, 默认为5s。
--deathTimeout [seconds] : 默认为3倍的readTimeout, 如果页面超过这个时间都没有任何响应, 那么就会断开连接。
开启本地监听服务器
复制http://192.168.201.54:10000,粘贴到浏览器地址栏,打开服务器网址,
复制监听脚本到需要被监听页面
当我们有真机访问被调试页面的时候,被调试页面就会出现在监听列表中,如果有多个网页,你可以从列表中选择一个。然后就可以使用后面的 Elements、Console 等面板来进行调试操作了:
首页RemoteTab由三部分组成, Targets是注册的远程设备列表, 当前我们还没有访问测试页面, 所以Targets列表为none, Clients是Weinre客户端, 也即打开这个Weinre页面的设备列表。ServerProperties就是我们运行Weinre时的一些配置项。
weinre 非常灵活,跨平台(Android、iOS 、Window Phone 都支持),跨浏览器(chrome,safari,国内各种浏览器都可以用), 可以让我们在电脑上直接调试运行在手机上的远程页面。在调试移动设备时需要在本地搭建一个局域网 IP 的服务器,将设备与本机网络连接成一个局域网,用移动设备访问这个网页即可。当然 Weinre 也不是万能的,相比 Chrome 的调试工具,它缺少 JavaScript 断点以及 Profiles 等常用功能,但是它兼容性强,可以实现基础调试功能。
weinre兼容性挺强,而且能支持微信端页面的调试,到此为止,如果页面请求使用的是http,那weinre已经可以解决调试问题了。
但是如果要调试https请求的页面,仅仅使用weinre无法解决,因为在页面中需要引入调试的js文件,weinre启动的是http服务,于是使用反向代理软件ngrok,它可以做地址映射,并支持http/https/tcp等,使用也比较简单:
这是官网下载地址:https://ngrok.com/download,或者可以直接使用npm下载:
npm install -g ngrok
然后启动
ngrok http 192.168.201.54:9999
启动后可以打开 http://127.0.0.1:4040 查看连接信息:
在html中引入下面的js文件
注意:
1.绑定端口一定不能与本地环境已监听的端口冲突。本地我已监听了8080端口,所以我绑定的是10000端口。
2.boundHost默认为localhost,只能本地PC上用http://localhost:8080来访问,将localhost换做本地ip就无法打开Weinre调试工具,为了能在其他设备以及本地设备用ip打开Weinre调试工具,需要设置boundHost为"-all-"或者ip.
3.监听https页面时,要先启动weinre,再启动ngrok.
JSConsole相当于一个简化版的weinre,专注于console功能,它相对于Weinre的优点就是提供了现成了线上Debug Server与Debug Client, 无需用户在PC本地运行Debug服务, 只要在需要调试的页面像Weinre一样加入一个target库, 就可以在JSConsole官网上调试这个页面了。JSConsole的网址为https://jsconsole.com/。
接着在打开的网页输入 :listen
,将会得到一串 GUID 以及一对带有 src 属性的 Javascript 标签,如下图:
将这个 Javascript 脚本插入到需要调试的 html 页面中,比如这样:
复制代码<script src="http://jsconsole.com/remote.js?BDA15940-A201-4EAB-9482-941CD41742EC"></script>
<script>
var a = 1
, b = 2;
console.log(a + b);
</script>
然后刷新你本地需要调试的页面(PC端或者移动端),如果是第一次打开的话,会弹出下图内容,大概意思就是告诉你现在引入了 JSConsole 的一段 js 进行调试,记得在上线时将它移除。
在打开 JSConsole 的页面便会输出 console 的内容;如果页面 JS 报错,一般情况下也能在 JSConsole 中进行定位。
需要注意的是,刷新的是本地页面,而并不是 JSConsole 的页面,一旦刷新 JSConsole 的页面,便会生成一个新的 GUID,这样之前生成的就没用了,调试也就失效了
1、一站式页面调试工具,远程调试任何手机浏览器页面,任何手机移动端webview(如:微信,HybirdApp,手机浏览器等)。 2、spy-debugger内部集成了weinre。 3、同时支持HTTP/HTTPS页面的调试。
安装
Windows 下
npm install spy-debugger -g
Mac 下
sudo npm install spy-debugger -g
安装后在命令行下输入 spy-debugger,启动代理服务器
设置手机代理
如果要监听https页面,你还需要做如下操作:
第一步:生成证书
spy-debugger initCA
// 证书生成在用户根目录的node-mitmproxy文件夹下的
// 如: /Users/wuchangming/node-mitmproxy
第二步:安装证书
把node-mitmproxy文件夹下的 node-mitmproxy.ca.crt 传到手机上,点击安装即可。
Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,分析请求数据、设置断点、调试web应用、修改请求的数据,甚至可以修改服务器返回的数据. 使用Fiddler无论对开发还是测试来说,都有很大的帮助。
Fiddler 是以代理web服务器的形式工作的,它是在web server 和 client 之间搭了一层 proxy,所有的请求都会经过它。在打开它的那一瞬间,它就已经设置好了浏览器的代理了。它使用代理地址:127.0.0.1, 端口:8888.当你关闭的时候,它会自动注销代理服务,不过如果Fiddler非正常退出,会造成网页无法访问。 这是因为Fiddler没有自动注销,解决的办法是重新启动下Fiddler..
每种图标代表不同的相应类型,具体的类型包括:
Inspectors tab下有很多查看Request或者Response的消息。分为上下两个部分,上半部分是请求头部分,下半部分是响应头部分。对于每一部分,提供了多种不同格式查看每个请求和响应的内容。
JPG 格式使用 ImageView 就可以看到图片,
HTML/JS/CSS 使用 TextView 可以看到响应的内容。
其中Raw Tab可以查看完整的消息,
Headers tab 只查看消息中的header.
Auth则可以查看授权Proxy-Authorization 和 Authorization的相关信息。
Cookies标签可以看到请求的cookie和响应的set-cookie头信息。
默认情况下,fiddler是不会捕获https会话的,所以需要自行设置下。启动软件,点击tools->Fiddler Options,在弹出框选择“HTTPS”,如下页面,将捕获HTTPS连接这一项前面全打钩,点击ok即可操作成功。
Tools --> Telerik Fiddler Options --> 选择https,这个面板的配置项有:
Capture HTTPS CONNECTs:捕获https连接
Decrypt HTTPS traffic:解密HTTPS通信
Ignore servercertificate errors:忽略服务器证书错误
Fiddler最强大的功能莫过于设置断点了,设置好断点后,你可以修改httpRequest 的任何信息包括host, cookie或者表单中的数据。设置断点有两种方法
第一种:打开Fiddler 点击Rules-> Automatic Breakpoint ->Before Requests(这种方法会中断所有的会话)
如何消除命令呢? 点击Rules-> Automatic Breakpoint ->Disabled
第二种: 在命令行中输入命令: bpu www.baidu.com (这种方法只会中断www.baidu.com)
如何消除命令呢? 在命令行中输入命令 bpu
当然Fiddler中也能修改Response
第一种:打开Fiddler 点击Rules-> Automatic Breakpoint ->After Response (这种方法会中断所有的会话)
如何消除命令呢? 点击Rules-> Automatic Breakpoint ->Disabled
第二种: 在命令行中输入命令: bpafter www.baidu.com (这种方法只会中断www.baidu.com)
如何消除命令呢? 在命令行中输入命令 bpafter,
Fiddler比较重要且比较强大的功能之一。可用于拦截某一请求,并重定向到本地的资源,或者使用Fiddler的内置响应。可用于调试服务器端代码而无需修改服务器端的代码和配置,因为拦截和重定向后,实际上访问的是本地的文件或者得到的是Fiddler的内置响应。当勾选allow autoresponser 并设置相应的规则后(本例中的规则是将http://blog.csdn.net/ohmygirl的请求拦截到本地的文件layout.html),如下图所示
因此,如果要调试服务器的某个脚本文件,可以将该脚本拦截到本地,在本地修改完脚本之后,再修改服务器端的内容,这可以保证,尽量在真实的环境下去调试,从而最大限度的减少bug发生的可能性。
不仅是单个url,Fiddler支持多种url匹配的方式:
I. 字符匹配
如 example可以匹配 http://www.example.com和http://example.com.cn
II. 完全匹配
以EXACT开头表示完全匹配,如上边的例子
EXACT:http://blog.csdn.net/ohmygirl
III. 正则表达式匹配
以regex: 开头,使用正则表达式来匹配URL
如:regex:(?insx).*\.(css|js|php)$ 表示匹配所有以css,js,php结尾的请求url
老版本的fiddler中叫request-builder.顾名思义,可以构建相应的请求,有两种常用的方式构建请求:
(1)Parsed 输入请求的url之后executed即可,也可以修改相应的头信息(如添加常用的accept, host, referrer, cookie,cache-control等头部)后execute.
这个功能的常见应用是刷新页面的访问量
(2)Raw。使用HTTP头部信息构建http请求。与上类似。不多叙述
Fiddler的左下角有一个命令行工具叫做QuickExec,允许你直接输入命令。
常见得命令有
help 打开官方的使用页面介绍,所有的命令都会列出来 http://docs.telerik.com/fiddler/knowledgebase/quickexec
cls 清屏 (Ctrl+x 也可以清屏) select 选择会话的命令 ?.png 用来选择png后缀的图片 bpu 截获request
通过陈列出所有的HTTP通信量,Fiddler可以很容易的向您展示哪些文件生成了您当前请求的页面。使用Statistics页签,用户可以通过选择多个会话来得来这几个会话的总的信息统计,比如多个请求和传输的字节数。
选择第一个请求和最后一个请求,可获得整个页面加载所消耗的总体时间。从条形图表中还可以分别出哪些请求耗时最多,从而对页面的访问进行访问速度优化
第一个选项zone有三种选择:no zone;仅显示局域网主机;仅显示互联网主机;
第二个选项Host有四种选择,可以在下面文本框输入内容,根据输入内容显示或不显示相应的主机;
“No Host Filter”不设置hosts过滤
“Hide The Following Hosts”隐藏过滤到的域名
“Show Only The Following Hosts”只显示过滤到的域名
“Flag The Following Hosts”标记过滤到的域名
Action按钮可以保存过滤规则集,载入过滤规则集等;
可以选择仅显示来自某些进程的流量;仅显示chrome流量;
仅显示包含某些字符的URL;隐藏包含某些字符的URL;显示头部包含某些标志的包;
还可以删除和设置请求头;此功能尚未用过;待用过之后再发文详述;
在post时中断请求;
在带查询参数的GET请求时中断;
在异步请求时中断;
获取到某种类型的响应时中断;
隐藏成功的包;
隐藏不成功的包;
2字头的状态码,代表请求已成功被服务器接收、理解、并接受;
隐藏需要用户验证的请求;
隐藏重定向请求;
默认显示全部类型;其他还有image,html,texe/css,scripts等类型;
捕获设置了cookie的响应头;
捕获响应头带某些字符串的包等;
HTTP抓包分析工具有比较多,如wireshark, FireBug,HttpWatch,Tcpdump,PAW(mac)等。在做移动端开发时,找到一款合适自己的能进行移动设备HTTP抓包的工具也是非常重要的。正所谓,工欲善其事必先利其器。
个人非常喜欢Fiddler和spy-debugger,功能强大,简单易用。
标签:查询参数 nec 企业 else 列表 查询 注销 roi 允许
原文地址:http://www.cnblogs.com/wangpenghui522/p/7190400.html