-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
337 lines (238 loc) · 210 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title></title>
<url>http://yoursite.com/2016/12/29/vue_problem/</url>
<content type="text"><![CDATA[vue vuex vue-resource vue-router 都有版本的升级因此遇到问题,确认使用的方法是否与版本对应,免得踩坑。。。1.端口号的问题2.vue-router 2.0改变的内容1234路由跳转 this.$route.router.go({name:"list"}); 改为 $this.$router.push('/list') 3.vue2.0废弃dispatch4.$index 现在必须使用 index 了(在 v-for 中显示声明)123<ul class='agent-otherhouse-list'> <li v-for='(house,index) in houseData' v-cloak v-on:mouseover='hoverShow(index)' :class="{'on':indexPage==index}"> </li></ul> 5.]]></content>
</entry>
<entry>
<title><![CDATA[vue之组件之间的通信]]></title>
<url>http://yoursite.com/2016/12/26/vue_communicate/</url>
<content type="text"><![CDATA[组件之间的通信 propscamelCase-vs-kebab-caseHTML 特性不区分大小写。当使用非字符串模版时,prop的名字形式会从 camelCase 转为 kebab-case(短横线隔开)App.vue kebab-case in HTMLrender_demo1.vue camelCase in JavaScript再次说明,如果你使用字符串模版,不用在意这些限制。举例App.vuerender_demo1.vue]]></content>
</entry>
<entry>
<title><![CDATA[gulp使用流程]]></title>
<url>http://yoursite.com/2016/12/23/gulp/</url>
<content type="text"><![CDATA[在使用gulp的时候,通常我们想把别人配置好的文件拿过来用,而不是自己重新配置,那么这个时候怎么快速搭建呢? gulp官网 需要什么? 首先默认你已经安装了node 环境 package.json gulpfile.jsnote:上边的两个文件是别人已经配置好的文件https://github.com/hello-sunbaixin/gulp-practice 这里存放了我已经配置好的文件 开始构建1.新建一个文件夹(任意位置)例如:work-gulp(以下所有git命令都在该文件夹下进行)2.进入文件夹,将package.json,gulpfile.js复制进去3.在work-gulp文件夹下,运行npm install 或npm install –save-dev 自动将package.json中的模块安装到node-modules文件夹下运行结束会产生node_modules文件夹,这里放着所有依赖的模块4.在work-gulp文件夹下,新建一个文件夹用于开发(例如demo)然后更改gulpfile.js,换成当前的开发目录5.在work-gulp文件夹下,执行gulp init命令(gulpfile.js可以配置好,用于初始化文件,如果没有,则需要手动新建开发)note:src下进行css img js的开发 html存放模板6.在对应目录建开发文件,如图7.运行gulp g-dist 将开发文件导入dist中,页面引用的路径都是dist下的note:dist文件夹内存放的是编译好的文件(scss已经转换成css,压缩或者代码检错等等),rev存放css js img 路径的配置信息8.运行gulp default或者gulp 可以直接在浏览器上看到效果,liveload即改即刷新9.开发结束 运行gulp rev 是将dist文件夹内的所有文件引用资源的相对路径改成上线路径,放到online文件夹内10.效果图11.上述是所有的配置过程,下次再开发的时候,直接用相同的步骤(从4开始,新建开发目录即可) 注解package.json这里我们可以看到package.json中,有文件名,版本号,项目描述,项目主文件,全局依赖,项目依赖模块,脚本scripts等组成部分,其中,我们现在需要明白的一个地方是其中的dependencies和devDevpendenies区别,前者是你生产环境需要依赖的库,后者是你开发时候用的库,比如测试库,测试服务器之类的,在真实生产环境是不需要的,如果我们使用了构架工具,例如gulp之类的,打包的时候,是不会将dev库打包进去的]]></content>
</entry>
<entry>
<title><![CDATA[vue的学习之路(适用于小白)]]></title>
<url>http://yoursite.com/2016/12/21/vue_learn/</url>
<content type="text"><![CDATA[作为vue 学习的小白,有必要知道快速入门,需要学习什么或者看哪些内容 vue官网vue源码解析http://blog.cgsdream.org/2016/11/05/vue-source-analysis-1/ 学习教程http://www.jb51.net/Special/874.htm 功能模块划分功能模块页面区域App.vue项目的入口import from 省略后缀 es6语法components 注册组件http://jiongks.name/blog/just-vue/http://blog.csdn.net/tencent_bugly/article/details/52512287https://segmentfault.com/a/1190000006000118http://blog.csdn.net/yolo0927/article/details/53464721http://www.cnblogs.com/jiangxiaobo/p/5425048.htmlvue2.0新手踩坑http://www.jianshu.com/p/5ba253651c3bvue+vue-route+vuexhttp://www.cnblogs.com/ychl/p/6122104.htmlvue-router 2.0改变的内容 https://cwsjoker.github.io/mystatic/CNode_Vue_Spa/index.html#!/artlist]]></content>
</entry>
<entry>
<title><![CDATA[浏览器的渲染]]></title>
<url>http://yoursite.com/2016/12/17/bower_rendering/</url>
<content type="text"><![CDATA[浏览器渲染过程http://www.cnblogs.com/jhmydear/p/4540807.htmlhttp://coolshell.cn/articles/9666.html]]></content>
</entry>
<entry>
<title><![CDATA[常用原生js兼容性写法]]></title>
<url>http://yoursite.com/2016/12/08/compatibility/</url>
<content type="text"><![CDATA[> ①添加事件方法123456789addHandler:function(element,type,handler){ if(element.addEventListener){//检测是否为DOM2级方法 element.addEventListener(type, handler, false); }else if (element.attachEvent){//检测是否为IE级方法 element.attachEvent("on" + type, handler); } else {//检测是否为DOM0级方法 element["on" + type] = handler; }} ②移除之前添加的事件方法123456789removeHandler:function(element, type, handler){ if (element.removeEventListener){ element.removeEventListener(type, handler, false); } else if (element.detachEvent){ element.detachEvent("on" + type, handler); } else { element["on" + type] = null; } } ③获取事件及事件对象目标12345678//获取事件对象的兼容性写法 getEvent: function(event){ return event ? event : window.event; }, //获取事件对象目标的兼容性写法 getTarget: function(event){ return event.target || event.srcElement; } ④阻止浏览器默认事件的兼容性写法1234567preventDefault: function(event){ if (event.preventDefault){ event.preventDefault(); } else { event.returnValue = false; } } ⑤阻止事件冒泡的兼容性写法1234567stopPropagation: function(event){ if (event.stopPropagation){ event.stopPropagation(); } else { event.cancelBubble = true; } } ⑥mouseover和mouseout 事件才包含的获取相关元素的方法123456789101112//mouseover和mouseout 事件才包含的获取相关元素的方法getRelatedTarget: function(event){ if (event.relatedTarget){ return event.relatedTarget; } else if (event.toElement){ return event.toElement; } else if (event.fromElement){ return event.fromElement; } else { return null; }} ⑦鼠标滚轮判断对于mousedown 和mouseup 事件来说,则在其event 对象存在一个button 属性,表示按下或释放的按钮。DOM的button 属性可能有如下3 个值:0 表示主鼠标按钮,1 表示中间的鼠标按钮(鼠标滚轮按钮),2 表示次鼠标按钮。在常规的设置中,主鼠标按钮就是鼠标左键,而次鼠标按钮就是鼠标右键。IE8 及之前版本也提供了button 属性,但这个属性的值与DOM 的button 属性有很大差异。 0:表示没有按下按钮。 1:表示按下了主鼠标按钮。 2:表示按下了次鼠标按钮。 3:表示同时按下了主、次鼠标按钮。 4:表示按下了中间的鼠标按钮。 5:表示同时按下了主鼠标按钮和中间的鼠标按钮。 6:表示同时按下了次鼠标按钮和中间的鼠标按钮。 7:表示同时按下了三个鼠标按钮。12345678910111213141516171819getButton: function(event){ if (document.implementation.hasFeature("MouseEvents", "2.0")){ return event.button; } else { switch(event.button){ case 0: case 1: case 3: case 5: case 7: return 0; case 2: case 6: return 2; case 4: return 1; } }} ⑧能够取得鼠标滚轮增量值(delta)的方法12345678getWheelDelta: function(event){ if (event.wheelDelta){ return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta); } else { return -event.detail * 40;//firefox中的值为+3表示向上滚,-3表示向下滚 }} ⑨跨浏览器的方式取得字符编码1234567getCharCode: function(event){ if (typeof event.charCode == "number"){ return event.charCode; } else { return event.keyCode; }} ⑩访问剪贴板中的数据1234getClipboardText: function(event){ var clipboardData = (event.clipboardData || window.clipboardData); return clipboardData.getData("text"); } 11.设置剪贴板中的数据123456setClipboardText: function(event, value){ if (event.clipboardData){ return event.clipboardData.setData("text/plain", value); } else if (window.clipboardData){ return window.clipboardData.setData("text", value); }]]></content>
</entry>
<entry>
<title><![CDATA[事件代理(事件委托)]]></title>
<url>http://yoursite.com/2016/12/07/event_delegate/</url>
<content type="text"><![CDATA[事件代理:绑定在祖先元素上的事件处理函数可以对在后代上触发的事件作出回应,利用的就是冒泡的原理 我们常用的代理方法是on,而所有其他的代理方法都是对on方法的进一步封装,看源码即知]]></content>
</entry>
<entry>
<title><![CDATA[new RegExp()]]></title>
<url>http://yoursite.com/2016/12/06/regexp/</url>
<content type="text"><![CDATA[正则表达式描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。 RegExp对象 Note:exec 是 RegExp 对象的方法;math 是 String 对象的方法。二者还有一个不同点,就是对参数 g 的解释。 test、match、exec方法区别 使用 返回值 test reg.test(str) true/false match str.macth(reg) 返回第一个匹配到的值,如果指定了参数 g,那么 match 一次返回所有的结果。 exec reg.exec(str) 如果不匹配就返回null,否则总是返回长度为1的数组,如果指定了匹配模式g,则下次调用 exec 时,会从上个匹配的 lastIndex 开始查找 例子test1234var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";var regexp = /[A-E]/gi;var rs = regexp.test(str);//true match1234var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";var regexp = /[A-E]/gi;var rs = str.match(regexp);//["A", "B", "C", "D", "E", "a", "b", "c", "d", "e"] exec1234567891011121314151617181920var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";var regexp = /[A-E]/gi;var rs;while ((rs = regexp.exec(str)) != null){ document.write(rs); document.write(regexp.lastIndex); document.write("<br />");}//每次只返回一个数组,A1B2C3D4E5a27b28c29d30e31 replace12str.replace(str)str.replace(reg)]]></content>
</entry>
<entry>
<title><![CDATA[break和continue]]></title>
<url>http://yoursite.com/2016/12/05/break_continue/</url>
<content type="text"><![CDATA[break和continue使用区别 breakbreak在循环中的功能是跳出当前循环。break语句跳出当前循环,break后面的所有语句都不再执行,跳出for循环。注意跳出的是距离此break语句最近的循环。123456789for(var i=0;i<5;i++){ for(var j=0;j<5;j++){ if(j==2){ break; } console.log(j) } } } 结果: continuecontinue的功能是结束本次循环跳到下一次循环。123456789for(var i=0;i<5;i++){ for(var j=0;j<5;j++){ if(j==2){ continue; } console.log(j) } } } 二者都作用的是当前循环,对于嵌套循环,如果这两者在内部循环中则只作用于内部循环。]]></content>
</entry>
<entry>
<title><![CDATA[jQuery源码]]></title>
<url>http://yoursite.com/2016/12/05/jquery/</url>
<content type="text"><![CDATA[]]></content>
</entry>
<entry>
<title><![CDATA[svn的使用]]></title>
<url>http://yoursite.com/2016/11/26/svn/</url>
<content type="text"><![CDATA[svn的使用 SVN1、 基本介绍SVN,即Subversion,是一个自由开源的版本控制系统,可以将代码恢复到早期版本,或者检查数据修改的历史,这些数据可以是源代码,也可以是其他类型的文件。功能:(1) 根据文件修改的次数自动增加版本号以便找回历史文件(2) 防止多人开发时同时修改一类文件导致覆盖或者被删除 常见图标:(1) 对号:版本正常(2) 感叹号:从服务器同步后有修改但是还没有上传到服务器(3) 问号:新建了一个文件但是服务器还不认识他(4) 加号:已经添加到观察名单但是还没上传到服务器(5) 锁:加锁2、 服务器/客户端搭建步骤服务器端搭建(1) 在E盘新建空文件夹SVN_Server(2) 右击->TortoiseSVN->Create repository here(创建版本库)(3) 进入conf文件夹,打开passwd,加上liupeng = liupeng(4) 打开svnserve.conf,将# password-db = passwd前的空格和#号删除,保存(5) 打开服务,启动dos,输入svnserve.exe -d -r E:\SVN_Server 客户端搭建(可以直接使用下载文件的步骤)(6) 在F盘新建空文件夹SVN_Client(7) 右击-> TortoiseSVN->Repo-Brower(8) 弹出框,输入svn://127.0.0.1,确定(9) 右击->SVN Checkout->OK SVN上传文件(10) 拷入三个文件1、2、3.txt(11) 右击1.txt-> TortoiseSVN->Add(12) 右击1.txt->SVN Commit…->确定(如果修改了1.txt,再重新执行commit即可)(11、12步骤可以该为在空白处直接SVN Commit,选择需要提交的文件) SVN下载文件(13) 在F盘新建空文件夹SVN_Client(14) 右击->SVN Checkout->OK(协议那栏注意不加文件名称)(15) 第二次下载的时候就叫做SVN Update 3、 客户端1、文件删除 (1)删除一个文件 (2)提交 (选择删除的文件)2、历史版本的找回 (1)右击-> TortoiseSVN->Update to revision… (2)弹出框选择第二个Revision,写上想要回到的版本号,确定3、历史版本间差异的对比 (1)client1中down一个文件并且修改提交 (2)client2中同样down这个文件并且修改提交 (3)在回到client1中更新这个文件 (4)选择文件,右击-> TortoiseSVN->Diff with previsious version3、冲突解决 (1)client1和client2中存在版本号一样的相同文件 (2)同时对其进行更改,client1先提交 (3)client2再提交,会出现问题 (4)此时应该先将client2进行update,生成一堆 (5)右击client2中的冲突文件-> TortoiseSVN->Edit Conflicts-<右击修改 (6)右击client2中的冲突文件-> TortoiseSVN->Resolved->commit (7)回到client1中更新即可 4、 服务器端1、 将启动SVN服务加到自启动中sc create svnserve binpath= “D:\Program Files\Subversion\bin\svnserve.exe” –service –root E:\SVN_Server 2、 取消记住用户名进入C:\Users\liupeng\AppData\Roaming\Subversion,删除auth文件夹即可 3、 权限控制1、默认情况下匿名用户也可以浏览并且下载服务器端的东西,进入E:\SVN_Server\conf里面,打开svnserve.conf,将anon-access前的空格和#号删除,并且将参数改为none 2、(1)进入E:\SVN_Server\conf\svnserve.conf,将authz-db前的空格和#删除(2)打开E:\SVN_Server\conf\authz,加入红色部分[groups]admin = liupeng harry_and_sally = harry,sallyharry_sally_and_joe = harry,sally,&joe[/]@admin = rwpbj = rw = r]]></content>
</entry>
<entry>
<title><![CDATA[浅谈touch事件]]></title>
<url>http://yoursite.com/2016/11/25/touch/</url>
<content type="text"><![CDATA[HTML5触摸事件(touchstart,touchmove,touchend) 常常在移动端滑动翻页时会用到,所以小总一下 touch事件 touchstart:当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发。 touchmove:当手指在屏幕上滑动时连续的触发。在这个事件发生期间,调用preventDefault()可阻止滚动。 touchend:当手指从屏幕上移开时触发。 touchcancel:当系统停止跟踪触摸时触发。关于此事件的确切触发事件,文档中没有明确说明。 12345678910111213141516171819202122232425function load (){ document.addEventListener('touchstart',touch, false); document.addEventListener('touchmove',touch, false); document.addEventListener('touchend',touch, false); function touch (event){ var event = event || window.event; var oInp = document.getElementById("inp"); switch(event.type){ case "touchstart": oInp.innerHTML = "Touch started (" + event.touches[0].clientX + "," + event.touches[0].clientY + ")"; break; case "touchend": oInp.innerHTML = "<br>Touch end (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")"; break; case "touchmove": event.preventDefault(); oInp.innerHTML = "<br>Touch moved (" + event.touches[0].clientX + "," + event.touches[0].clientY + ")"; break; } }}window.addEventListener('load',load, false); 每个touch事件event对象都提供需要的属性 – – touches: 表示当前跟踪的触摸操作的touch对象的数组。 targetTouches: 特定于事件目标的Touch对象的数组。 changeTouches: 表示自上次触摸以来发生了什么改变的Touch对象的数组。 – – clientX: 触摸目标在视口中的x坐标。 clientY: 触摸目标在视口中的y坐标。 identifier: 标识触摸的唯一ID。 pageX: 触摸目标在页面中的x坐标。 pageY: 触摸目标在页面中的y坐标。 screenX: 触摸目标在屏幕中的x坐标。 screenY: 触摸目标在屏幕中的y坐标。 target: 触目的DOM节点目标。 最佳做法阻止缩放缺省的多点触摸设置不是特别的好用,因为你的滑动和手势往往与浏览器的行为有关联,比如说滚动和缩放。要禁用缩放功能的话,使用下面的元标记设置你的视图区(viewport),这样其对于用户来说就是不可伸缩的了:1content="width=device-width, initial-scale=1.0, user-scalable=no"> 看看这篇关于移动HTML 5的文章,了解更多关于视图区设置的信息。阻止滚动一些移动设备有缺省的touchmove行为,比如说经典的iOS overscroll效果,当滚动超出了内容的界限时就引发视图反弹。这种做法在许多多点触控应用中会带来混乱,但要禁用它很容易。123document.body.addEventListener('touchmove', function(event) { event.preventDefault();}, false);]]></content>
</entry>
<entry>
<title><![CDATA[position]]></title>
<url>http://yoursite.com/2016/11/24/position/</url>
<content type="text"><![CDATA[position是前端经常会用到的样式,但是position属性的各个值都是相对于什么定位的,常常会有人搞混甚至是不清楚,所以有必要总结一下 参数 图解relativerelative相对于正常位置定位的12345678910111213141516171819202122<style> .top,.bottom{ width:200px; height:150px; } .top{ background:#c85e7c; } .bottom{ background:#c18401; } .positionEle{ border:1px solid #000; position:relative; top:40px; left:10px; }</style><div class="top">1.正常流</div><div class="bottom">2. <div class="positionEle">3.查看position属性的各个值相对于什么定位</div></div> absoluteabsolute是相对于离它最近的具有定位属性(除了static)的祖代元素开始定位的,如果祖代元素没有定位属性,则相对于浏览器窗口case1:相对于浏览器窗口1234567891011121314151617181920212223 <style> .top,.bottom{ width:200px; height:150px; } .top{ margin-top:60px; background:#c85e7c; } .bottom{ background:#c18401; } .positionEle{ border:1px solid #000; position:absolute; top:40px; left:10px; } </style><div class="top">1.正常流</div><div class="bottom">2. <div class="positionEle">3.查看position属性的各个值相对于什么定位</div></div> case2:相对于具有定位属性的父元素1234567891011121314151617181920212223242526 <style> .top,.bottom{ width:200px; height:150px; } .top{ background:#c85e7c; } .bottom{ position:relative; background:#c18401; } .positionEle{ border:1px solid #000; position:absolute; top:40px; left:10px; } </style></head><body><div class="top">1.正常流</div><div class="bottom">2. <div class="positionEle">3.查看position属性的各个值相对于什么定位</div></div> fixed生成绝对定位的元素,相对于浏览器窗口进行定位。不论祖代元素是否定位123456789101112131415161718192021222324 <style> .top,.bottom{ width:200px; height:150px; } .top{ background:#c85e7c; } .bottom{ position:relative; background:#c18401; } .positionEle{ border:1px solid #000; position:fixed; top:40px; left:10px; } </style><div class="top">1.正常流</div><div class="bottom">2. <div class="positionEle">3.查看position属性的各个值相对于什么定位</div></div>]]></content>
</entry>
<entry>
<title><![CDATA[display:inline inline-block block几种方法]]></title>
<url>http://yoursite.com/2016/11/23/inline/</url>
<content type="text"><![CDATA[inline inline-block block区分这几种属性的使用 一、display:block就是将元素显示为块级元素.block元素的特点是: 总是在新行上开始; 高度,行高以及顶和底边距都可控制; 宽度缺省是它的容器的100%,除非设定一个宽度1<div>, <p>, <h1>, <form>, <ul> 和 <li>是块元素的例子。 二、display:inline就是将元素显示为行内元素.inline元素的特点是: 和其他元素都在一行上; 高,行高及顶和底边距不可改变; 宽度就是它的文字或图片的宽度,不可改变。1<span>, <a>, <label>, <input>, <img>, <strong> 和<em>是inline元素的例子。 inline像block可以控制一个元素的行宽高等特性,需要切换的情况如下: 让一个inline元素从新行开始; 让块元素和其他元素保持在一行上; 控制inline元素的宽度(对导航条特别有用); 控制inline元素的高度; 无须设定宽度即可为一个块元素设定与文字同宽的背景色。 三、display:inline-block将对象呈递为内联对象,但是对象的内容作为块对象呈递。旁边的内联对象会被呈递在同一行内,允许空格。inline-block的元素特点:将对象呈递为内联对象,但是对象的内容作为块对象呈递。旁边的内联对象会被呈递在同一行内,允许空格。(准确地说,应用此特性的元素呈现为内联对象,周围元素保持在同一行,但可以设置宽度和高度地块元素的属性) 并不是所有浏览器都支持此属性,目前支持的浏览器有:Opera、Safari在IE中对内联元素使用display:inline-block,IE是不识别的,但使用display:inline-block在IE下会触发layout,从而使内联元素拥有了display:inline-block属性的表症。从上面的这个分析,也不难理解为什么IE下,对块元素设置display:inline-block属性无法实现inline-block的效果。这时块元素仅仅是被display:inline-block触发了layout,而它本就是行布局,所以触发后,块元素依然还是行布局,而不会如Opera中块元素呈递为内联对象。 IE6,7下块元素如何实现display:inline-block的效果?123456789101112131415 <style> .test1{ margin-top:10px; display:inline-block; width:200px; height:100px; background:#8ec07c; } .test2{ display:inline-block; }</style><span class="test1">测试inline-block</span><div class="test2">测试inline-block</div> 非ie6,7而ie6,7下 兼容性:IE6、IE7不识别inline-block,但可以触发块元素(这是如图第一个标签在ie6,7可以正常修饰宽高的原因)。其它主流浏览器均支持inline-block。 兼容所有浏览器的方法是:123display:inline-block;*display:inline;zoom:1;//IE特有的属性 1、首先设置inline-block触发块元素,具有了layout的特性,2、然后设置*display:inline使块元素呈现内联元素,使用zoom:1触发layout。 为什么inline-block元素之间会产生空格呢123456789101112131415161718<style>.box1,.box2,.box3{ font-size:12px; height:20px; width:20px; border:1px solid #000; display:inline-block; *display:inline; zoom:1; }</style><div class="box"> <div class="box1">12</div> <div class="box2">23</div> <div class="box3">34</div> <span>1234</span> <span>1244</span></div> 非ie6,7ie6,7产生的原因就是标签之间换行或者手动空格产生的 ###那么如何去除inline-block元素之间的空隙呢?下面介绍几种方法方法一:元素标签之间放在一行,但显然这样代码的可读性有些差123456<div class="box"> <div class="box1">12</div><div class="box2">23</div> <div class="box3">34</div> <span>1234</span> <span>1244</span></div> 方法二:font-size:01234567891011121314151617181920212223.box{ font-size:0; // 题外话之前用-webkit-text-size-adjust:none;取消chrome最小字体是12px的限制,但最新版的chrome已对该用法做了限制 } .box1,.box2,.box3{ font-size:12px; height:20px; width:20px; border:1px solid #000; display:inline-block; *display:inline; zoom:1; } .box span{ font-size:12px; } <div class="box"> <div class="box1">12</div> <div class="box2">23</div> <div class="box3">34</div> <span>1234</span> <span>1244</span> </div>]]></content>
</entry>
<entry>
<title><![CDATA[什么是hasLayout]]></title>
<url>http://yoursite.com/2016/11/23/hasLayout/</url>
<content type="text"><![CDATA[IE使用Layout概念来控制元素的尺寸和位置。如果一个元素有Layout,它就有自身的尺寸和位置;如果没有,它的尺寸和位置由最近的拥有布局的祖先元素控制。 在默认情况下,拥有Layout的元素包括:1234567<html>, <body><table>, <tr>, <th>, <td><img><hr><input>, <button>, <select>, <textarea>, <fieldset>, <legend><iframe>, <embed>, <object>, <applet><marquee> (注意,和默认不拥有Layout。)凡是具有以下CSS属性的元素,也会拥有布局:123456789position: absolutefloat: left|rightdisplay: inline-blockwidth: any value other than 'auto'height: any value other than 'auto'zoom: any value other than 'normal' (IE专用属性)writing-mode: tb-rl(IE专用属性)overflow: hidden|scroll|auto(只对IE 7及以上版本有效)overflow-x|-y: hidden|scroll|auto(只对IE 7及以上版本有效) hasLayout是IE特有的属性,不是CSS属性。可以用Javascript函数hasLayout查看一个元素是否拥有Layout。如果有,这个函数就返回true;否则返回false。hasLayout是一个只读属性,所以无法使用Javascript进行设置。]]></content>
</entry>
<entry>
<title><![CDATA[清除浮动的几种方法]]></title>
<url>http://yoursite.com/2016/11/23/clearFloat/</url>
<content type="text"><![CDATA[清除浮动的几种方法及优缺点 css浮动浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样。12345678910111213141516171819.side1{ float:left; background:#c18401; width:100px; height:100px; } .side2{ float:left; background:#c85e7c; width:100px; height:100px; } .content{ border:5px solid #000; }<div class="content"> <div class="side1"></div> <div class="side2"></div></div> 如果不清除浮动,会影响正常的布局,因此下面提出几种解决清除浮动的方法Note:想了解BFC和hasLayout以及使用zoom:1的原因猛戳BFC原理;hasLayout 清除浮动的方法方法一、使用CSS的overflow属性给浮动元素的容器(浮动元素的父元素)添加overflow:hidden;或overflow:auto;可以清除浮动,但是在ie6浏览器下上述方法不好用,另外在 IE6 中还需要触发 hasLayout ,例如为父元素设置容器宽高或设置 zoom:1。在添加overflow属性后,浮动元素又回到了容器层,把容器高度撑起,达到了清理浮动的效果。123456789101112131415161718192021 .side1{ float:left; background:#c18401; width:100px; height:100px; } .side2{ float:left; background:#c85e7c; width:100px; height:100px; }.content{ overflow:hidden;//overflow: hidden|scroll|auto(只对IE 7及以上版本有效)会触发hasLayout zoom:1;//height:100px;//使用zoom:1来兼容ie6 border:5px solid #000; }<div class="content"> <div class="side1"></div> <div class="side2"></div></div> Note:如果一个元素有Layout,它就有自身的尺寸和位置,有一些样式属性的存在(width,height,overflow,display:inline-block等)就可以触发hasLayout,但是之所以不用这些属性,是因为会影响布局(overflow:hidden只对IE 7及以上版本有效),所以使用zoom:1兼容ie6触发hasLayout ;zoom:1是IE专用属性,理解这一点,很多使用zoom:1的场合就融会贯通了overflow:hidden;或overflow:auto;可以清除浮动的原因是触发了BFC,关于BFC参见文章BFC原理 优点:方便维护,容易记住缺点:使用overflow:hidden;当子元素的内容想超高父元素的话,会被隐藏,如果没有这个需求,使用overflow:hidden挺方便的,推荐;使用overflow:auto子元素的高度超过父元素出现滚动条 方法二、使用带clear属性的空元素在浮动元素后使用一个空元素,并在CSS中赋予.clear{clear:both;}属性即可清理浮动123456789101112131415161718192021222324 .side1{ float:left; background:#c18401; width:100px; height:100px; } .side2{ float:left; background:#c85e7c; width:100px; height:100px; } .content{ border:5px solid #000; } .clear{ clear:both; }<div class="content clearfix"> <div class="side1"></div> <div class="side2"></div> <div class="clear"></div> //亦可使用<br class="clear" />或<hr class="clear" />来进行清理。</div> 优点:简单,代码少,浏览器兼容性好。缺点:需要添加大量无语义的html元素,代码不够优雅,后期不容易维护。 方法三、使用CSS的:after伪元素结合 :after 伪元素(注意这不是伪类,而是伪元素,代表一个元素之后最近的元素)和 IEhack ,可以完美兼容当前主流的各大浏览器,这里的 IEhack 指的是触发 hasLayout。给浮动元素的容器添加一个clearfix的class,然后给这个class添加一个:after伪元素实现元素末尾添加一个看不见的块元素(Block element)清理浮动。123456789101112131415161718192021222324252627282930.side1{ float:left; background:#c18401; width:100px; height:100px; } .side2{ float:left; background:#c85e7c; width:100px; height:100px; } .content{ border:5px solid #000; } .clearfix:after{ visibility:hidden; content:'.'; display:block; height:0; clear:both; } .clearfix{ zoom:1;//IE6和IE7浏览器,要给clearfix这个class添加一条zoom:1;触发haslayout。 } <div class="content clearfix"> <div class="side1"></div> <div class="side2"></div> <div class="clear"></div> </div> 通过CSS伪元素在容器的内部元素最后添加了一个看不见的空格”020”或点”.”,并且赋予clear属性来清除浮动。需要注意的是为了IE6和IE7浏览器,要给clearfix这个class添加一条zoom:1;触发haslayout。 总结通过上面的例子,我们不难发现清除浮动的方法可以分成两类: 一是利用 clear 属性,包括在浮动元素末尾添加一个带有 clear: both 属性的空 div 来闭合元素,其实利用 :after 伪元素的方法也是在元素末尾添加一个内容为一个点并带有 clear: both 属性的元素实现的。 二是触发浮动元素父元素的 BFC (Block Formatting Contexts, 块级格式化上下文),使到该父元素可以包含浮动元素,关于这一点。 推荐1.在网页主要布局时使用:after伪元素方法并作为主要清理浮动方式;2.在小模块如ul里使用overflow:hidden;(留意可能产生的隐藏溢出元素问题);3.如果本身就是浮动元素则可自动清除内部浮动,无需格外处理;4.正文中使用邻接元素清理之前的浮动。5.最后可以使用相对完美的:after伪元素方法清理浮动,文档结构更加清晰。]]></content>
</entry>
<entry>
<title><![CDATA[BFC原理]]></title>
<url>http://yoursite.com/2016/11/22/BFC/</url>
<content type="text"><![CDATA[BFC背后神奇的原理]]></content>
</entry>
<entry>
<title><![CDATA[__proto__(隐式原型)与prototype(显式原型)]]></title>
<url>http://yoursite.com/2016/11/21/prototype_chain/</url>
<content type="text"><![CDATA[理解proto和prototype,才能更好的理解原型链 一、 例子在理解原型链之前,先看一个例子12345function A(){};A.prototype.test=function(){console.log("A")};function B(){};B.prototype=new A();var c=new B(); 请猜想c.constructor? 答:A 解答现在控制台打印c对象c并没有constructor的属性,而是有内置属性proto Note:对象c自身没有constructor属性,但是因为实例拥有构造函数原型上的属性和方法,所以实例c是能访问到constructor属性123456789c.__proto__==B.prototype又因为B.prototype=new A();所以B.prototype=p,p=new A();p.__proto__=A.prototype;B.prototype.__proto__==A.prototype;所以c.__proto__.__proto__==A.prototype构造函数的原型上内置属性proto和constructor构造函数的原型上的构造器函数又指向prototype属性所在函数 Note:注意实际过程中构造函数的原型是否被重写,像B.prototype=new A();就是被重写了,B.prototype上不存在constructor,就要去B.prototype.proto上去找 123即A.prototype.constructor==Ac.__proto__.__proto__.constructor==A.prototype.constructor==A;c.constructor==A 二、什么是显示原型和隐式原型显示原型每一个函数在创建之后都会拥有一个名为prototype的属性,这个属性指向函数的原型对象 Note:通过Function.prototype.bind方法构造出来的函数是个例外,它没有prototype属性;隐式原型JavaScript中任意对象都有一个内置属性[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过proto来访问。ES5中有了对于这个内置属性标准的Get方法Object.getPrototypeOf(). Note: Object.prototype 这个对象是个例外,它的proto值为null 二者的关系:隐式原型指向创建这个对象的函数(constructor)的prototype 三、作用是什么显式原型的作用:用来实现基于原型的继承和属性的共享隐式原型的作用:构成原型链,同样用于实现基于原型的继承。举个例子,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着proto依次查找。 四、proto的指向?proto的指向到底如何判断呢?根据ECMA定义 ‘to the value of its constructor’s “prototype” ‘ —-指向创建这个对象的函数的显式原型。所以关键的点在于找到创建这个对象的构造函数,接下来就来看一下JS中对象被创建的方式,一眼看过去似乎有三种方式:(1)对象字面量的方式(2)new 的方式(3)ES5中的Object.create() 但是我认为本质上只有一种方式,也就是通过new来创建。为什么这么说呢,首先字面量的方式是一种为了开发人员更方便创建对象的一个语法糖,本质就是: 123var o = new Object(); o.xx = xx;o.yy=yy; 再来看看Object.create(),这是ES5中新增的方法,在这之前这被称为原型式继承,12345678//道格拉斯在2006年写了一篇文章,题为 Prototypal Inheritance In JavaScript。在这篇文章中,他介绍了一种实现继承的方法,这种方法并没有使用严格意义上的构造函数。//他的想法是借助原型可以基于已有的对象创建新对象,同时还不比因此创建自定义类型,为了达到这个目的,他给出了如下函数:function object(o){ function F(){} F.prototype = o; return new F()}//----- 《JavaScript高级程序设计》P169 所以从实现代码 return new F() 中我们可以看到,这依然是通过new来创建的。不同之处在于由 Object.create() 创建出来的对象没有构造函数,看到这里你是不是要问,没有构造函数我怎么知道它的proto指向哪里呢,其实这里说它没有构造函数是指在 Object.create() 函数外部我们不能访问到它的构造函数,然而在函数内部实现中是有的,它短暂地存在了那么一会儿。假设我们现在就在函数内部,可以看到对象的构造函数是F, 现在//以下是用于验证的伪代码1234567var f = new F(); //于是有f.__proto__ === F.prototype //true//又因为F.prototype === o;//true//所以f.__proto__ === o; 因此由Object.create(o)创建出来的对象它的隐式原型指向o。 举例子来巩固一下一个对象的proto指向谁了。构造函数的显示原型的隐式原型:内建对象(built-in object):比如Array(),Array.prototype.proto指向什么?Array.prototype也是一个对象,对象就是由 Object() 这个构造函数创建的,因此:1Array.prototype.__proto__ === Object.prototype //true, 或者也可以这么理解,所有的内建对象都是由Object()创建而来。自定义对象1、 默认情况下:123function Foo(){}var foo = new Foo()Foo.prototype.__proto__ === Object.prototype //true 理由同上 2、 其他情况:(1)1234function Bar(){}//这时我们想让Foo继承BarFoo.prototype = new Bar()Foo.prototype.__proto__ === Bar.prototype //true (2)1234567//我们不想让Foo继承谁,但是我们要自己重新定义Foo.prototypeFoo.prototype = { a:10, b:-10 } //这种方式就是用了对象字面量的方式来创建一个对象,根据前文所述 Foo.prototype.__proto__ === Object.prototype 注:以上两种情况都等于完全重写了Foo.prototype,所以Foo.prototype.constructor也跟着改变了,于是乎constructor这个属性和原来的构造函数Foo()也就切断了联系。构造函数的隐式原型既然是构造函数那么它就是Function()的实例,因此也就指向Function.prototype,比如 Object.proto === Function.prototype 五、instanceofinstanceof 操作符的内部实现机制和隐式原型、显式原型有直接的关系。instanceof的左值一般是一个对象,右值一般是一个构造函数,用来判断左值是否是右值的实例。它的内部实现原理是这样的:1234//设 L instanceof R //通过判断 L.__proto__.__proto__ ..... === R.prototype ?//最终返回true or false 也就是沿着L的proto一直寻找到原型链末端,直到等于R.prototype为止。知道了这个也就知道为什么以下这些奇怪的表达式为什么会得到相应的值了12345Function instanceof Object // true Object instanceof Function // true Function instanceof Function //trueObject instanceof Object // trueNumber instanceof Number //false]]></content>
</entry>
<entry>
<title><![CDATA[基本类型和引用类型]]></title>
<url>http://yoursite.com/2016/11/19/base_reference_type/</url>
<content type="text"><![CDATA[基本类型:undefined null Boolean Number String 基本类型都是按值访问的,就是可以操作保存在变量中的值;而引用类型的值是保存在内存中的,js是不能操作对象在内存中的位置的,实际上是操作的对象的引用,因此引用类型的值是按引用访问的 动态属性对于引用类型的变量,可以对其增加和删除属性和方法。基本类型不可以12var people=new Object();people.name='sbx'; 复制变量基本类型12var num1=5;var num2=num1; ;引用类型在程序设计里边 注解有这样的一段话:当复制保存着对象的某个变量时,操作的是对象的引用。但在为对象添加属性时,操作的是实际的对象,举例说明 1234var obj1=new Object();obj2=obj1;obj1.name="sbx";alert(obj2.name);//sbx ;复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量. 类型检测typeoftypeof 操作符是确定一个变量是字符串、数值、布尔值,还是undefined 的最佳工具。typeof是检测基本数据类型的得力助手,但是对引用类型的话没有太大作用,如果变量的值是一个对象或null,则返回的是Object;instanceof我们并不是想知道某个值是对象,而是想知道它是什么类型的对象,就要用instanceof;所有引用类型的值都是Object 的实例。因此,在检测一个引用类型值和Object 构造函数时,instanceof 操作符始终会返回true。当然,如果使用instanceof 操作符检测基本类型的值,则该操作符始终会返回false,因为基本类型不是对象。123456var obj={"key":{"1":"2"},"id":[1,2,3]};typeof(obj["key"])//"object"typeof(obj["id"])//"object"obj["key"] instanceof Object//trueobj["id"] instanceof Object//trueobj["id"] instanceof Array//true 当然instanceof还用来检测实例与原型之间的关系,所有出现在实例原型链上的原型都会返回true;123456789function A(){};A.prototype.test=function(){console.log("A")};function B(){};B.prototype=new A();var c=new B();c instanceof B//truec instanceof A//truec instanceof Object//true]]></content>
</entry>
<entry>
<title><![CDATA[对象简单及深度克隆(复制 拷贝)]]></title>
<url>http://yoursite.com/2016/11/17/clone/</url>
<content type="text"><![CDATA[除了数组和json数据要深度克隆,其他都可以=来复制,这种复制的差异主要是基本类型和引用类型之间的差别,为了理解深入,可以先去参考的文章 浅拷贝基本类型的拷贝,利用=就可以实现,而如果引用类型(Array,Object)还是=来拷贝的话,就是浅拷贝1234var arr=[1,2,3];var arrobj=arr;arrobj.push(5);alert(arr)//[1,2,3,5] 可见对于引用类型的复制,操作的是引用对象而不是在内存中的实际的值,拷贝对象和被拷贝对象都指向内存中的同一个位置,一改则都改,为了避免拷贝对象和被拷贝对象的互相的干扰,就需要深度拷贝; 深拷贝所谓”深拷贝”,就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用”浅拷贝”就行了12345678910111213//源码function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]);//递归 } else { c[i] = p[i]; } } return c; } 延伸:$.extend()也有深拷贝和浅拷贝,想了解猛戳$.extend() 数组深拷贝1.js的slice函数1arrayObj.slice(start, [end]) 参数 1 2 arrayObj 必选项。一个 Array 对象。 start 必选项。arrayObj 中所指定的部分的开始元素是从零开始计算的下标。 end 可选项。arrayObj 中所指定的部分的结束元素是从零开始计算的下标。 说明 slice 方法返回一个 Array 对象,其中包含了 arrayObj 的指定部分。 slice 方法一直复制到 end 所指定的元素,但是不包括该元素。 如果 start 为负,将它作为 length + start处理,此处 length 为数组的长度。 如果 end 为负,就将它作为 length + end 处理,此处 length 为数组的长度。 如果省略 end ,那么 slice 方法将一直复制到 arrayObj 的结尾。 如果 end 出现在 start 之前,不复制任何元素到新数组中。例子12345678910111213var arr=[1,2,4,5]var arrobj=arr.slice(0);arrobj.push(7)alert(arrobj)//[1,2,4,5,7]alert(arr)//[1,2,4,5]//看一下slice具体的使用arr.slice(0)//[1, 2, 4, 5]arr.slice(0,4)//[1, 2, 4, 5]arr.slice(0,3)//[1, 2, 4]arr.slice(-1,3)//[]arr.slice(-3,3)//[2, 4]arr.slice(4,3)//[]arr.slice(1,-2)//[2] 2.js的concat函数concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。语法1arrayObject.concat(arrayX,arrayX,......,arrayX) 说明返回一个新的数组。该数组是通过把所有 arrayX 参数添加到 arrayObject 中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。12var arr = ["One","Two","Three"];var arrobj=arr.concat();]]></content>
</entry>
<entry>
<title><![CDATA[编码 解码]]></title>
<url>http://yoursite.com/2016/11/17/encode/</url>
<content type="text"><![CDATA[escape() encodeURI() encodeURIComponent() 编码 解码 摘要: escape()不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值。比如”春节”的返回结果是%u6625%u8282,,escape()不对”+”编码 主要用于汉字编码,现在已经不提倡使用。 encodeURI()是Javascript中真正用来对URL编码的函数。 编码整个url地址,但对特殊含义的符号”; / ? : @ & = + $ , #”,也不进行编码。对应的解码函数是:decodeURI()。 encodeURIComponent() 能编码”; / ? : @ & = + $ , #”这些特殊字符。对应的解码函数是decodeURIComponent()。假如要传递带&符号的网址,所以用encodeURIComponent()详总:http://www.haorooms.com/post/js_escape_encodeURIComponent 解码例子 针对escape、encodeURI、encodeURIComponent三种编码方式,根据其编码特征来处理 1、escape,特征最为明显,对于值小与255的字符编码格式为%[a-zA-Z0-9]{2},对值大于255的字符编码格式为%u[a-zA-Z0-9]{4}, escape不进行编码的字符有69个: ,+,-,.,/,@,_,0-9,a-z,A-Z2、encodeURI,编码格式为%[a-zA-Z0-9]{2}, encodeURI不进行编码的字符有82个:!,#,$,&,’,(,),,+,,,-,.,/,:,;,=,?,@,,~,0-9,a-z,A-Z3、encodeURIComponent三种编码方式,编码格式为%[a-zA-Z0-9]{2}, encodeURIComponent不进行编码的字符有71个:!, ‘,(,),*,-,.,,~,0-9,a-z,A-Z 提取三种编码方式不同的部分:-当字符的值小于255时,三种编码方式结果相同,可以任意使用一种解码方式-当字符的值大于255时,escape编码的结果与另外两者不同,可根据其编码特征来处理,即当编码格式为%u[a-zA-Z0-9]{4}时,使用unescape解码,-当编码格式为%[a-zA-Z0-9]{2}时,因为encodeURIComponent不进行编码的字符少于encodeURI, 则可判断decodeURIComponent可以同时针对encodeURI和因为encodeURIComponent两种编码方式进行解码 记录解码结果,如果解码后与原字符串相同,则结束递归12345678910111213141516function decode(value) { var ov = value, nv; var re4escape = new RegExp("%u[a-zA-Z0-9]{4}","ig"); var re4decodeuri = new RegExp("^((%[a-zA-Z0-9]{2})|([!#$&'()*+,-./:;=?@_~a-zA-Z0-9]))*$",""); if (re4escape.test(ov)) nv = unescape(ov); else if (re4decodeuri.test(ov)) nv = decodeURIComponent(ov); else nv = ov; if (ov != nv) return decode(nv); else return nv } 图解]]></content>
</entry>
<entry>
<title><![CDATA[transitionend animationend 事件兼容问题]]></title>
<url>http://yoursite.com/2016/11/17/transitionend/</url>
<content type="text"><![CDATA[介绍1.transitionend animationend 事件兼容问题2.transitionend有过渡效果的css属性3.webkitAnimationEnd(animationend)事件与webkitTransitionEnd(transitionend)事件4.transitionend事件的多次执行及解决办法, 不同于transitionend事件,animationend只会在动画完成后执行一次 详解transitionend animationend 事件兼容问题webkitAnimationEnd(animationend)事件与webkitTransitionEnd(transitionend)事件]]></content>
</entry>
<entry>
<title><![CDATA[小动画]]></title>
<url>http://yoursite.com/2016/11/16/animation/</url>
<content type="text"><![CDATA[介绍一些小动画的制作以及css3动画属性的使用 animation-timing-function 之steps()使用;timing-function 作用于每两个关键帧之间,而不是整个动画 旋转加载123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117.wrap{ width:80px; height:80px; position:relative;}.wrap>div{ position:absolute; top:0; left:40px; width:5px; height:78px;}.wrap>div:after,.wrap>div:before{ content:"."; display:block; height:50%; width:5px; background:#000; border-radius:5px;}.wrap .line1{ -webkit-transform: rotate(0deg);}.wrap .line2{ -webkit-transform: rotate(30deg);}.wrap .line3{ -webkit-transform: rotate(60deg);}.wrap .line4{ -webkit-transform: rotate(90deg);}.wrap .line5{ -webkit-transform: rotate(120deg);}.wrap .line6{ -webkit-transform: rotate(150deg);}.wrap .line1:before{ -webkit-animation:load 1200ms linear 0s infinite forwards;}.wrap .line2:before{ -webkit-animation:load 1200ms linear 0.1s infinite forwards;}.wrap .line3:before{ -webkit-animation:load 1200ms linear 0.2s infinite forwards;}.wrap .line4:before{ -webkit-animation:load 1200ms linear 0.3s infinite forwards;}.wrap .line5:before{ -webkit-animation:load 1200ms linear 0.4s infinite forwards;}.wrap .line6:before{ -webkit-animation:load 1200ms linear 0.5s infinite forwards;}.wrap .line1:after{ -webkit-animation:load 1200ms linear 0.6s infinite forwards;}.wrap .line2:after{ -webkit-animation:load 1200ms linear 0.7s infinite forwards;}.wrap .line3:after{ -webkit-animation:load 1200ms linear 0.8s infinite forwards;}.wrap .line4:after{ -webkit-animation:load 1200ms linear 0.9s infinite forwards;}.wrap .line5:after{ -webkit-animation:load 1200ms linear 1s infinite forwards;}.wrap .line6:after{ -webkit-animation:load 1200ms linear 1.1s infinite forwards;}.circle{ width: 40px; height: 40px; position: absolute; top: 27px; left: 30px; background: #fff; border-radius: 50%;}@-webkit-keyframes load{ 0% { opacity: 0; } 100% { opacity: 1; }} html123456789<div class="wrap"> <div class="line1"></div> <div class="line2"></div> <div class="line3"></div> <div class="line4"></div> <div class="line5"></div> <div class="line6"></div></div><div class="circle"></div> 晃动尾巴的狗steps(n,start/end) n指每帧之间变化几次 即0%-33%变化n次 33%-67%变化n次 67%-100%变化n次123456789101112131415161718192021222324252627.dog{ position:absolute; top:200px; -webkit-animation: dog .8s steps(1) infinite forwards; width: 175px; height: 160px; background: url("http://sta.ganjistatic1.com/ng/app/client/app/misc/11th_anniversary/images/dog.png") no-repeat; background-size: 175px auto;}@-webkit-keyframes dog { 0% { background-position: 0 0 } 33% { background-position: 0 -160px } 67% { background-position: 0 -320px } 100% { background-position: 0 0 }} html12<!--晃动尾巴的狗--><div class="dog"></div>]]></content>
</entry>
<entry>
<title><![CDATA[chrome控制台的使用]]></title>
<url>http://yoursite.com/2016/11/16/chrome/</url>
<content type="text"><![CDATA[掌握谷歌的控制台可以使程序的调试事半功倍 ELEMENT编辑小技巧 Ctrl+shift+I /f12打开调试工具 Ctrl+shift+j 打开调试工具 并把光标直接定位到控制台 Ctrl+shift+c 打开调试工具 定位文件 “Sources”面板中 选择打开新的文件: ctrl+p ; 选择指定文件中的某一行某一列:ctrl+o使用“:行数:列数”的功能 选择指定文件中某一个函数:ctrl+shift+p 可输入选择想找的函数 展开列 选择”Elements”面板 选择DOM元素和在带有剪头的地点按住Alt +点击鼠标左键,可以展开所有子节点 改变开发者工具的位置试一试快捷键:Ctrl + Shift + D。设置开发者工具有三个选项: 不在窗口中显示开发者工具 在窗口右侧显示开发者工具 在窗口底部显示开发者工具 自定义颜色调色板 你可以点击颜色代码前面的小图标,调整颜色 多个光标 移动光标按住CMD + 点击可以添加多个光标,你也可以使用Ctrl + U撤销你选择的最后一个光标。 复制图片的Data URI 选择”Network”面板 在“Resources”面板选择你的图片 在图片上右击,选择“Copy Image as Data URI”选项 触发伪类 在左边的面板元素上右击鼠标,并选择“:active :hover :focus :visited” 另外在右边的面板中选择切换伪类状态的图标 使用$0获取当前元素 选择“Elements”面板 在”Element”面板中选择DOM元素 点击”Console”并输入$0可以获取当前元素 在元素中显示 在控制台,选择一个DOM节点:(eg:document.getElementById(“#box”)) 在“Console”面板中右击,选择”Reveal in Elements Panel” 查看事件监听器 选择“Elements”面板” 在“Event Listeners”菜单中选择一个事件 右击并选择“Show Function Definition”,你可以查看到对应的源码 CONSOLEUsing the Consolecrtl+shif+J 打开控制+直接把光标定位到console面板 计算一段程序执行时间,可以在timeline上看见计算某条语句的执行次数把参数以表格形式输出 Interact from Command LineSOURCE运行预定义的代码片段 在左侧边栏中选择: Sources > Snippets 右击选择Select New 输入文件名和在右侧的面板中输入代码片段 代码片段文件名上右击选择Run Workspaces 选择“Sources”面板 在Sources面板中右击并选择“Add Folder to Workspaces”最后选择你工程项目的存储位置即可 右键点击本地映射文件,并选择Map to Network Resources就会加载相应的“网络”文件了 修改你的文件代码和查看 添加断点及Blackbox script用于查看和调试当前页面所加载的脚本的源文件。断点不只可以添加删除,还可以在断点处进行编辑。此外XHR Breakpoints允许当一个预期Ajax请求创建时断开 blackbox允许屏蔽指定的js 屏蔽文件后会怎么样 库代码(被屏蔽的文件)里抛出异常时不会暂停(当设置为Pause on exceptions时) 调试时Stepping into/out/over都会忽略库代码 事件断点也会忽略库代码 库代码里设置的任何断点也不会起作用 最终的结果就是只会调试应用代码而忽略第三方代码(配置了Blackbox的代码)。 http://www.alloyteam.com/2015/01/chrome-devtools-blackbox/>比较大的用途就是 一步一步调代码时候(step into/out/over),避免代码进入一些库中(jquery等) 这个配合事件监听以很方便找到某一事件的触发函数 (要快速找到当你点击一个按钮或一个链接被点击时候执行的代码等) Networknetwork下的每一项 Name and Path:分别是资源的名称和URL路径 Method:用于请求的HTTP方法。例如:GET或POST。 Status and Text:http状态码和文本信息 Domain:请求资源的域名 Type:所请求的资源的MIME类型。Documents,Stylesheets,Images,Scripts,XHR,Fonts,Other Initiator:Initiator 可以快速定位请求是怎么发起的 有四种可能: - Parser:请求是由页面的HTML解析时发送的; - Redirect:请求是由页面重定向发送的; - Script:请求是由script脚本处理发送的; - Other:请求是由其他过程发送的,比如页面里的link链接点击导航到页面或者在地址栏输入URL地址。 Cookies:cookie的细节在resource面板 Set-Cookies:cookie在http请求中设置 Size and Content:size是所有的请求头(一般几百字节)加上请求体的大小;content是所有解码内容的大小,如果从浏览器缓存中加载资源而不是通过网络,这一领域将包含文本(从缓存)。 Time and Latency:Time是总的时间,从一开始请求到接受最后一个字节的时间;Latency:响应第一个字节的时间 Timeline:下面会有详解network下的Header点击View parsed/View source可以看被解析格式或者源文件格式点击View decoded/View URL encoded 可以看解码和编码格式的network-preview network-response network-Timeline Stalled/Blocking:浏览器发请求前本地的操作时间,比如去缓存中查看页面缓存等 Proxy:与代理服务器连接的时间 DNS Lookup: DNS查询的时间 Connecting:建立TCP连接的时间 相当于客户端从发请求开始到TCP握手结束这一阶段。 Sending:发送请求时间 一般很小 Waiting:发送请求完毕到接收请求开始的时间。这个时间段就是服务器处理和返回数据网络延时时间。 Content Download / Downloading:接受数据的时间 蓝线表示: DOMReady事件。事件触发的条件是:浏览器已经把整个 HTML 文档的 DOM结构解析完毕。一般前端开发者监听这个事件是为了可靠地在文档中查找元素。这个事件触发之前有可能只下载了半截 HTML,想要的元素还没出现。红线表示: load 事件,触发条件是:整个页面的 JS CSS 图片都下载完毕。用户看到的进度条/小菊花已经不再显示为“忙”的状态。是用户眼中的加载完毕。 network-cookiecookie每个参数值详解 WebSocket framesdata:Continuation FrameBinary FrameConnection Close FramePing FramePong Framelength:负载消息的长度 单位字节time:当消息被创建的时候的时间戳说明:在每一帧消息到达后刷新帧表格,点击左边的resource刷新。只有最后100 WebSocket消息帧表保存的。 如何过滤和排序结果每一列都有一个小箭头,点击切换排序Timeline题目左键-可以更换条目timeline:这是以每个网络请求的开始时间来排序。这是默认的排序,(和starttime一样)。stattime:按每个网络请求的开始时间排序(排序由时间表选项一样)。response time:按每个请求的响应时间来排序。endtime:按每个请求完成时排序。Duration:按每个请求的总时间排序。选择这个过滤器来确定哪些资源需要最长的时间来加载。Latency:从请求开始到响应开始这一段时间排序。选择这个过滤器来确定哪些资源需要最长的时间加载出第一个字节。 Network Filmstrip“Film Strip”显示页面从开始到结束渲染的截图。你可以点击截图和在timeline-style中查看视图。 选择“Network”面板 点击“录制”图标 重新加载页面 TIMELINETimeline面板中记录和分析了你的应用在运行时所有的活动情况,它是你排查应用性能瓶颈的最佳工具!Timeline预览面板Timeline面板有三个主要的窗口:顶部的预览窗口,中间的记录窗口,底部的工具条,如下图:在你开启记录(就好像打开了录像机的录制功能)后,在这期间你的应用中发生的所有事件都会被记录下来形成一条日志记录,按照记录的类型一般会标注上不同的颜色:举个例子,下面的截图中显示了一个html页面的事件日志记录,可以看到,第一条记录表示的是浏览器为了获取html页面而发送了http请求的发送请求事件,接下来是一个接受响应事件,和接受对应响应体(html页面内容的字节)的事件,最后是一个加载完毕事件记录。除了Records视图外,你还可以在三个模式中切换关注点: Events:显示所有的事件记录 Frames:显示页面渲染的帧数 Memory:显示页面的内存使用情况 下面着重介绍一下三种模式 Timeline三种模式Events 模式Events模式提供了一个概览图,包含了在记录期间你的页面被捕获到的所有事件,你可以很容易的看到你的应用到底哪里耗时最久,等等~~ 每个带颜色的横条表示特定类型的事件,横条的长度代表的是该事件从开始到结束的耗时~~Frames 模式帧模式从渲染性能的角度提供了数据支撑,一个“frame”表示浏览器为了渲染单个内容块而必须要做的工作(包括:执行js,处理事件,修改DOM,更改样式和布局,绘制页面)! 我们的目标是保证我们的页面要有高于每秒60帧的跑分,这和目前大多数显示器的刷新率相吻合(60Hz)!这么算的话,我们的应用的每一帧耗时应该低于16.6ms(1000ms/60)上图中,在Frame视图中有两条贯穿该视图的横线,分别标识出60FPS和30FPS的基准,按照我们刚才提到的那个公式,我们可以理解为分别标识了16.6ms和33.3ms两个时间点~~ 图中帧柱的高度表示了该帧的总耗时,帧柱中的颜色分别对应该帧中包含的不停类型的事件!注意上图中的鼠标位置,该工具条显示了当前选中的帧柱的耗时,可以看到鼠标指上去后会显示出该帧柱的详细数据! 你可能注意到了在帧柱上存在灰色区域和空白区域~~它们分别代表:灰色区块:那些没有被DevTools感知到的活动空白区块:显示刷新周期(display refresh cycles)中的空闲时间段如下图所示:当你在Frame视图中选择了一个区域,在Timeline面板的最底部(右下方)会统计出你选中的时间范围内的帧柱的统计数据,如下图:当鼠标指上去后会弹出详细信息,包含下面字段: Selected range:选中的时间段内包含的帧柱数 Minimum Time:该时间段里帧柱中的最小耗时 Average Time:该时间段里帧柱的平均耗时 Maximum Time:该时间段里帧柱中的最大耗时 Standard Deviation:计算平均耗时的有效偏差值 Time by category:耗时的分布情况 Memory 模式Memory视图显示了我们的应用的内存使用情况图表,包括页面的文档数,DOM节点数,和没有被垃圾回收掉的仍然在内存中的事件监听器数,如下图:模拟流程打开一个你想分析的页面;打开DevTools的Timeline面板,点击”Record”按钮,或者使用热键:Ctrl + E(Win), Cmd + E(Mac);然后在页面上操作你想要了解的功能;停止记录,分析收集到的记录数据。收集记录的小技巧 尽可能的缩短记录的时间:确保记录的时间段很短,有利于锁定关注点,避免太多不必要的数据干扰; 避免不必要的操作:同上道理,在记录期间,尽可能只触发你想分析的操作; 关闭浏览器缓存:如果你想分析网络操作细节,你最好关闭浏览器缓存; 关闭浏览器扩展工具:这样可以避免记录到这些第三方插件产生的行为记录,你可以开启浏览器的“隐身模式” 锁定强制同步布局瓶颈所谓布局(Layout),指的是浏览器计算页面中所有元素的位置和尺寸的过程!通常我们的Chrome会延迟布局计算,这样可以攒够一批变更(css变化或dom结构变化)后一次性执行!但是我们的脚本可以强制浏览器立刻进行布局操作,频繁的进行强制同步布局很可能会造成性能瓶颈! Timeline面板会用“黄色惊叹号三角标”标注出那些发生的强制浏览器布局,当你查看对应记录详情时,也会在弹出的窗口中看到问题代码的调用堆栈信息,如下: 如果一个记录包含子记录触发了强制布局,那父记录会被一个“浅黄色惊叹号三角标”标识,如下图: 这种子记录是如何产生的呢?原因有二:1.在执行某个事件的过程中同步产生了其他事件;2.当打开了底部工具条中的“Glue asynchronous events to causes”开关后,异步事件记录会作为触发该异步事件的记录的子记录。 下面分别举两个例子:当Chrome尝试去解析一段HTML时,如果发现该HTML引用了一些外部资源,那么Chrome必须先加载这些文件才能完成解析,这就是上面说的第一点,如下图: 在前端浏览器中存在很多异步回调的场景,比方说ajax。由于触发异步和异步回调事件之间可能间隔很长时间,这对于我们分析数据造成了一定程度的不便,所以我们可以打开“Glue asynchronous events to causes”开关,如下图: 心细的童鞋注意到了在上图中展示的第一条记录条中,被标识了不同颜色区块~它们分别对应下面的含义: 左边深色:表示父记录和它的同步子记录的耗时(长度); 中间稍浅:表示父记录和它的异步子记录的耗时; 右边泛白:表示从第一个异步事件开始到最后一个异步事件结束的耗时。如下图: 当鼠标指向某个记录时,弹出的窗口中显示了该记录详细的数据: Duration:匹配该记录及其子记录的总耗时; Self Time:只包含自己得耗时(不包含子记录); CPU time:CPU耗时。如下图:Timeline中的各种事件Loading事件Scripting事件Render事件Painting事件timeline详解-值的一看; PROFILESRESOURCEAudits用于页面优化,对网络效率和性能的审查 并且会给出一些建议 DEVICE MODEREMOTE DEBUGGINGSETTING]]></content>
</entry>
<entry>
<title><![CDATA[变量提升和函数声明提前]]></title>
<url>http://yoursite.com/2016/11/15/variable_hoising/</url>
<content type="text"><![CDATA[理解JavaScript变量声明行为的一个好办法是把变量声明看作由两部分组成,即声明和赋值。JavaScript隐式地提升(hoists)声明部分到封闭函数的顶部,而将赋值留在原地。换句话说,变量的作用域是整个函数,但仅在var语句出现的位置进行赋值 函数的声明方式在定义一个函数的时候通常有两种声明方式:12foo(){}; // 函数声明var foo = function(){}; // 函数表达式 不同之处函数表达式后面加括号可以直接执行函数声明会提前预解析预解析让我们先看一个例子:12345foo(); // 函数声明foo_later(); // foo_later is not a functionfunction foo(){ console.log('函数声明'); }var foo_later = function(){ console.log('函数表达式'); } 可以看到,函数声明foo被预解析了,它可以在其自身代码之前执行;而函数表达式foo_later则不能。要解决这个问题,我们先要弄清楚JavaScript解析器的工作机制。 变量提升(hoist)JavaScript解析器会在自身作用域内将变量和函数声明提前(hoist),也就是说,上面的例子其实被解析器理解解析成了以下形式: 12345678function foo(){ console.log('函数声明'); } // 函数声明全部被提前var foo_later; // 函数表达式(变量声明)仅将变量提前,赋值操作没有被提前foo(); foo_later(); foo_later = function(){ console.log('函数表达式'); } 这样也就可以解释,为什么在函数表达式之前调用函数,会返回错误了,因为它还没有被赋值,只是一个未定义变量,当然无法被执行。 同样的,我们也可以试着猜测下面这段代码的输出结果:12345console.log(declaredLater); var declaredLater = "Now it's defined!";console.log(declaredLater); 该段代码可以被解析成一下形式: 1234567var declaredLater; console.log(declaredLater); // undefineddeclaredLater = "Now it's defined!";console.log(declaredLater); // Now it's defined! 变量声明被提到最前(所以不会报出变量不存在的错误),但赋值没有被提前,所以第一次的输出结果是undefined。 需要注意的是由于函数声明会被预解析,所以不要使用此种方法来声明不同函数。尝试猜想下面例子的输出结果: 123456789101112if(true){ function aaa(){ alert('1'); } }else{ function aaa(){ alert('2'); }}aaa(); 与我们预想的不同,该段代码弹出的是“2”.这是因为两个函数声明在if语句被执行之前就被预解析了,所以if语句根本没有用,调用aaa()的时候直接执行了下面的函数。 总结通过上面的讲解可以总结如下: 变量的声明被提前到作用域顶部,赋值保留在原地函数声明整个“被提前”函数作为值赋给变量时只有变量“被提前”了,函数没有“被提前”通过练习上面的实例自己多感受一下。另外,作为最佳实践:变量声明一定要放在作用域/函数的最上方(JavaScript 只有函数作用域!)。 参考: JavaScript 中对变量和函数声明的“提前(hoist)” 函数声明 VS 函数表达式]]></content>
</entry>
<entry>
<title><![CDATA[强制缓存和协商缓存]]></title>
<url>http://yoursite.com/2016/11/08/cache/</url>
<content type="text"><![CDATA[强制缓存: 在web服务器返回的响应中添加Expires和Cache-Control Header Expires:比较老的做法,设置一个过期时间 Cache-Control:设置的是相对时间 Cache-Control的优先级高于Expires 协商缓存 【Last-Modified和If-Modified-Since配合使用】【ETag和If-None-Match配合使用】 后者更靠谱一些 请求头参数:If-Modified-Since If-None-Match 响应头参数:Last-Modified ETag 请求头参数和响应头参数 比较 来看是否命中缓存强制缓存的优先级高于协商缓存 参考学习强制缓存和协商缓存请求头 知乎分析作者:beepony链接:https://www.zhihu.com/question/22073045/answer/27323420来源:知乎著作权归作者所有,转载请联系作者获得授权。 http协议里的get和post方法首先,你要先比较了解 HTTP 协议里各个方法的定义。例如:GET 和 POST 方法 GET 方法是从指定的资源请求数据GET 请求可被缓存GET 请求保留在浏览器历史记录中GET 请求可被收藏为书签GET 请求不应在处理敏感数据时使用GET 请求有长度限制GET 请求只应当用于取回数据 POST 方法向指定资源提交要被处理的数据POST 请求不会被缓存POST 请求不会保留在浏览器历史记录中POST 不能被收藏为书签POST 请求对数据长度没有要求 Cache-Control 与 ExpiresCache-Control 与 Expires 作用一致,都是指当前资源的有效期,控制浏览器是否直接从浏览器获取数据还是重新发送请求到服务器取数据。Cache-Control 的选择更多,设置更细致,如果同时存在的话,优先级高于 Expires。 Last-Modified/ETag 与 Cache-Control/Expires配置 Last-Modified/ETag 的情况下,浏览器再次访问统一 URI 的资源,还是会发送请求到服务器询问文件是否已经修改,如果没有,服务器会只返回影响吗 304回给浏览器,代表资源没有变化,告诉浏览器直接读取缓存数据 Cache-Control/Expires 不同,如果检测到本地的缓存还是有效的时间范围内,浏览器直接使用本地副本,不会发送任何请求。两者一起使用时,Cache-Control/Expires的优先级要高于Last-Modified/ETag。即当本地副本根据Cache-Control/Expires发现还在有效期内时,则不会再次发送请求去服务器询问修改时间(Last-Modified)或实体标识(Etag)了。一般情况下,使用 Cache-Control/Expires 会配合 Last-Modified/ETag 一起使用,因为即使服务器设置缓存时间, 当用户点击“刷新”按钮时,浏览器会忽略缓存继续向服务器发送请求,这时 Last-Modified/ETag 将能够很好利用 304 ,从而减少响应开销。看到这里,你也许会问,既然已经有了 Last-Modified 已经能够知道本地缓存是否是最新的了,为什么还需要 Etag 呢? 使用Etag主要是基于以下几个原因: Last-Modified 标注的最后修改时间只能精确到秒,如果有些资源在一秒之内被多次修改的话,他就不能准确标注文件的新鲜度了 如果某些资源会被定期生成,当内容没有变化,但 Last-Modified 却改变了,导致文件没使用缓存 有可能存在服务器没有准确获取资源修改时间,或者与代理服务器时间不一致的情形。 Etag 是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified 与 ETag 是可以一起使用的,服务器会优先验证 ETag,一致的情况下,才会继续比对 Last-Modified,最后才决定是否返回304。 用户操作也与缓存有关系此外,用户操作也与缓存有关系通过上表我们可以看到,当用户在按 F5 进行刷新的时候,会忽略 Expires/Cache-Control 的设置,会再次发送请求去服务器请求,而 Last-Modified/Etag 还是有效的,服务器会根据情况判断返回 304 还是 200;而当用户使用 Ctrl+F5 进行强制刷新的时候,只是所有的缓存机制都将失效,重新从服务器拉去资源。 不能被缓存的请求 HTTP 信息头中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0 等告诉浏览器不用缓存的请求 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的 经过HTTPS安全加密的请求(有人也经过测试发现,ie 其实在头部加入 Cache-Control:max-age 信息,firefox 在头部加入 Cache-Control:Public 之后,能够对HTTPS的资源进行缓存) HTTP 响应头中不包含 Last-Modified/Etag,也不包含 Cache-Control/Expires 的请求无法被缓存]]></content>
</entry>
<entry>
<title><![CDATA[ajax源码解析-jQuery. ajaxPrefilter和jQuery. ajaxTransport]]></title>
<url>http://yoursite.com/2016/11/04/ajax_5/</url>
<content type="text"><![CDATA[核心 jQuery. ajaxPrefilter前置处理器jQuery. ajaxTransport请求分发器 流程图 参考jQuery源码分析之ajaxTransport 源码注解123456789101112131415161718192021222324252627282930313233343536373839404142全局变量var prefilter={};jQuery.extend({ ajaxPrefilter: addToPrefiltersOrTransports(prefilters), ajaxTransport: addToPrefiltersOrTransports(transports), })<!--ajaxPrefilter和ajaxTransport的构造器-->function addToPrefiltersOrTransports(structure) { // dataTypeExpression is optional and defaults to "*" <!--返回的是一个函数 此处应用的就是闭包--> return function (dataTypeExpression, func) { if (typeof dataTypeExpression !== "string") { func = dataTypeExpression; dataTypeExpression = "*"; } if (jQuery.isFunction(func)) { var dataTypes = dataTypeExpression.toLowerCase().split(rspacesAjax), i = 0, length = dataTypes.length, dataType, list, placeBefore; // For each dataType in the dataTypeExpression for (; i < length; i++) { dataType = dataTypes[i]; // We control if we're asked to add before // any existing element placeBefore = /^\+/.test(dataType); if (placeBefore) { dataType = dataType.substr(1) || "*"; } list = structure[dataType] = structure[dataType] || []; // then we add to the structure accordingly list[placeBefore ? "unshift" : "push"](func); } } }; } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172jQuery.ajaxPrefilter("script", function (s) { if (s.cache === undefined) { s.cache = false; } if (s.crossDomain) { s.type = "GET"; s.global = false; } });jQuery.ajaxPrefilter("json jsonp", function (s, originalSettings, jqXHR) { var inspectData = s.contentType === "application/x-www-form-urlencoded" && ( typeof s.data === "string" ); if (s.dataTypes[0] === "jsonp" || s.jsonp !== false && ( jsre.test(s.url) || inspectData && jsre.test(s.data) )) { var responseContainer, jsonpCallback = s.jsonpCallback = jQuery.isFunction(s.jsonpCallback) ? s.jsonpCallback() : s.jsonpCallback, previous = window[jsonpCallback], url = s.url, data = s.data, replace = "$1" + jsonpCallback + "$2"; if (s.jsonp !== false) { url = url.replace(jsre, replace); if (s.url === url) { if (inspectData) { data = data.replace(jsre, replace); } if (s.data === data) { // Add callback manually url += (/\?/.test(url) ? "&" : "?") + s.jsonp + "=" + jsonpCallback; } } } s.url = url; s.data = data; // Install callback window[jsonpCallback] = function (response) { responseContainer = [response]; }; // Clean-up function jqXHR.always(function () { // Set callback back to previous value window[jsonpCallback] = previous; // Call if it was a function and we have a response if (responseContainer && jQuery.isFunction(previous)) { window[jsonpCallback](responseContainer[0]); } }); // Use data converter to retrieve json after script execution s.converters["script json"] = function () { if (!responseContainer) { jQuery.error(jsonpCallback + " was not called"); } return responseContainer[0]; }; // force json dataType s.dataTypes[0] = "json"; // Delegate to script return "script"; } }); 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227<!--处理跨域情况的--> jQuery.ajaxTransport("script", function (s) { // This transport only deals with cross domain requests if (s.crossDomain) { var script, head = document.head || document.getElementsByTagName("head")[0] || document.documentElement; return { send: function (_, callback) { script = document.createElement("script"); script.async = "async"; if (s.scriptCharset) { script.charset = s.scriptCharset; } script.src = s.url; // Attach handlers for all browsers script.onload = script.onreadystatechange = function (_, isAbort) { if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) { // Handle memory leak in IE script.onload = script.onreadystatechange = null; // Remove the script if (head && script.parentNode) { head.removeChild(script); } // Dereference the script script = undefined; // Callback if not abort if (!isAbort) { callback(200, "success"); } } }; // Use insertBefore instead of appendChild to circumvent an IE6 bug. // This arises when a base node is used (#2709 and #4378). head.insertBefore(script, head.firstChild); }, abort: function () { if (script) { script.onload(0, 1); } } }; } }); <!--处理xmlHttpRequest请求--> if (jQuery.support.ajax) { jQuery.ajaxTransport(function (s) { // Cross domain only allowed if supported through XMLHttpRequest if (!s.crossDomain || jQuery.support.cors) { var callback; return { send: function (headers, complete) { // Get a new xhr var xhr = s.xhr(), handle, i; // Open the socket // Passing null username, generates a login popup on Opera (#2865) if (s.username) { xhr.open(s.type, s.url, s.async, s.username, s.password); } else { xhr.open(s.type, s.url, s.async); } // Apply custom fields if provided if (s.xhrFields) { for (i in s.xhrFields) { xhr[i] = s.xhrFields[i]; } } // Override mime type if needed if (s.mimeType && xhr.overrideMimeType) { xhr.overrideMimeType(s.mimeType); } // X-Requested-With header // For cross-domain requests, seeing as conditions for a preflight are // akin to a jigsaw puzzle, we simply never set it to be sure. // (it can always be set on a per-request basis or even using ajaxSetup) // For same-domain requests, won't change header if already provided. if (!s.crossDomain && !headers["X-Requested-With"]) { headers["X-Requested-With"] = "XMLHttpRequest"; } // Need an extra try/catch for cross domain requests in Firefox 3 try { for (i in headers) { xhr.setRequestHeader(i, headers[i]); } } catch (_) { } // Do send the request // This may raise an exception which is actually // handled in jQuery.ajax (so no try/catch here) xhr.send(( s.hasContent && s.data ) || null); // Listener callback = function (_, isAbort) { var status, statusText, responseHeaders, responses, xml; // Firefox throws exceptions when accessing properties // of an xhr when a network error occured // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) try { // Was never called and is aborted or complete if (callback && ( isAbort || xhr.readyState === 4 )) { // Only called once callback = undefined; // Do not keep as active anymore if (handle) { xhr.onreadystatechange = jQuery.noop; if (xhrOnUnloadAbort) { delete xhrCallbacks[handle]; } } // If it's an abort if (isAbort) { // Abort it manually if needed if (xhr.readyState !== 4) { xhr.abort(); } } else { status = xhr.status; responseHeaders = xhr.getAllResponseHeaders(); responses = {}; xml = xhr.responseXML; // Construct response list if (xml && xml.documentElement /* #4958 */) { responses.xml = xml; } responses.text = xhr.responseText; // Firefox throws an exception when accessing // statusText for faulty cross-domain requests try { statusText = xhr.statusText; } catch (e) { // We normalize with Webkit giving an empty statusText statusText = ""; } // Filter status for non standard behaviors // If the request is local and we have data: assume a success // (success with no data won't get notified, that's the best we // can do given current implementations) if (!status && s.isLocal && !s.crossDomain) { status = responses.text ? 200 : 404; // IE - #1450: sometimes returns 1223 when it should be 204 } else if (status === 1223) { status = 204; } } } } catch (firefoxAccessException) { if (!isAbort) { complete(-1, firefoxAccessException); } } // Call complete if needed if (responses) { complete(status, statusText, responses, responseHeaders); } }; // if we're in sync mode or it's in cache // and has been retrieved directly (IE6 & IE7) // we need to manually fire the callback if (!s.async || xhr.readyState === 4) { callback(); } else { handle = ++xhrId; if (xhrOnUnloadAbort) { // Create the active xhrs callbacks list if needed // and attach the unload handler if (!xhrCallbacks) { xhrCallbacks = {}; jQuery(window).unload(xhrOnUnloadAbort); } // Add to list of active xhrs callbacks xhrCallbacks[handle] = callback; } xhr.onreadystatechange = callback; } }, abort: function () { if (callback) { callback(0, 1); } } }; } }); }]]></content>
</entry>
<entry>
<title><![CDATA[ajax源码解析-$.ajax()中常见应用示例]]></title>
<url>http://yoursite.com/2016/11/03/ajax_4/</url>
<content type="text"><![CDATA[$.ajax()中常见应用示例 cache和ifModified参数 跨域请求 cache和ifModified参数1) cache参数:GET和POST最重要的区别语义上,GET是获取指定URL上的资源,是读操作,重要的一点是不论对某个资源GET多少次,它的状态是不会改变的,在这个意义上,我们说GET是安全的(不是被密码学或者数据保护意义上的安全)。因为GET是安全的,所以GET返回的内容可以被浏览器,Cache服务器缓存起来。而POST的语意是对指定资源“追加/添加”数据,所以是不安全的,每次提交的POST,参与的代码都会认为这个操作会修改操作对象资源的状态,于是,浏览器在你按下F5的时候会跳出确认框,缓存服务器不会缓存POST请求返回内容。2) ifModified参数:通过ifModified参数提高请求性能(即:“条件GET”:Last-Modified / If-Modified-Since和ETag / If-None-Match)当你请求的资源并不是一层不变的时候,即不能简单的一直使用客户端缓存时,你可能通过将cache设置为false来发送请求,这实际上是在url加上时间戳组合成新的url,每次发送新的请求,这明显加大了服务器的压力。对于这种情况,我们可以通过ifModified参数改进缓存方式(即:cache和ifModified都设置为true),仅在请求的数据改变时重新获取。通过这种方式请求的url不会改变,并且每次都会发送到服务器,只是会有检验方法验证是否需要重新获取数据从而节省带宽和开销。更多ETag描述(优点,解决了Last-Modified无法解决的一些问题,什么场合不应该被使用) 过程如下:a) 将$.ajax()函数的cache和ifModified参数同时设置为true。b) 客户端请求服务端A,在服务端加上Last-Modified/ETag响应体一起返回。c) 客户端缓存接收到的Last-Modified/ETag响应体,并在下一次发生请求A时将缓存的Last-Modified/ETag值做为If-Modified-Since/IF-None-Match请求头一起发给服务器。d) 服务器接收If-Modified-Since/IF-None-Match后, 就根据参数值检验自上次客服端请求之后资源是否有改动 i. 若还未改动则直接返回响应304和一个空的响应体。 ii. 若已改动则重新处理数据,返回最新的请求数据。e) 这样,既保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。这一过程中,我们只需要做:服务器返回Last-Modified/ETag响应头和在服务端检验数据是否失效并采取对应处理方式。其余步骤由jQuery框架的ajax()函数完成。 关键代码如下:客服端:1234567891011121314 $('#btn_nowTime_long3').bind('click', null , function () { $.ajax('AjaxHandler.ashx?func=GetServerTime4Modified', { type: 'get', dataType: 'text', cache: true, ifModified: true, success: function (data) { if (data) alert(data); }, });}); 服务端: 123456789101112131415if(!String.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"])){ if (CheckResourceValidate()) // 检查资源有效性 { // 如果资源有效,则直接返回304状态码,客户端回去到此状态码后会从缓存中取值。 context.Response.StatusCode = 304; return; }} // 请求数据GetServerTimeAfter2Second();context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(5));// 设置Last-Modified响应体context.Response.Cache.SetLastModified(DateTime.Now); 跨域请求在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档在同一域下的内容。所谓同源是指,域名(host),协议(protocol),端口(port)相同。 URL 说明 是否允许通信 能否通过javascript解决 http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同文件夹 允许 http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同端口 不允许 能 http://www.a.com/a.js https://www.a.com/b.js 同一域名,不同协议(http和https) 不允许 不能 http://www.a.com/a.js http://70.32.92.74/b.js 域名和域名对应ip 不允许 能 http://www.cnblogs.com/a.js http://www.a.com/b.js http://script.a.com/b.js http://a.com/b.js 不同域名(host) 不允许 能 1) $.ajax()为我们提供了两种解决方案 ,不过都是只支持get方式,分别是jQuery的jQuery.ajax“jsonp”格式和jquery.getScript()(即jQuery.ajax “script”格式)方式。2) $.ajax()跨域原理分析由于javascript的安全限制“同源策略”,所以我们无法使用XMLHttpRequest直接请求别的域名下的资源。不过拥有src属性和href属性的script\img\iframe和link\a标签不受同源策略影响。$.ajax()提供的两种解决方案正是应用了动态创建script的方式来实现(即:生成script标签,src引入脚本,然后执行,最后移除script标签)。 3) jQuery.ajax()的jsonp和script方式的异同点:a) 相同:都走$.ajax() script格式的流程;不会触发全局事件和局部事件;只支持GET方式(POST请求会自动转化为GET请求);默认不启用缓存(cache:false)b) 不同:jsonp方式可以通过jsonp和jsonpCallback参数指定一个特定回调函数。4) 示例部署说明: 因为是跨域请求,所以需要在本机部署两个示例程序以模拟不同域之间的访问,并且在示例代码中需要修改“crossUrl”为目的域路径。5) jsonp示例代码: 客服端:123456789101112131415// jsonp方式跨域请求(dataType:jsonp)$('#btn_cross_req1').bind('click', null , function () { $.ajax(crossUrl, { type: 'get', dataType: 'jsonp', jsonp: 'jsonpParamName', jsonpCallback: 'crossCallback', crossDomain: true, });});function crossCallback(data) {alert('jsonp' + data); } 服务端: 123context.Response.ContentType = "text/plain";string jsonpCallbackName = reqCollection["jsonpParamName"]; context.Response.Write(String.Format("{0}('来自域:{1}的相应信息')", jsonpCallbackName, context.Request.Url.Host)); 分析:a) 因jsonp和jsonpCallback参数而改变的url如下。(即默认为:callback=jQuery随机值,更改为:jsonpParamName=crossCallback)URL:http://192.168.1.100:6567/AjaxHandler.ashx?func=CrossRequest&jsonpParamName=crossCallback&_=1368360234428b) 服务器端获取到jsonp回调函数名后,返回一个函数表达式。6) 在XMLHttpRequest Level 2中新增了跨域访问方式、接收二进制等新功能,详细请看:XMLHttpRequest2 新技巧]]></content>
</entry>
<entry>
<title><![CDATA[ajax源码解析-jQuery ajax相关函数]]></title>
<url>http://yoursite.com/2016/11/03/ajax_3/</url>
<content type="text"><![CDATA[解释了ajax源码中一些函数的使用 1) jQuery.ajaxSetup({ })jQuery.ajax()函数中的所有的参数选项都可以通过jQuery.ajaxSetup()函数来全局设置默认值。 2) $.ajax()函数的封装a) $(“”).load(url [, params] [, callback])请求远程的HTML文件代码(dataType: “html”),默认使用 GET 方式,如果传递了params参数则使用Post方式。在请求“成功”完成时将responseText属性值插入至DOM中。但不管请求是否成功完成“在最后”都会执行callback回调函数(即:complete:callback)。b) jQuery.get(url [, data] [, callback] [, type] )通过HTTP GET请求载入数据,并在请求成功时执行回调函数(即:success: callback)。c) jQuery.getJSON(url [, data] [, callback] )通过 HTTP GET 请求载入 JSON 数据。相当于: jQuery.get(url, [data],[callback], “json”)可以通过使用JSONP 形式的回调函数来加载其他网域的JSON数据。d) jQuery.getScript(url [, callback] )通过 HTTP GET 请求载入并执行一个 JavaScript 文件。相当于: jQuery.get(url, null, [callback], “script”)可以跨域调用 JavaScript 文件。e) jQuery.post(url [, data] [, callback] [, type] )通过 HTTP POST 请求载入信息,并在请求成功时执行回调函数(即:success: callback)。 3) 对象序列化a) jQuery.param(object,traditional)创建数组或对象的序列化表示,该序列化可在ajax请求时在URL查询字符串中使用。序列化过程中会使用encodeURIComponent()函数把字符串作为URI组件进行编码。encodeURIComponent() 方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ‘ ( ) 。其他字符(比如:;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。// 在param中会进行如下处理12345function( key, value ) { // 如果value是函数,则取其函数返回值 value = jQuery.isFunction( value ) ? value() : value; s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );}; 对于 jQuery 1.4,$.param() 方法将会通过深度递归的方式序列化对象,以便符合现代化脚本语言的需求,比如 PHP、Ruby on Rails 等。你可以传递traditional = true 或在ajax功能中传递包含traditional的options参数。传送门:$.param()深度递归详解和$.param() 示例b) $(“”).serializeArray()可以将一个或多个表单元素(比如 input、 textarea等),或者 form 元素本身的jQuery对象序列化为JSON对象。(非 JSON 字符串。需要使用插件或者第三方库进行字符串化操作)特别说明,元素不能被禁用(禁用的元素不会被包括在内),并且元素应当有含有 name 属性。提交按钮的值也不会被序列化。文件选择元素的数据也不会被序列化。传送门:$(“”).serializeArray() 示例c) $(“”).serialize()可以将一个或多个表单元素(比如 input、 textarea等),或者 form 元素本身的jQuery对象序列化为经过URL编码转换后的字符串,可直接用在URL查询字符串中。jQuery内部定义:123serialize: function() { return jQuery.param( this.serializeArray() );} 传送门:$(“”).serialize()示例]]></content>
</entry>
<entry>
<title><![CDATA[ajax源码解析-jQuery Ajax事件]]></title>
<url>http://yoursite.com/2016/11/03/ajax_2/</url>
<content type="text"><![CDATA[jQuery框架中,伴随Ajax请求会触发若干事件,我们可以订阅这些事件并在其中处理我们的逻辑。在jQuery中有两种Ajax事件:局部事件和全局事件。 局部事件(回调函数)在$.ajax()方法的options参数中声明,可以用来设置请求数据和获取、处理响应数据。 局部事件 具体解析 beforeSend 该函数可在发送请求前修改XMLHttpRequest对象,如添加自定义 HTTP 头。签名:function (jqXHR,s) { }函数说明:传入jqXHR、s对象 dataFilter 在请求成功之后调用。若状态码为304(未修改)则不触发此回调。签名:function (data, dataType) { return newData; } 函数说明:传入返回的数据、”dataType”参数的值。并且必须返回新的数据传递给success回调函数 success 请求成功时触发。签名:function (data,statusText,jqXHR) { } 函数说明:传入返回的数据、描述状态的字符串”success”、jqXHR对象 error 请求失败时调用此函数。签名:function (jqXHR, textStatus, errorThrown) { } 函数说明:传入jqXHR对象、描述状态的字符串”error”、错误信息 complete 请求完成后回调函数 (请求成功或失败之后均调用)签名:function (jqXHR, textStatus) { } 函数说明:传入jqXHR对象、描述状态的字符串(可能值:”No Transport”、”timeout”、”notmodified”—304 “、”parsererror”、”success”、”error”) 定义方式例如:12345678910$.ajax({ // ... beforeSend: function(){ // Handle the beforeSend event }, complete: function(){ // Handle the complete event } // ...}); 全局事件 每次Ajax请求都会触发,它会向DOM中的所有元素广播,你只需为DOM中任意元素bind好全局事件即会触发(若绑定多次,则会依次触发为事件注册的回调函数)。 全局事件 具体解析 ajaxStart 开始新的Ajax请求,并且此时jQuery对象上没有其他ajax请求正在进行。签名:function(e) 函数说明:传入事件对象 ajaxSend 当一个Ajax请求开始时触发签名:function(e,jqXHR,s) 函数说明:传入事件对象、jqXHR、s对象 ajaxSuccess 全局的请求成功 签名:function(e,jqXHR,s,data) 函数说明:传入事件对象、jqXHR、s对象、请求成功返回的相应数据 ajaxError 全局的发生错误时触发 签名:function(e,jqXHR,s,errorData) 函数说明:传入事件对象、jqXHR、s对象、请求失败返回的错误信息 ajaxComplete 全局的请求完成时触发 签名:function(e,jqXHR,s) 函数说明:传入事件对象、jqXHR、s对象 ajaxStop 当jQuery对象上正在进行Ajax请求都结束时触发。签名:function(e) 函数说明:传入事件对象 全局事件在jQuery中的声明方式:12345jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ jQuery.fn[ o ] = function( f ){ return this.on( o, f ); };}); 所以我们可以使用下面两种方式定义全局事件:1234// 可以用bind来绑定,用unbind来取消绑定。$("#loading").bind("ajaxSend", function(){ … });或者:$("#loading").ajaxStart(function(){ … }); ajax方法完整的事件流成功的ajax事件流失败的ajax事件流 示例:$.ajax()触发的事件(局部事件和全局事件)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051// 全局事件$("#div_event").ajaxStart(function (e) { doAddEvent4textarea('txt_event', '触发ajaxStart回调函数');});$("#div_event").ajaxSend(function (e) { doAddEvent4textarea('txt_event', '触发ajaxSend回调函数');});$("#div_event").ajaxSuccess(function (e, jqXHR, s, data) { doAddEvent4textarea('txt_event', '触发ajaxSuccess回调函数');});$("#div_event").ajaxError(function (e, jqXHR, s, errorData) { doAddEvent4textarea('txt_event', '触发ajaxError回调函数');});$("#div_event").ajaxComplete(function (e, jqXHR, s) { doAddEvent4textarea('txt_event', '触发ajaxComplete回调函数');});$("#div_event").ajaxStop(function (e) { doAddEvent4textarea('txt_event', '触发ajaxStop回调函数');});// 局部事件function bindLocalEvent(e) { var textareaid = e.data.textareaid; var global = e.data.global; $.ajax('AjaxHandler.ashx?func=btn_nowTime_long', { type: 'get', dataType: 'text', global: global, cache: false, beforeSend: function (jqXHR, s) { doAddEvent4textarea(textareaid, '触发beforeSend回调函数'); }, dataFilter: function (data, dataType) { doAddEvent4textarea(textareaid, '触发dataFilter回调函数'); }, success: function (data, statusText, jqXHR) { doAddEvent4textarea(textareaid, '触发success回调函数'); }, error: function (jqXHR, textStatus, errorThrown) { doAddEvent4textarea(textareaid, '触发error回调函数'); }, complete: function (jqXHR, textStatus) { doAddEvent4textarea(textareaid, '触发complete回调函数'); } });}function doAddEvent4textarea(textareaid, txt) { var textarea = $("#" + textareaid); textarea.val(textarea.val() + '\r\n' + txt);} $.ajax()方法的全局事件典型用例 你的页面存在多个甚至为数不少的ajax请求,但是这些ajax请求都有相同的消息机制。ajax请求开始前显示一个提示框,提示“正在读取数据”;ajax请求成功时提示框显示“数据获取成功”;ajax请求结束后隐藏提示框。 a) 不使用全局事件的做法是:给$.ajax()加上beforeSend、success、complete回调函数,在回调函数中加上处理提示框。b) 使用全局事件的做法是:123456$(document).ajaxStart(onStart) .ajaxComplete(onComplete) .ajaxSuccess(onSuccess);function onStart(event) { //..... }function onComplete(event, xhr, settings) { //..... }function onSuccess(event, xhr, settings) { //..... }]]></content>
</entry>
<entry>
<title><![CDATA[技术文档]]></title>
<url>http://yoursite.com/2016/11/03/tecLink/</url>
<content type="text"><![CDATA[http相关 jQuery相关等技术文档 1) jQuery相关jQueryAPI文档jQuery百度百科(Eg:模块,历史版本)Ajax 技术资源中心(IBM)这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。jQuery.ajax()中的预过滤器和分发机制函数inspectPrefiltersOrTransports详解jQuery的deferred对象详解$.param()深度递归详解 2) XMLHttpRequest Level 2 的新功能相关XMLHttpRequest 增强功能XMLHttpRequest Level 2 使用指南XMLHttpRequest2 新技巧 3) 跨域请求相关JavaScript跨域总结与解决办法总结了5种js跨域方式:利用iframe标签和document.domain属性、动态创建scrip、利用iframe标签和location.hash属性、window.name实现的跨域数据传输、使用HTML5 postMessage、利用flash跨域。域名和IP地址及域名解析xhr注入_百度百科说说JSON和JSONP 4) HTTP相关HTTP深入浅出 http请求1) 介绍了一次HTTP通信的7个步骤:建立TCP连接、Web浏览器向Web服务器发送请求命令、Web浏览器发送请求头信息、Web服务器应答、Web服务器发送应答头信息、Web服务器向浏览器发送数据、Web服务器关闭TCP连接2) 介绍HTTP请求格式HTTP GET和POST的区别HTTP 头部详解HTTP Content-type对照表格式:Content-Type: [type]/[subtype]; parameterHTTP状态码一览表(HTTP Status Code) 5)Jquery其他部分不定义JQuery插件,不要说会JQuery]]></content>
</entry>
<entry>
<title><![CDATA[ajax源码解析-源码流程]]></title>
<url>http://yoursite.com/2016/11/02/ajax_1/</url>
<content type="text"><![CDATA[ajax源码 了解执行的整个过程 参照注释看相关文章 ajax 源码核心1.s对象和jqXHR对象2.jQuery. ajaxPrefilter和jQuery. ajaxTransport3.跨域请求和xmlHttpRequest请求4.deferred 参考ajax源码注解 流程图 源码注解123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478ajax: function( url, options ) { //ajax方法参数调整,如果url是object,这是我们一般的调用方式 // If url is an object, simulate pre-1.5 signature if ( typeof url === "object" ) { options = url; url = undefined; } //option是一个对象 // Force options to be an object options = options || {}; var // Cross-domain detection vars parts, // Loop variable i, // URL without anti-cache param cacheURL, // Response headers as string responseHeadersString, // timeout handle timeoutTimer, // To know if global events are to be dispatched fireGlobals, transport, // Response headers responseHeaders, // Create the final options object // 由ajaxSetting和入口传入的option合成的对象s, //jQuery.ajaxSetup等函数的使用 参见文章ajax源码解析-jQuery ajax相关函数 //对象s内的各个参数详解,参见文章ajax源码解析-s对象和jqXHR对象 s = jQuery.ajaxSetup( {}, options ), // Callbacks context //设置context,如果没有context那么就是返回的最终的options=ajaxSettings+options(用户调用ajax方法时候传送的option) callbackContext = s.context || s, //如果传入的对象有context,同时context是DOM对象或者是jQuery对象,那么把该DOM对象封装为jQuery对象 //如果不满足也就是没有context或者context不是DOM对象和jQuery对象,那么globalEventContext就是jQuery.event对象! // Context for global events is callbackContext if it is a DOM node or jQuery collection globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? jQuery( callbackContext ) : jQuery.event, //创建Deferred对象 // Deferreds deferred = jQuery.Deferred(), //创建Callbacks对象 completeDeferred = jQuery.Callbacks("once memory"), //获取最终options的statusCode参数,默认是空对象! // Status-dependent callbacks statusCode = s.statusCode || {}, // Headers (they are sent all at once) requestHeaders = {}, requestHeadersNames = {}, // The jqXHR state state = 0, // Default abort message strAbort = "canceled", //创建一个伪的xhr对象,该对象有readyState,getResponseHeader,getAllResponseHeaders,setRequestHeader //overrideMimeType,statusCode,abort方法和属性! // Fake xhr jqXHR = { readyState: 0, // Builds headers hashtable if needed getResponseHeader: function( key ) { var match; //状态是2的时候才能获取数据 if ( state === 2 ) { if ( !responseHeaders ) { responseHeaders = {}; //rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL //responseHeaders的键名就是第一个捕获组的数据,第二个键值就是第二个捕获组数据! while ( (match = rheaders.exec( responseHeadersString )) ) { responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; } } //返回这个key对应的键值! match = responseHeaders[ key.toLowerCase() ]; } return match == null ? null : match; }, // Raw string //如果状态是2,那么就是responseHeadersString getAllResponseHeaders: function() { return state === 2 ? responseHeadersString : null; }, // Caches the header //设置HTTP请求头的时候,头是小写的 setRequestHeader: function( name, value ) { var lname = name.toLowerCase(); //如果state为0那么就缓存头,把结果放入requestHeaders中!但是要提前查找requestHeadersNames if ( !state ) { name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; requestHeaders[ name ] = value; } return this; }, // Overrides response content-type header //如果state=0那么可以覆盖这个mimetype! overrideMimeType: function( type ) { if ( !state ) { s.mimeType = type; } return this; }, // Status-dependent callbacks statusCode: function( map ) { var code; if ( map ) { if ( state < 2 ) { for ( code in map ) { // Lazy-add the new callback in a way that preserves old ones statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; } } else { // Execute the appropriate callbacks jqXHR.always( map[ jqXHR.status ] ); } } return this; }, // Cancel the request //取消请求 abort: function( statusText ) { var finalText = statusText || strAbort; if ( transport ) { transport.abort( finalText ); } done( 0, finalText ); return this; } }; function done( status, nativeStatusText, responses, headers ) { var isSuccess, success, error, response, modified, statusText = nativeStatusText; // Called once //如果state是2,那么直接返回! if ( state === 2 ) { return; } // State is "done" now //state设置为2表示不会再次执行了! state = 2; // Clear timeout if it exists //如果timeoutTimer存在,那么直接清除! if ( timeoutTimer ) { clearTimeout( timeoutTimer ); } // Dereference transport for early garbage collection // (no matter how long the jqXHR object will be used) transport = undefined; // Cache response headers //获取response的头部信息,默认是空! responseHeadersString = headers || ""; // Set readyState //如果status>0那么把readyState设置为4! jqXHR.readyState = status > 0 ? 4 : 0; // Determine if successful //如果status在指定的区间内那么表示成功! isSuccess = status >= 200 && status < 300 || status === 304; // Get response data //如果done方法有responses那么对他进行处理! if ( responses ) { response = ajaxHandleResponses( s, jqXHR, responses ); } // Convert no matter what (that way responseXXX fields are always set) response = ajaxConvert( s, response, jqXHR, isSuccess ); // If successful, handle type chaining if ( isSuccess ) { // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. //如果ifModified存在,那么就要设置If-Modified-Since和If-None-Match头! if ( s.ifModified ) { modified = jqXHR.getResponseHeader("Last-Modified"); if ( modified ) { jQuery.lastModified[ cacheURL ] = modified; } modified = jqXHR.getResponseHeader("etag"); if ( modified ) { jQuery.etag[ cacheURL ] = modified; } } // if no content //204表示没有数据,这时候页面就不需要跳转!还是停留在当前页面! if ( status === 204 || s.type === "HEAD" ) { statusText = "nocontent"; //如果是304那么表示没有修改内容! // if not modified } else if ( status === 304 ) { statusText = "notmodified"; //如果有数据,那么我们获取到数据! // If we have data, let's convert it } else { statusText = response.state; success = response.data; error = response.error; isSuccess = !error; } } else { //这里的else表示请求失败!我们从statusText获取到错误的信息,然后对statusText进行处理! // We extract error from statusText // then normalize statusText and status for non-aborts error = statusText; if ( status || !statusText ) { statusText = "error"; if ( status < 0 ) { status = 0; } } } //为jqXHR设置数据 // Set data for the fake xhr object jqXHR.status = status; jqXHR.statusText = ( nativeStatusText || statusText ) + ""; // Success/Error if ( isSuccess ) { //如果成功了请求,那么我们传入的Context是callbackContext,传入的数据是response.data //response.status和jqXHR对象 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); } else { deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); } // Status-dependent callbacks jqXHR.statusCode( statusCode ); statusCode = undefined; //如果是全局执行 if ( fireGlobals ) { globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", [ jqXHR, s, isSuccess ? success : error ] ); } // Complete //这个对象添加的所有函数执行,表示完成,不是成功,失败,而是complelte表示不管成功与否都是会执行的! //而且只会执行一次! completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); if ( fireGlobals ) { //globalEventContext也就是最终options的事件,触发事件ajaxComplete! globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); // Handle the global AJAX counter //如果全局的ajax计数器已经是0了,那么就会触发ajaxStrop事件! if ( !( --jQuery.active ) ) { jQuery.event.trigger("ajaxStop"); } } } // Attach deferreds // 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。 // 通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。 // deferred对象就是jQuery的回调函数解决方案 '延迟执行' //让jqXHR具有promise的所有的属性和方法!不包括状态改变的方法,如resollveWith等 //同时jqXHR的complete对应于completeDeferred的add方法,但是该jqXHR中也封装了三个Callbacks对象 //但是这里没有用内部的Callbacks对象,而是采用一个新的Callbacks对象 //completeDeferred = jQuery.Callbacks("once memory"), deferred.promise( jqXHR ).complete = completeDeferred.add; //success调用的promise对象内置的done方法对应于的Callbacks对象 jqXHR.success = jqXHR.done; //error方法调用的promise对象内置的fail方法对应的Callbacks对象! //注意:这个内置的promise对象的progress方法对应的Callbacks对象没有用到! jqXHR.error = jqXHR.fail; // 处理url 去掉hash地址和添加协议 // 例如 var c="//brandshow.58.com/show/loadBrandAds#top" // c.replace(rhash, "").replace(rprotocol, ajaxLocParts[1] + "//"); // 结果"http://brandshow.58.com/show/loadBrandAds"--> s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); //type就是get或者post。这个方式可以通过用户传入的对象的method或者type或者最终的对象的method或者type获取! // Alias method option to type as per ticket #12004 s.type = options.method || options.type || s.method || s.type; // Extract dataTypes list //取出dataType两边的空格,同时通过空格进行分组得到一个数组!dataType="html" s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; //如果没有crossDomain对象 // A cross-domain request is in order when we have a protocol:host:port mismatch if ( s.crossDomain == null ) { parts = rurl.exec( s.url.toLowerCase() ); //parts返回值(以数组形式包含协议 域名 端口号;然后分别和当前地址的协议 域名 端口号比较,有一处不等则判断为跨域 ) // 例如:["http://api.house.58.com", "http:", "api.house.58.com", undefined] //如果在同一个域名里面那么这里的判断都是false,结果就是crossDomain为false //如果不再同一个域名里面,那么这里的判断都是true,结果就是crossDomain为true! s.crossDomain = !!( parts && ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) ); } //如果存在data同时存在processData同时data不是string! //traditional是为了兼容jQuery<1.3.2行为的! // Convert data if not already a string if ( s.data && s.processData && typeof s.data !== "string" ) { s.data = jQuery.param( s.data, s.traditional ); } // Apply prefilters // prefilters前置过滤器 // jQuery1.5以后,AJAX模块提供了三个新的方法用于管理、扩展AJAX请求,分别是: // 1.前置过滤器 jQuery. ajaxPrefilter // 2.请求分发器 jQuery. ajaxTransport, // 3.类型转换器 ajaxConvert // prefilters对象 Object {json: Array[1], jsonp: Array[1], script: Array[1]} <!--前置过滤器主要预处理参数 举例 dataType:json或者jsonp 会一次经过jQuery. ajaxPrefilter("json jsonp")和jQuery. ajaxPrefilter("script") 结果:url会拼接上s.jsonp+jsonpcallback(如?callback=jQuery4781297478394_481274389) s.cache=false; 如果是跨域 s.type = "GET"; s.global = false; --> //参见文章ajax源码解析-jQuery. ajaxPrefilter和jQuery. ajaxTransport inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); //如果在预过滤器中已经终止了请求,那么直接返回jqXHR对象! // If request was aborted inside a prefilter, stop there if ( state === 2 ) { return jqXHR; } // We can fire global events as of now if asked to // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) //如果是global参数,那么我们直接trigger事件ajaxStart! fireGlobals = jQuery.event && s.global; // Watch for a new set of requests if ( fireGlobals && jQuery.active++ === 0 ) { jQuery.event.trigger("ajaxStart"); } // Uppercase the type //把type变成大写 s.type = s.type.toUpperCase(); // Determine if request has content //rnoContent = /^(?:GET|HEAD)$/ //也就是如果没有指定type也就是请求方式! s.hasContent = !rnoContent.test( s.type ); // Save the URL in case we're toying with the If-Modified-Since // and/or If-None-Match header later on //获取url参数! cacheURL = s.url; // More options handling for requests with no content //如果指定了请求方式,如get,post等! if ( !s.hasContent ) { //没有指定请求方式的时候有传递数据! // If data is available, append data to url if ( s.data ) { //var rquery = (/\?/); //如果url后面有问号,那么直接把参数绑定到问号后面就可以了!否则添加问号在绑定! //同时删除数据! cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); // #9682: remove data so that it's not used in an eventual retry delete s.data; } // Add anti-cache in url if needed //如果指定了cache为false表示不能进行数据缓存,那么会在url后面添加一个当前时间! if ( s.cache === false ) { s.url = rts.test( cacheURL ) ? // If there is already a '_' parameter, set its value //var nonce = jQuery.now(); cacheURL.replace( rts, "$1_=" + nonce++ ) : // Otherwise add one to the end cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; } } // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. //如果添加了ifModified头 //var lastModified={} if ( s.ifModified ) { //如果lastModified保存了这个cacheURL也就是这个URL有缓存了!那么直接添加头If-Modified-Since数据为 //jQuery.lastModified[ cacheURL ]获取到的数据! if ( jQuery.lastModified[ cacheURL ] ) { jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); } //如果在etag: {}中保存了这个URL //那么添加If-None-Match,因为Etag和if-None-Match是一对,Last-Modified和If-Modified-Since是一对! if ( jQuery.etag[ cacheURL ] ) { jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); } } // Set the correct header, if data is being sent //如果有数据传送,同时也指定了get,post方法,同时contentType也指定! //那么添加一个头Content-Type! if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { jqXHR.setRequestHeader( "Content-Type", s.contentType ); } // Set the Accepts header for the server, depending on the dataType //同时添加请求头Accept //(1)如果指定了dataType,同时accepts中dataType存在,也就是必须是指定的data[type] jqXHR.setRequestHeader( "Accept", s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? // allTypes = "*/".concat("*"); //如果支持的数据类型是内置的类型,那么获取内置的值,如text获取的就是"text/plain" //同时dataTypes[0]不是"*",那么我们加上一个逗号,同时加上后面剩余的部分! /* var allTypes = "*/".concat("*"); //打印 //alert(allTypes); //最后的格式就是:text/html,*/*;q=0.01 //如果传入的dataType就是*,那么最后的结果就是"*/*" s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : s.accepts[ "*" ] ); // Check for headers option //如果还定义了headers选项,那么会被逐个发送到服务器端! for ( i in s.headers ) { jqXHR.setRequestHeader( i, s.headers[ i ] ); } // Allow custom headers/mimetypes and early abort //如果指定了beforeSend,同时beforeSend的函数调用的结果是false或者state是2,那么取消这次请求 //beforeSend中传入的参数为callbackContext = s.context || s也就是最终对象的context参数为上下文 //第一个参数是XHR对象,第二个参数是最终的options对象! if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { // Abort if not done already and return return jqXHR.abort(); } // aborting is no longer a cancellation strAbort = "abort"; // Install callbacks on deferreds //往jqXHR["success"]和jqXHR["error"],jqXHR["complete"]中添加回调函数 //回调函数就是通过最终options对象获取到的success,error,complete函数! for ( i in { success: 1, error: 1, complete: 1 } ) { jqXHR[ i ]( s[ i ] ); } // Get transport //传入的参数是transports对象!这个函数里面会判断是否传入了transports transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); // If no transport, we auto-abort if ( !transport ) { done( -1, "No Transport" ); } else { //如果有transport那么readyState就是1,表示 (载入)已调用send()方法,正在发送请求,也就是请求的发送是在 //inspectPrefiltersOrTransports里面完成的! jqXHR.readyState = 1; // Send global event //指示是否触发全局Ajax事件。将该值设为false将阻止全局事件处理函数被触发 //fireGlobals = jQuery.event && s.global; //如果是表示全局ajax事件,那么我们要调用ajaxSend方法!同时为这个方法传入参数jqXHR和最终option! if ( fireGlobals ) { globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); } // Timeout //如果指定了async同时timeout>0表示指定了隔多少秒就放弃 //一个超时调用,超时直接调用abort方法! if ( s.async && s.timeout > 0 ) { timeoutTimer = setTimeout(function() { jqXHR.abort("timeout"); }, s.timeout ); } //如果有transport,那么调用send方法! try { state = 1; <!--经过请求分发器的处理 返回的对象格式一致(不论是跨域请求还是非跨域请求) 即{send:{},abort:{}}--> transport.send( requestHeaders, done ); } catch ( e ) { // Propagate exception as error if not done if ( state < 2 ) { done( -1, e ); // Simply rethrow otherwise } else { throw e; } } }]]></content>
</entry>
<entry>
<title><![CDATA[ajax源码解析-s对象和jqXHR对象]]></title>
<url>http://yoursite.com/2016/10/31/ajax/</url>
<content type="text"><![CDATA[jQuery.ajax( [url,] options ) 通过 HTTP 请求加载远程数据。返回值:$.ajax() 返回jqXHR对象(jqXHR对象:为XMLHttpRequest对象的超集)。可用于手动终止请求abort()、为ajax函数设置额外的回调函数等。 ajax内部实现的两个重要对象:s对象和jqXHR对象。 s对象 s对象由默认设置jQuery.ajaxSettings对象、options参数集合和jQuery.ajaxSetup({})默认设置合并而成s对象。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081var s = jQuery.ajaxSetup({}, options)jQuery.extend({ ajaxSetup: function (target, settings) { if (settings) { // Building a settings object ajaxExtend(target, jQuery.ajaxSettings); } else { // Extending ajaxSettings settings = target; target = jQuery.ajaxSettings; } ajaxExtend(target, settings); return target; }, ajaxSettings: { url: ajaxLocation, isLocal: rlocalProtocol.test(ajaxLocParts[1]), global: true, type: "GET", contentType: "application/x-www-form-urlencoded", processData: true, async: true, /* timeout: 0, data: null, dataType: null, username: null, password: null, cache: null, traditional: false, headers: {}, */ accepts: { xml: "application/xml, text/xml", html: "text/html", text: "text/plain", json: "application/json, text/javascript", "*": allTypes }, contents: { xml: /xml/, html: /html/, json: /json/ }, responseFields: { xml: "responseXML", text: "responseText" }, // List of data converters // 1) key format is "source_type destination_type" (a single space in-between) // 2) the catchall symbol "*" can be used for source_type converters: { // Convert anything to text "* text": window.String, // Text to html (true = no transformation) "text html": true, // Evaluate text as a json expression "text json": jQuery.parseJSON, // Parse text as xml "text xml": jQuery.parseXML }, // For options that shouldn't be deep extended: // you can add your own custom options here if // and when you create one that shouldn't be // deep extended (see ajaxExtend) flatOptions: { context: true, url: true } }, }) 参数名 描述 可由ajax的options参数设置 url (默认: 当前页地址) 要请求的目的URL地址。 username password 用于响应HTTP访问认证请求的用户名及密码 type (默认: “GET”) 请求方式 (“POST” 或 “GET”)。注意:其它 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持。 dataType 预期服务器返回的数据类型。如果不指定,jQuery将自动根据 HTTP 包 MIME 信息来智能判断,比如 XML MIME 类型就被识别为 XML。随后服务器端返回的数据会根据这个值解析后,传递给回调函数。 必须确保网页服务器报告的 MIME 类型与我们选择的dataType所匹配。比如说,XML的话,服务器端就必须声明 text/xml 或者 application/xml 来获得一致的结果。 可用值: 1.”xml”返回 XML 文档,可用jQuery处理。 2.”html”返回纯文本 HTML 信息;包含的 script 标签会在插入dom时执行。 3.”script”返回纯文本 JavaScript 代码,常常用于跨域请求。不会触发全局事件和局部事件;只支持GET方式(POST请求会自动转化为GET请求);默认不启用缓存(cache:false) 4.”json”返回 JSON 数据。JSON 数据是一种能很方便通过 JavaScript 解析的结构化数据。 5.”jsonp”JSONP 格式,用于跨域请求。6.”text”返回纯文本字符串 其中,text 和 xml 类型返回的数据不会经过处理。数据仅仅简单的将XMLHttpRequest的responseText或responseHTML属性传递给 success 回调函数。 如果指定了 script 或者jsonp类型,那么当从服务器接收到数据时,实际上是用了script标签而不是XMLHttpRequest对象。 这种情况下,$.ajax() 不再返回一个XMLHttpRequest对象,并且也不会传递事件处理函数,比如beforeSend。 contentType (默认: “application/x-www-form-urlencoded”)标明发送或者接收的实体的MIME类型。当“非GET或HEAD请求”的HTTP请求时,会被设置为HTTP头请求信息。 mimeType 多用途互联网邮件扩展(MIME,Multipurpose Internet Mail Extensions);用于重写服务器端响应的MIME类型。 data 发送到服务器的数据。可以是一个查询字符串,比如 key1=value1&key2=value2 ,也可以是一个映射,比如 {key1: ‘value1’, key2: ‘value2’} 。如果使用了后者的形式,则数据在发送前会通过jQuery.param()函数转换成查询字符串。这个处理过程也可以通过设置processData选项为false来回避。 processData (默认: true) 默认情况下,发送到服务器的数据(即data参数)将被转换为字符串以配合默认内容类型 “application/x-www-form-urlencoded”。如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。 jQuery中的处理方式:1) async (默认: true) 默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。 timeout 设置请求超时时间(毫秒)。通过setTimeout(fn,time)实现。 cache (默认: true)dataType为 script 和jsonp时默认为 false。设置为 false 将不缓存此页面。 当使用GET或HEAD方式发送请求时要添加时间戳参数 (net Date()).getTime() 来保证每次发送的URL不同, 可以避免浏览器缓存.(只有GET和HEAD方式的请求浏览器才会缓存) jQuery中的处理方式:2) ifModified (默认: false) 仅在服务器数据改变时获取新数据。通过响应头If-Modified-Since、IF-None-Match和请求头Last-Modified、Etag提高GET或HEAD方式请求效率。(只有GET和HEAD方式的请求浏览器才会缓存) global (默认: true) 是否触发全局 AJAX 事件。设置为 false 将不会触发全局AJAX 事件:ajaxStart、ajaxSend、ajaxSuccess、ajaxError、ajaxComplete、ajaxStop。(比如请求频繁时可禁用全局AJAX事件提高效率) context (默认:true) 这个对象用于设置Ajax相关回调函数的上下文,让回调函数内this指向这个对象。如果不设定这个参数,那么回调函数中的this就指向调用本次AJAX请求时传递的options参数载体“s对象”。但对于全局Ajax事件来说,this都是指向全局事件所绑定的元素。 jsonp 指定获得jsonp回调函数名的参数名(默认为:callback)。这个值用来替代URL中”callback=?”里的”callback”部分,比如{jsonp:’onJsonPLoad’}会替换为将”onJsonPLoad=?”传给服务器。 jsonpCallback 为jsonp请求指定一个回调函数名。jsonpCallback参数一般为字符串,也可接收函数(该函数返回字符串)。默认情况下生成随机函数名:”jQuery” + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, “” ) + jQuery.now() crossDomain (默认:null)false:同域请求;true跨域请求。倘若crossDomain标识为null,则jQuery会自动根据本地url、端口来解析。可以根据需求直接赋值来提高性能。 通常情况下由服务器自动解析即可,但如果你想在同一域中强制跨域请求(像JSONP一样),那么将crossDomain为true,这允许你将服务器端重定向到另一个域。 scriptCharset 只有当请求时dataType为”jsonp”或”script”,并且type是”GET”才会用于修改charset。 因为此时是动态创建script来完成脚本加载,但是如果js中的编码与页面的编码不一致时,js可能加载失败或者显示乱码或者IE下报某符号错误。设置此参数就相当于为script标签设置charset属性。 hearders (默认:{}) 设置HTTP请求头数据”{键:值}”。此设置发生在:jQuery所有影响HTTP头的参数(options)设置之后,beforeSend回调函数之前。 statusCode (默认:{}) 定义一组HTTP状态码与回调函数的映射,当响应的状态码有匹配statusCode则会触发对应回调函数。例如,如果响应状态是404,将触发以下警报: jQuery中定义:3) traditional 如果你想要用传统的方式来序列化数据,那么就设置为true。请参考$.param()深度递归详解。 xhrFields 声明附加到XMLHttpRequest对象的自定义“key-value”数组。例如,如果需要的话,你可以用它来设置跨域的withCredentials为true,即: xhrFields: { withCredentials: true } 5个局部事件 beforeSend、dataFilter、success、error、complete。(详见后面事件介绍部分) 由ajax函数内部解析或内部提供 dataTypes 由dataType按空格拆分所得。 isLocal 根据协议确定当前url请求的是否为本地请求。 jQuery中定义默认值为:4) hasContent 非GET或HEAD请求为true,用于处理data和contentType参数。 contents 一个”{类型字符串:正则表达式}”的对象,倘若dataTypes[0]为“*”时,用contents中的正则表达式去匹配contentType,匹配成功则用“类型字符串”覆盖dataTypes[0]。 jQuery内部定义如下:5) accepts 浏览器能够处理的媒体类型,其值取决于dataTypes[0]参数。 jQuery内部定义如下:6) responseFields jqXHR超集设置“数据类型:属性”对应关系,在返回响应数据时,用于确定创建哪个属性变量。 jQuery中定义如下:7) converters 存储数据类型对应的转换器,根据dataTypes获取对应转换器,用于对响应数据response进行处理。该处理发生在dataFilter回调函数之后。 jQuery中定义如下:8) jQuery内部实现方式1) s.processData123if ( s.data&&s.processData&&typeofs.data !== "string" ) { s.data = jQuery.param(s.data, s.traditional );} 2)s.cache1234567if ( s.cache === false ) { var ts = jQuery.now(), // rts = /([?&])_=[^&]*/尝试替换 ret = s.url.replace( rts, "$1_=" + ts ); // rquery = /\?/如果没有替换任何内容,则把时间戳加到url最后 s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );} 3)statusCode12345$.ajax({ statusCode: {404: function() { alert('page not found'); }}); 4)isLocal1isLocal:/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/.test(/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/.exec(url)) 5)contents123456contents: { xml: /xml/, html: /html/, json: /json/, script: /javascript|ecmascript/} 6)accepts12345678accepts: { xml: "application/xml, text/xml", html: "text/html", text: "text/plain", json: "application/json, text/javascript", script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript", "*": allTypes // dataTypes[0]匹配不上时取此值} 7)responseFields1234responseFields: { xml: "responseXML", text: "responseText"} 8)converters12345678910converters: { "* text": window.String, "text html": true, "text json": jQuery.parseJSON, "text xml": jQuery.parseXML, "text script": function( text ) { jQuery.globalEval( text ); // 执行脚本 return text; }} jqXHR对象jqXHR对象为不同浏览器内置的XMLHttpRequest提供了一致的超集。对于XMLHttpRequest之外的传输机制,比如JSONP请求,jXHR对象也可以进行处理。超集与真子集:如果一个集合S2中的每一个元素都在集合S1中,且集合S1中可能包含S2中没有的元素,则集合S1就是S2的一个超集。 S1是S2的超集,则S2是S1的真子集,反之亦然。 jqXHR对象我们常常使用如下成员,这些成员主要用于ajax的全局事件和局部事件,并且做为$.ajax()函数返回值返回。12345678910jqXHR:{ readyState ,setRequestHeader: function( name, value ) ,getAllResponseHeaders: function() ,getResponseHeader: function( key ) ,overrideMimeType: function( type ) ,abort: function( statusText ) ,responseText ,responseXML} 另外,jqXHR的全部成员如下: 1.在图中我们看到一些陌生的函数,比如:done()、fail()、promise()、isResolve()、isRejected()、then()、always()、progress()等,都是jQuery的deferred对象API。 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。 2.通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。但是,在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。 简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是”延迟”,所以deferred对象的含义就是”延迟”到未来某个点再执行。 它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。 更专业的资源:jQuery的deferred对象详解]]></content>
</entry>
<entry>
<title><![CDATA[hexo搭建个人博客]]></title>
<url>http://yoursite.com/2016/10/28/hexo/</url>
<content type="text"><![CDATA[搭建博客参考文章Next主题]]></content>
</entry>
<entry>
<title><![CDATA[JSON 格式]]></title>
<url>http://yoursite.com/2016/10/28/JSON/</url>
<content type="text"><![CDATA[JSON格式(JavaScript Object Notation的缩写)是一种用于数据交换的文本格式 JSON格式JSON对值的类型和格式有严格的规定。 1.复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。2.简单类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。3.字符串必须使用双引号表示,不能使用单引号。4.对象的 键名必须放在双引号里面。5.数组或对象最后一个成员的后面,不能加逗号。 以下是合格的JSON值。1234["one", "two", "three"]{ "one": 1, "two": 2, "three": 3 }{"names": ["张三", "李四"] }[ { "name": "张三"}, {"name": "李四"} ] 以下是不合格的JSON值。123456789{ name: "张三", 'age': 32 } // 属性名必须使用双引号[32, 64, 128, 0xFFF] // 不能使用十六进制值{ "name": "张三", "age": undefined } // 不能使用undefined{ "name": "张三", "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'), "getName": function() { return this.name; }} // 不能使用函数和日期对象 需要==注意==的是,空数组和空对象都是合格的JSON值,null本身也是一个合格的JSON值。ES5新增了JSON对象,用来处理JSON格式数据。它有两个方法:JSON.stringify()和JSON.parse()。 JSON.stringify() JSON.stringify方法用于将一个值转为字符串。该字符串应该 符合JSON格式,并且可以被JSON.parse方法还原 第一个参数1234567JSON.stringify('abc') // ""abc"" JSON.stringify(1) // "1" JSON.stringify(false) // "false" JSON.stringify([]) // "[]" JSON.stringify({}) // "{}" JSON.stringify([1, "false", false])// '[1,"false",false]' JSON.stringify({ name: "张三" })// '{"name":"张三"}' 注意:对于原始类型的字符串,转换结果会带双引号,即字符串abc会被转成”abc”,这是因为将来还原的时候,双引号可以让JavaScript引擎知道,abc是一个字符串,而不是一个变量名。 12345JSON.stringify({ f: function(){}, a: [ function(){}, undefined ]});// "{"a": [null,null]}" 如果原始对象中,有一个 成员的值是undefined、函数或XML对象,这个成员会被省略。如果 数组的成员是undefined、函数或XML对象,则这些值被转成null。 正则对象会被转成空对象。要是正则对象装换成字符串要借助toJSON方法,后面介绍了12JSON.stringify(/foo/) // "{}"JSON.stringify方法会忽略对象的不可遍历属性。 123456789101112var obj = {};Object.defineProperties(obj, { 'foo': { value: 1, enumerable: true }, 'bar': { value: 2, enumerable: false }});JSON.stringify(obj); // {"foo":1} 上面代码中,bar是obj对象的不可遍历属性,JSON.stringify方法会忽略这个属性。 第二个参数JSON.stringify方法还可以接受一个数组,作为第二个参数,指定需要转成字符串的属性。12345678var obj = { 'prop1': 'value1', 'prop2': 'value2', 'prop3': 'value3'};var selectedProperties = ['prop1', 'prop2'];JSON.stringify(obj, selectedProperties)// "{"prop1":"value1","prop2":"value2"}" 上面代码中,JSON.stringify方法的第二个参数指定,只转prop1和prop2两个属性。 这个类似“白名单”的数组,只对对象的属性有效,对数组无效。1234JSON.stringify(['a', 'b'], ['0'])// "["a","b"]"JSON.stringify({0: 'a', 1: 'b'}, ['0'])// "{"0":"a"}" 上面代码中,第二个参数指定JSON格式只转0号属性,实际上对数组是无效的,只对对象有效。 第二个参数还可以是一个函数,用来更改JSON.stringify的默认行为。12345678function f(key, value) { if (typeof value === "number") { value = 2 * value; } return value;}JSON.stringify({ a: 1, b: 2 }, f)// '{"a": 2,"b": 4}' 上面代码中的f函数,接受两个参数,分别是被转换的对象的键名和键值。如果键值是数值,就将它乘以2,否则就原样返回。 注意,这个处理函数是递归处理所有的键。1234567891011var o = {a: {b: 1}};function f(key, value) { console.log("["+ key +"]:" + value); return value;}JSON.stringify(o, f)// []:[object Object]// [a]:[object Object]// [b]:1// '{"a":{"b":1}}' 上面代码中,对象o一共会被f函数处理三次。第一次键名为空,键值是整个对象o;第二次键名为a,键值是{b: 1};第三次键名为b,键值为1。递归处理中,每一次处理的对象,都是前一次返回的值。 123456789var o = {a: 1};function f(key, value) { if (typeof value === 'object') { return {b: 2}; } return value * 2;}JSON.stringify(o,f)// "{"b": 4}" 上面代码中,f函数修改了对象o,接着JSON.stringify方法就递归处理修改后的对象o。 如果处理函数返回undefined或没有返回值,则该属性会被忽略。123456789function f(key, value) { if (typeof(value) === "string") { return undefined; } return value;}JSON.stringify({ a: "abc", b: 123 }, f)// '{"b": 123}' 上面代码中,a属性经过处理后,返回undefined,于是该属性被忽略了。 第三个参数JSON.stringify还可以接受第三个参数,用于增加返回的JSON字符串的可读性。如果是数字,表示每个属性前面添加的空格(最多不超过10个);如果是字符串(不超过10个字符),则该字符串会添加在每行前面。123456789101112131415JSON.stringify({ p1: 1, p2: 2 }, null, 2);/*"{ "p1": 1, "p2": 2}"*/JSON.stringify({ p1:1, p2:2 }, null, '|-');/*"{|-"p1": 1,|-"p2": 2}"*/ toJSON 方法如果JSON.stringify方法处理的对象,包含一个toJSON方法,则它会使用这个方法得到一个值,然后再将这个值转成字符串,而忽略其他成员。toJSON()可以作为函数过滤器的补充,因此 理解序列化的内部顺序十分重要。假设把一个对象传入JSON.stringify(),序列化该对象的顺序如下。 (1) 如果存在toJSON()方法而且能通过它取得有效的值,则调用该方法。否则,返回对象本身。(2) 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值。(3) 对第(2)步返回的每个值进行相应的序列化。(4) 如果提供了第三个参数,执行相应的格式化。无论是考虑定义toJSON()方法,还是考虑使用函数过滤器,亦或需要同时使用两者,理解这个顺序都是至关重要的。 123456789101112131415JSON.stringify({ toJSON: function () { return "Cool" }})// ""Cool""var o = { foo: 'foo', toJSON: function() { return 'bar'; }};var json = JSON.stringify({x: o});// '{"x":"bar"}' Date对象就部署了一个自己的toJSON方法。。原生Date 对象有一个toJSON()方法12JSON.stringify(new Date("2011-07-29"))// "2011-07-29T00:00:00.000Z" toJSON方法的一个应用是,可以将正则对象自动转为字符串。123RegExp.prototype.toJSON = RegExp.prototype.toString;JSON.stringify(/foo/)// "/foo/" 理解序列化的执行顺序 就可以解释该结果产生的原因 上面代码,在正则对象的原型上面部署了toJSON方法,将其指向toString方法,因此遇到转换成JSON时,正则对象就先调用toJSON方法转为字符串,然后再被JSON.stingify方法处理。 JSON.parse() JSON.parse方法用于将JSON字符串转化成对象。 1234567JSON.parse('{}') // {}JSON.parse('true') // trueJSON.parse('"foo"') // "foo"JSON.parse('[1, 5, "false"]') // [1, 5, "false"]JSON.parse('null') // nullvar o = JSON.parse('{"name": "张三"}');o.name // 张三 如果传入的字符串不是有效的JSON格式,JSON.parse方法将报错。12JSON.parse("'String'") // illegal single quotes// SyntaxError: Unexpected token ILLEGAL 上面代码中,双引号字符串中是一个单引号字符串,因为单引号字符串不符合JSON格式,所以报错。 为了处理解析错误,可以将JSON.parse方法放在try…catch代码块中。JSON.parse方法可以接受一个处理函数,用法与JSON.stringify方法类似。123456789101112function f(key, value) { if (key === ''){ return value; } if (key === 'a') { return value + 10; }}var o = JSON.parse('{"a":1,"b":2}', f);o.a // 11o.b // undefined 注意 与下面代码比较的区别12345678910111213function f(key, value) { if (key === ''){ return value; } if (key === 'a') { return value + 10; }else{ return value}var o = JSON.parse('{"a":1,"b":2}', f);o.a // 11o.b // 2 兼容性问题 1 2 3 4 5 6 Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari Basic support (Yes) 3.5 (1.9.1) 8.0 10.5 4.0 常见问题 ie6 7下不支持JSON解决方法一:1234567var jsons = req.responseText; var s; if (typeof(JSON) == 'undefined'){ s = eval("("+jsons+")"); }else{ s = JSON.parse(jsons); } 解决方法二:调用的页面里引用json2.js即可解决问题(由于安全性问题 推荐方法二)。1<script type="text/javascript" src="js/json2.js"></script> json2.js地址 http://j2.58cdn.com.cn/js/v8/modules/common/json2.js或者到官网下载http://www.json.org/js.htmlgithub:https://github.com/douglascrockford/JSON-js]]></content>
</entry>
<entry>
<title><![CDATA[js小记]]></title>
<url>http://yoursite.com/2016/10/27/jsSummary/</url>
<content type="text"><![CDATA[平时遇到的js一些方法,或者是面试题,又或者总结之类的。。 javascript有哪些方法定义对象123对象字面量: var obj = {};构造函数: var obj = new Object();Object.create(): var obj = Object.create(Object.prototype); 判断对象是否含有某个属性(in 和 hasOwnProperty区别)12345678function car(){this.name='sbx';this.age="1234"} var car1=new car() car.prototype.sex="nv" car1.constructor//car(){this.name='sbx';this.age="1234"} car1.hasOwnProperty("name")//true car1.hasOwnProperty("sex")//false "name" in car1//true "sex" in car1//true 判断某个属性是否存在与某个对象中,可以通过in运算符,hasOwnProperty()和propertyIsEnumerable()方法来完成.in运算符,如果对象的自有属性或继承属性中包含这个属性,则返回true.对象的hasOwnProperty()方法用来检测给定的名字是否是对象的自有属性.propertyIsEnumerable()是hasOwnProperty()的增强版,只有检测到时自有属性且这个属性的可枚举性为true时才能返回true. indexOf()1stringObject.indexOf(searchvalue,fromindex) 该方法将从头到尾地检索字符串 stringObject,看它是否含有子串 searchvalue。开始检索的位置在字符串的 fromindex 处或字符串的开头(没有指定 fromindex 时)。如果找到一个 searchvalue,则返回 searchvalue 的第一次出现的位置。stringObject 中的字符位置是从 0 开始的。 Math Math.random() 0.0-1.0 随机数 Math.ceil() 向上取整 Math.floor() 一律舍去 仅保留整数 Math.round() 进行四舍五入 数组转字符串需要将数组元素用某个字符连接成字符串,示例代码如下:123var a, b; a = new Array(0,1,2,3,4); b = a.join("-"); 字符串转数组实现方法为将字符串按某个字符切割成若干个字符串,并以数组形式返回,示例代码如下:12var s = "abc,abcd,aaa";ss = s.split(",");// 在每个逗号(,)处进行分解。 判断一个元素是否是数组// 这里提供两种js方法。返回true则是数组。123456789var array = new Array("1", "2", "3", "4", "5");$.isArray(array)alert(array instanceof Array);alert(array.constructor == Array);// 较为严谨并且通用的方法:function isArray(object){ return object && typeof object==='object' && Array == object.constructor;} toArray原生写法1234toArray:function(){ Array.prototype.slice.call(this)}//$("div")返回的是jQuery对象 jQuery.toArray(); Array.prototype.slice.call(arguments)看一下call的使用123456var a = function(){ console.log(this); // 'littledu' console.log(typeof this); // Object console.log(this instanceof String); // true } a.call('littledu'); 可以看到函数a中的this指向call传入的参数到这里,基本就差不多了,我们可以大胆猜一下slice的内部实现,如下:123456789Array.prototype.slice = function(start,end){ var result = new Array(); start = start || 0; end = end || this.length; //this指向调用的对象,当用了call后,能够改变this的指向,也就是指向传进来的对象,这是关键 for(var i = start; i < end; i++){ result.push(this[i]); } return result; } 用闭包随机生成id click和onclickclick()方法的主要作用是触发调用click方法元素onclick事件。123456789101112<script type="text/javascript">$(function(){$("#btn3").click(function(){alert("aa");});});function change(){alert("bb");}</script><button id="btn3" onclick="change()">dd</button>//弹出bb 然后是aa getAttribute()和setAttribute()兼容性问题getAttribute()和setAttribute()在设置或者获取某些属性的时候,会存在一些兼容性问题,那么哪些属性会出现问题呢? -1.class -2.for -3.cellspacing -4.cellpadding -5.tabindex -6.readonly -7.maxlength -8.rowspan -9.colspan -10.usemap -11.frameborder -12.contenteditable -13.style 12345678910111213141516<div id="idHeader" class="class-header" title="kingwell" status="1"></div><label id="forUserName" for="userName" title="kingwell" status="1"></label>$(function(){ var el = document.getElementById("idHeader"); //alert(el.getAttribute("id"));//ie6,7正常 //alert(el.id);//ie6,7正常 alert(el.getAttribute("class"));//其他正常,ie6.7不正常 alert(el.getAttribute("className"));//其他不正常,ie6,7正常 //alert(jQuery.valHooks.button.get(el,"class"))//用于解决ie6,7下情况 //alert(el.getAttribute("status"))//ie6,7正常 var elfor = document.getElementById("forUserName"); alert(elfor.getAttribute("for"))//其他正常,ie6.7不正常 alert(elfor.getAttribute("htmlFor"))//ie6,7正常 其他不正常 //alert(jQuery.valHooks.button.get(el,"for"))//ie6,7均不正常 //alert(jQuery.attrHooks.contenteditable.get(el,"for"))})]]></content>
</entry>
<entry>
<title><![CDATA[深入理解javascript的闭包特性]]></title>
<url>http://yoursite.com/2016/10/26/closure/</url>
<content type="text"><![CDATA[理解JavaScript的闭包是迈向高级JS程序员的必经之路,理解了其解释和运行机制才能写出更为安全和优雅的代码 变量的作用域要理解闭包,首先必须理解Javascript特殊的变量作用域。变量的作用域无非就是两种:全局变量和局部变量。1.Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。12345var n=999; function f1(){ alert(n); } f1(); // 999 2.另一方面,在函数外部自然无法读取函数内的局部变量。1234 function f1(){ var n=999; } alert(n); // error 这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!12345 function f1(){ n=999; } f1(); alert(n); // 999 如何从外部读取函数内部变量的?正常情况下f1内局部变量访问不到,只能内部定义一个函数123456 function f1(){ var n=999; function f2(){ alert(n); // 999 } } f1内部变量对f2可见,而f2内部变量对f1不可见 这就是Javascript语言特有的“链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。 既然这样,将f2作为返回值,就可以访问到f1内部的变量,达到了外部访问f1内部变量的目的 123456789 function f1(){ var n=999; function f2(){ alert(n); } return f2; } var f=f1();f();//999 闭包的概念我们将像f2函数这样,能够读取其他函数内部变量的函数,称之为闭包由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”外部通过f2函数访问到f1内部的变量,可见闭包是沟通外部和内部之间的桥梁 闭包的用途、闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。怎么理解始终存在内存?1234567function f1(){ var n=999; alert(n++); }f1()//999f1()//999f1()//999 f1每次调用结束后 变量n会被清除,不会保存在内存中 1234567891011function f1(){ var n=999; function f2(){ alert(n++); } return f2; } var result=f1(); result()//999 result()//1000 result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。 为什么会这样呢? 原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。 垃圾回收机制在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数f1被f2引用,f2又被f1外的result引用,这就是为什么函数f1执行后不会被回收的原因。那么我们来想象另一种情况,如果f1返回的不是函数f2,情况就完全不同了。因为f1执行完后,f2没有被返回给f1的外界,只是被f1所引用,而此时f1也只会被f2引 用,因此函数f1和f2互相引用但又不被外界打扰(被外界引用),函数f1和f2就会被GC回收123456789function f1(){ var n=999; function f2(){ alert(n++); } f2(); } f1()//999 f1()//999 使用闭包的注意点1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。 2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便]]></content>
</entry>
<entry>
<title><![CDATA[jQuery.event兼容各浏览器的event详细解析]]></title>
<url>http://yoursite.com/2016/10/25/event/</url>
<content type="text"><![CDATA[jQuery在遵循W3C规范的情况下,对事件的常用属性进行了封装,使得事件处理在各大浏览器下都可以正常的运行而不需要进行浏览器类型判断,如果想了解如何封装,可以看jquery源码 event对象的各个属性介绍jQuery的一个方法 jQuery.event.fix(event || window.event);此方法个浏览器的event对象转换为 jQuery.event; 如果您的事件是通过jQuery方法绑定的,就不需要进行转换了! 1.event.type属性该方法作用是可以获取到时间的类型代码如下:1234$("a").click(function(event){ alert(event.type); //获取时间类型 return false; //阻止链接跳转}) 以上代码运行后会返回:“click”。 2.event.preventDefault()方法该方法的作用是阻止默认的事件行为。JavaScript中符合W3C规范的preventDefault()方法在IE浏览器中无效。jQuery对其进行了封装,使之能兼容各种浏览器。 3.event.stopPropagation()方法该方法是阻止事件的冒泡。JavaScript中符合W3C规范的stopPropagation()方法在IE浏览器中无效。jQuery对其进行封装,使之能兼容各种浏览器。 4.event.target属性event.target属性的作用是获取到出发事件的元素。jQuery对其封装后,避免了W3C、IE和safari浏览器不同标准的差异。代码如下:1234$("a[href=http://www.jb51.net]").click(function(event){ alert(event.target.href); //获取触发事件的<a>元素的href属性值 alert(event.target.tagName); //获取触发事件的元素的标签名称 return false; //阻止链接跳转}) 5.event.relatedTarget属性在标准DOM中,mouseover和mouseout所发生的元素可以通过event.target()方法来访问,相关元素是通过event.relatedTarget属性来访问的。event.relatedTarget属性在mouseover中相当于的event.fromElement属性,在mouseout中相当于event.toElement,jQuery对其进行了封装,使之能兼容各种浏览器。 6.event.pageX/event.pageY属性该方法的作用是获取到光标相对页面的x坐标和y坐标。如果没有使用jQuery时,那么IE浏览器中是用event/event.y方法,而在Firefox浏览器中用event.pageX/event.pageY方法。如果页上有滚动条,则还要加上滚动条的宽度和高度。在IE浏览器中还应该减去默认的2px的边框。代码如下:1234567$(function() { $("a").click(function(event) { alert("Current mouse position:" + event.pageX + "," + event.pageY); //获取鼠标当前相对于页面的坐标 return false; //阻止链接跳转 });}) 7.event.which属性该方法的作用是在鼠标单击事件中获取到鼠标的左、中、右键;在键盘事件中获取键盘的按钮。 代码如下:12345$(function() { $("body").mousedown(function(e) { alert(e.which); //1 = 鼠标左键;2 = 鼠标中键;3 = 鼠标右键。 })}) 以上代码加载到页面中,用鼠标单击页面时,单击左、中、右键分别返回1、2、3. 8.event.metaKey属性针对不同浏览器对键盘中的按键解释不同,jQuery也进行了封装,并规定event.metaKey()方法为键盘事件中获取按键。 9.event.originalEvent属性。该方法的作用是指向原始的事件对象。 事件的传播传播的三个阶段当一个事件发生以后,它会在不同的DOM节点之间传播(propagation)。这种传播分成三个阶段: 1.第一阶段:从window对象传导到目标节点,称为“捕获阶段”(capture phase)。2.第二阶段:在目标节点上触发,称为“目标阶段”(target phase)。3.第三阶段:从目标节点传导回window对象,称为“冒泡阶段”(bubbling phase)。这种三阶段的传播模型,会使得一个事件在多个节点上触发。比如,假设div节点之中嵌套一个p节点。123<div> <p>Click Me</p></div> 如果对这两个节点的click事件都设定监听函数,则click事件会被触发四次。12345678910111213141516var phases = { 1: 'capture', 2: 'target', 3: 'bubble'};var div = document.querySelector('div');var p = document.querySelector('p');div.addEventListener('click', callback, true);//true 代表在事件捕获阶段触发 false 代表事件在冒泡阶段触发 默认为falsep.addEventListener('click', callback, true);//jquery封装的事件默认冒泡阶段捕获div.addEventListener('click', callback, false);p.addEventListener('click', callback, false);function callback(event) { var tag = event.currentTarget.tagName; var phase = phases[event.eventPhase]; console.log("Tag: '" + tag + "'. EventPhase: '" + phase + "'");} 事件代理常用于为后追加的元素绑定事件由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)。123456var ul = document.querySelector('ul');ul.addEventListener('click', function(event) {if (event.target.tagName.toLowerCase() === 'li') { // some code}}); 上面代码的click事件的监听函数定义在ul节点,但是实际上,它处理的是子节点li的click事件。这样做的好处是,只要定义一个监听函数,就能处理多个子节点的事件,而且以后再添加子节点,监听函数依然有效。如果希望事件到某个节点为止,不再传播,可以使用事件对象的stopPropagation方法。 123p.addEventListener('click', function(event) { event.stopPropagation();}); 使用上面的代码以后,click事件在冒泡阶段到达p节点以后,就不再向上(父节点的方向)传播了。 但是,stopPropagation方法不会阻止p节点上的其他click事件的监听函数。如果想要不再触发那些监听函数,可以使用stopImmediatePropagation方法。1234567p.addEventListener('click', function(event) { event.stopImmediatePropagation();});p.addEventListener('click', function(event) { // 不会被触发});]]></content>
</entry>
<entry>
<title><![CDATA[$.extend详解]]></title>
<url>http://yoursite.com/2016/10/24/$.extend/</url>
<content type="text"><![CDATA[jQuery.extend()函数用于将一个或多个对象的内容合并到目标对象。该函数可以将一个或多个对象的成员属性和方法复制到指定的对象上。该函数属于全局jQuery对象。 静态函数jQuery.extend()有以下两种用法:用法一:jQuery 1.0 新增该用法。 1jQuery.extend( target [, object1 ] [, objectN... ] ) 用法二:jQuery 1.1.4 新增该用法。 1jQuery.extend( [ deep ], target , object1 [, objectN... ] ) 用法二是用法一的变体,参数deep用于指示是否深度递归合并。$.extend() 打印出的值也是target的值 参数请根据前面语法部分所定义的参数名称查找对应的参数。 参数 描述 deep deep可选/Boolean类型指示是否深度合并对象,默认为false。如果该值为true,且多个对象的某个同名属性也都是对象,则该”属性对象”的属性也将进行合并。 targetObject targetObject类型目标对象,其他对象的成员属性将被复制到该对象上。 object1 object1可选/Object类型第一个被合并的对象。 objectN objectN可选/Object类型第N个被合并的对象。 注意事项 ● 该函数复制的对象属性包括方法在内。此外,还会复制对象继承自原型中的属性(JS内置的对象除外) 。 ● 参数deep的默认值为false,你可以为该参数明确指定true值,但不能明确指定false值。简而言之,第一个参数不能为false值。 ● 如果参数为null或undefined,则该参数将被忽略。 ● 如果只为$.extend()指定了一个参数,则意味着参数target被省略。此时,target就是jQuery对象本身。通过这种方式,我们可以为全局对象jQuery添加新的函数。 ● 如果多个对象具有相同的属性,则后者会覆盖前者的属性值。 实例用法一 实例 常见用法 如果多个被合并对象有相同的属性,则后者会覆盖之前的属性。 用法 二 此外,如果多个对象的同名属性都是对象,则合并这些”属性对象”的属性]]></content>
</entry>
<entry>
<title><![CDATA[cookie使用总结]]></title>
<url>http://yoursite.com/2016/10/21/cookie/</url>
<content type="text"><![CDATA[cookie 一个轻量级的cookie 插件,可以读取、写入、删除 cookie。 jquery.cookie.js 的配置首先包含jQuery的库文件,在后面包含 jquery.cookie.js 的库文件。 使用方法1.新添加一个会话 cookie:$.cookie(‘the_cookie’, ‘the_value’);注:当没有指明 cookie有效时间时,所创建的cookie有效期默认到用户关闭浏览器为止,所以被称为“会话cookie(session cookie)”。2.创建一个cookie并设置有效时间为 7天:$.cookie(‘the_cookie’, ‘the_value’, { expires: 7 });注:当指明了cookie有效时间时,所创建的cookie被称为“持久 cookie (persistent cookie)”。3.创建一个cookie并设置 cookie的有效路径:$.cookie(‘the_cookie’, ‘the_value’, { expires: 7, path: ‘/‘ });注:在默认情况下,只有设置 cookie的网页才能读取该 cookie。如果想让一个页面读取另一个页面设置的cookie,必须设置cookie的路径。cookie的路径用于设置能够读取 cookie的顶级目录。将这个路径设置为网站的根目录,可以让所有网页都能互相读取 cookie (一般不要这样设置,防止出现冲突) 。4.读取cookie:$.cookie(‘the_cookie’); // cookie存在 => ‘the_value’$.cookie(‘not_existing’); // cookie不存在 => null5.删除cookie,通过传递null作为cookie的值即可 :$.cookie(‘the_cookie’, null); ———-相关参数的解释————— 1).expires: 365定义cookie的有效时间,值可以是一个数字(从创建cookie时算起,以天为单位)或一个Date 对象。如果省略,那么创建的cookie是会话cookie,将在用户退出浏览器时被删除。2).path: ‘/‘默认情况:只有设置cookie的网页才能读取该cookie。定义cookie的有效路径。默认情况下, 该参数的值为创建 cookie 的网页所在路径(标准浏览器的行为) 。如果你想在整个网站中访问这个cookie需要这样设置有效路径:path: ‘/‘。如果你想删除一个定义 了有效路径的 cookie,你需要在调用函数时包含这个路径: $.cookie(‘the_cookie’, null,{ path: ‘/‘ });。domain: ‘example.com’默认值:创建 cookie的网页所拥有的域名。3).secure: true默认值:false。如果为true,cookie的传输需要使用安全协议(HTTPS)。4).raw: true默认值:false。默认情况下,读取和写入 cookie 的时候自动进行编码和解码(使用encodeURIComponent 编码,decodeURIComponent 解码)。要关闭这个功能设置 raw: true 即可。 引自:http://wenku.baidu.com/view/0147277e27284b73f2425074.html 代码:http://files.cnblogs.com/Denny_Yang/jquery.cookie.js 当cookie设置了除了0以外的具体时间的时候,小于0,这个cookie直接就过期,大于0,那就等到这个时间之后,cookie过期,不论其是否关闭浏览器cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案 cookie 和session 的区别:1、cookie数据存放在客户的浏览器上,session数据放在服务器上。2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用session。3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能 考虑到减轻服务器性能方面,应当使用COOKIE。4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。5、所以个人建议: 将登陆信息等重要信息存放为SESSION 其他信息如果需要保留,可以放在COOKIE中知乎:1.因为http是无状态的,每次请求都是 一个独立过程,所以下一次请求无法得知上一次请求产生的一些数据因此产生了cookie,作用是在一次请求介绍后保存一些数据到客户端,客户端在下次请求时携带上这些数据来确定状态;2.session是一般基于cookie的(session id也可以通过url参数进行传递),原理是通过cookie在客户端保存一个唯一身份识别id然后再服务器内存或者数据库中对这个唯一身份进行关联,每次请求过来的时候通过这个id从内存或者数据库中取出相应数据;3,session id在客户端可以通过cookie或者get post 参数,或者url地址的形式进行传递(只要与服务器进行约定方法非常多)默认是通过cookie实现的;在服务器上session可以通过内存,文件,数据库等形式进行保存(java web中默认是存在内存中,django默认是存在数据库中,尚未发现存在文件中的) 1234567891011session<?phpsession_start();if(isset($_SESSION['views'])) $_SESSION['views']=$_SESSION['views']+1;else $_SESSION['views']=1;echo "Views=". $_SESSION['views'];?> localstorageHTML5中提供了localStorage对象可以将数据长期保存在客户端,直到人为清除。localStorage提供了几个方法:1、存储:localStorage.setItem(key,value)如果key存在时,更新value2、获取:localStorage.getItem(key)如果key不存在返回null3、删除:localStorage.removeItem(key)一旦删除,key对应的数据将会全部删除4、全部清除:localStorage.clear()某些时候使用removeItem逐个删除太麻烦,可以使用clear,执行的后果是会清除所有localStorage对象保存的数据5、遍历localStorage存储的key.length 数据总量,例:localStorage.length.key(index) 获取key,例:var key=localStorage.key(index);6、存储JSON格式数据JSON.stringify(data) 将一个对象转换成JSON格式的数据串,返回转换后的串JSON.parse(data) 将数据解析成对象,返回解析后的对象备注:localStorage存数的数据是不能跨浏览器共用的,一个浏览器只能读取各自浏览器的数据,储存空间5M 。 附cookie源码123456789101112131415161718192021222324252627282930313233343536373839404142434445define(function() { return { get: function (name, encode) { var arg = name + "="; var alen = arg.length; var clen = document.cookie.length; var i = 0; var j = 0; while (i < clen) { j = i + alen; if (document.cookie.substring(i, j) == arg) return this.getCookieVal(j, encode); i = document.cookie.indexOf(" ", i) + 1; if (i == 0) break; } return null; }, set: function (name, value, expires, path, domain, secure) { var argv = arguments; var argc = arguments.length; // var expires = (argc > 2) ? argv[2] : null; var now = new Date(); var expires = (argc > 2) ? argv[2] : new Date(now.getFullYear(), now.getMonth() + 1, now.getUTCDate()); var path = (argc > 3) ? argv[3] : '/'; var domain = (argc > 4) ? argv[4] : '.58.com'; var secure = (argc > 5) ? argv[5] : false; document.cookie = name + "=" + escape(value) + ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + ((path == null) ? "" : ("; path=" + path)) + ((domain == null) ? "" : ("; domain=" + domain)) + ((secure == true) ? "; secure" : ""); }, remove: function (name) { //if (this.get(name)) // document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT"; if (this.get(name)) this.set(name, "", new Date(1970, 1, 1)); }, getCookieVal: function(offset, encode){ var endstr = document.cookie.indexOf(";", offset); if (endstr == -1) { endstr = document.cookie.length; } if (encode == false) return document.cookie.substring(offset, endstr); else return unescape(document.cookie.substring(offset, endstr)); } };});]]></content>
</entry>
<entry>
<title><![CDATA[Javascript 高级程序设计]]></title>
<url>http://yoursite.com/2016/10/21/note/</url>
<content type="text"><![CDATA[Javascript 高级程序设计 记录下读书心得 javascript简介 javascript 由三部分组成ECMAscript Dom(文档对象模型) Bom(浏览器对象模型) 在HTML中使用javascriptscriptscript标签 6个属性 async 表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本。只对外部脚本文件有效。 charset defer 表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效 language 已弃用 src 包含要执行的外部文件 type ,目前type 属性的值依旧还是text/javascript。不过,这个属性并不是必需的,如果没有指定这个属性,则其默认值仍为text/javascript。 使用script元素的方式有两种:直接在页面中嵌入JavaScript 代码和包含外部JavaScript文件 在使用script嵌入JavaScript 代码时,记住不要在代码中的任何地方出现”/script”字符串,通过转义字符“/”可以解决这个问题 12345678910xhtml可以省略</script><script type="text/javascript" src="example.js" />html不可以省略<script type="text/javascript" src="example.js"></script><script type="text/javascript" src="example.js">console.log("1");</script>带有src 属性的<script>元素不应该在其<script>和</script>标签之间再包含额外的JavaScript 代码。如果包含了嵌入的代码,则只会下载并执行外部脚本文件,嵌入的代码会被忽略。 通过script便签元素的src 属性还可以包含来自外部域的JavaScript 文件。这一点既让script元素倍显强大,又让它备受争议。在这一点上,script与img元素非常相似,即它的src属性可以是指向当前HTML 页面所在域之外的某个域中的完整URL 在script元素中设置defer 属性,相当于告诉浏览器立即下载,但延迟执行。 同样与defer 类似,async 只适用于外部脚本文件,都是用来改变脚本,并告诉浏览器立即下载文件。但与defer不同的是,标记为async 的脚本并不保证按照指定它们的先后顺序执行 文档类型HTML 也有多个不同的版本,只有完全明白页面中使用的确切 HTML 版本,浏览器才能完全正确地显示出 HTML 页面。这就是 <!DOCTYPE> 的用处。 <!DOCTYPE> 不是 HTML 标签。它为浏览器提供一项信息(声明),即 HTML 是用什么版本编写的。 文档模式http://www.cnblogs.com/venoral/p/5317824.html最初是 混杂模式和标准模式 IE 又提出一种所谓的准标准模式准标准模式与标准模式非常接近,它们的差异几乎可以忽略不计虽然这两种模式主要影响CSS内容的呈现,但在某些情况下也会影响到JavaScript 的解释执行 如果在文档开始处没有发现文档类型声明,则所有浏览器都会默认开启混杂模式。但采用混杂模式不是什么值得推荐的做法,因为不同浏览器在这种模式下的行为差异非常大 对于准标准模式,则可以通过使用过渡型(transitional)或框架集型(frameset)文档类型来触发 基本概念数据类型typeofNumber String Boolean Null undefined Null空对象指针 typeof(null) //object如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null 而不是其他值var c=null;这样做不仅可以体现null 作为空对象指针的惯例,而且也有助于进一步区分null 和undefined。null==undefined //true undefined声明但未初始化的变量 Boolean各种值转换为boolean值的情况,解释了if() 转换过程 输入值 示例 返回值 0 Boolean(0) false NaN Boolean(NaN) false 数字(非 0 或 NaN) Boolean(4) true 空字符串 Boolean(“”) false 非空字符串 Boolean(“6”) true null Boolean(null) false undefined Boolean(undefined) false Object 类的实例 Boolean(new Object()) true 无参数 Boolean() false NumberNaN 非数字,NaN 本身有两个非同寻常的特点。首先,任何涉及NaN 的操作(例如NaN/10)都会返回NaN,这个特点在多步计算中有可能导致问题。其次NaN 与任何值都不相等,包括NaN 本身 isNaN() 是非数字isNaN()在接收到一个值之后,会尝试将这个值转换为数值。某些不是数值的值会直接转换为数值,例如字符串”10”或Boolean 值。而任何不能被转换为数值的值都会导致这个函数返回true 12345alert(isNaN(NaN)); //truealert(isNaN(10)); //false(10 是一个数值)alert(isNaN("10")); //false(可以被转换成数值10)alert(isNaN("blue")); //true(不能转换成数值)alert(isNaN(true)); //false(可以被转换成数值1) 数值转换有3 个函数可以把非数值转换为数值:Number()、parseInt()和parseFloat()。第一个函数,即转型函数Number()可以用于任何数据类型,而另两个函数则专门用于把字符串转换成数值 Number()函数的转换规则如下。 如果是Boolean 值,true 和false 将分别被转换为1 和0。 如果是数字值,只是简单的传入和返回。 如果是null 值,返回0 。 如果是undefined,返回NaN。 如果是字符串,遵循下列规则: 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即”1” 会变成1,”123”会变成123,而”011”会变成11(注意:前导的零被忽略了); 如果字符串中包含有效的浮点格式,如”1.1”,则将其转换为对应的浮点数值(同样,也会忽略前导零); 如果字符串中包含有效的十六进制格式,例如”0xf”,则将其转换为相同大小的十进制整数值; 如果字符串是空的(不包含任何字符),则将其转换为0; 如果字符串中包含除上述格式之外的字符,则将其转换为NaN。 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。 1234var num1 = Number("Hello world!"); //NaNvar num2 = Number(""); //0var num3 = Number("000011"); //11var num4 = Number(true); //1 一般在处理字符串转换为数字 使用parseInt更合理 1.它会忽略字符串前面的空格,直至找到第一个非空格字符。如果第一个字符不是数字字符或者负号,parseInt()就会返回NaN,也就是说,用parseInt()转换空字符串会返回NaN(Number()对空字符返回0)。 2.如果第一个字符是数字字符,parseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。例如,”1234blue”会被转换为1234,因为”blue”会被完全忽略。类似地,”22.5”会被转换为22,因为小数点并不是有效的数字字符。 3.如果字符串中的第一个字符是数字字符,parseInt()也能够识别出各种整数格式(十进制、八进制和十六进制数)。也就是说,如果字符串以”0x”开头且后跟数字字符,就会将其当作一个十六进制整数;如果字符串以”0”开头且后跟数字字符,则会将其当作一个八进制数来解析。 1234567891011121314var num1 = parseInt("1234blue"); // 1234var num2 = parseInt(""); // NaNvar num3 = parseInt("0xA"); // 10(十六进制数)var num4 = parseInt(22.5); // 22var num5 = parseInt("070"); // 56(八进制数)var num6 = parseInt("70"); // 70(十进制数)var num7 = parseInt("0xf"); // 15(十六进制数)指定基数会影响到转换的输出结果。例如:var num1 = parseInt("10", 2); //2 (按二进制解析)var num2 = parseInt("10", 8); //8 (按八进制解析)var num3 = parseInt("10", 10); //10 (按十进制解析)var num4 = parseInt("10", 16); //16 (按十六进制解析) 与parseInt()函数类似,parseFloat()也是从第一个字符(位置0)开始解析每个字符。而且也是一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。也就是说,字符串中的第一个小数点是有效的,而第二个小数点就是无效的了, 123456var num1 = parseFloat("1234blue"); //1234 (整数)var num2 = parseFloat("0xA"); //0var num3 = parseFloat("22.5"); //22.5var num4 = parseFloat("22.34.5"); //22.34var num5 = parseFloat("0908.5"); //908.5var num6 = parseFloat("3.125e7"); //31250000 String 字符字面量比如/n /t字符字面量可以出现在字符串中的任意位置,而且也将被作为一个字符来解析 12var text = "This is the letter sigma: \u03a3.";alert(text.length); // 输出28 2.,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量 这个过程是在后台发生的,而这也是在某些旧版本浏览器(例如版本低于1.0 的Firefox、IE6 等 间接解释了push效率高于+连接字符串)中拼接字符串时速度很慢的原因所在。但这些浏览器后来的版本已经解决了这个低效率问题。 3.转换字符串数值、布尔值、对象和字符串值(没错,每个字符串也都有一个toString()方法,该方法返回字符串的一个副本)都有toString()方法。但null 和undefined 值没有这个方法。 1234567数值调用toString() 可传递一个基数var num = 10;alert(num.toString()); // "10"alert(num.toString(2)); // "1010"alert(num.toString(8)); // "12"alert(num.toString(10)); // "10"alert(num.toString(16)); // "a" String()函数遵循下列转换规则: 如果值有toString()方法,则调用该方法(没有参数)并返回相应的结果; 如果值是null,则返回”null”; 如果值是undefined,则返回”undefined”。 ObjectObject 的每个实例都具有下列属性和方法。 constructor:保存着用于创建当前对象的函数。对于前面的例子而言,构造函数(constructor)就是Object()。 hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在。其中,作为参数的属性名(propertyName)必须以字符串形式指定(例如:o.hasOwnProperty(“name”))。 isPrototypeOf(object):用于检查传入的对象是否是传入对象的原型(第5 章将讨论原型)。 propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in 语句(本章后面将会讨论)来枚举。与hasOwnProperty()方法一样,作为参数的属性名必须以字符串形式指定。 toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。 toString():返回对象的字符串表示。 valueOf():返回对象的字符串、数值或布尔值表示。通常与toString()方法的返回值相同。 123456789101112function car(){this.name='sbx';this.age="1234"}var car1=new car()car.prototype.sex="nv"car1.constructor//car(){this.name='sbx';this.age="1234"}car1.hasOwnProperty("name")//truecar1.hasOwnProperty("sex")//falsecar.prototype.isPrototypeOf(car1)//truecar1.propertyIsEnumerable("age")//truecar1.propertyIsEnumerable("sex")//falsecar1.toLocaleString()//"[object Object]"car1.toString()//"[object Object]"car1.valueOf()//car {name: "sbx", age: "1234"} 操作符相等操作符相等和不相等——先转换再比较,全等和不全等——仅比较而不转换。 == 和=== 对比 == 相等(转换值比较)=== 全等(值和类型都要比较)=== 类型不同 就不相等 ,有一个值为NaN 也不相等 – – – — — == -0==0 true 1==true true 5==’5’ true null==undefined true === -0===0 true 1===true false 5===’5’ false null===undefined false 语句for-in 枚举对象的属性 break 和continue 语句用于在循环中精确地控制代码的执行。其中,break 语句会立即退出循环,强制继续执行循环后面的语句。而continue 语句虽然也是立即退出循环,但退出循环后会从循环的顶部继续执行 1234567891011121314151617181920212223242526var num = 0;for (var i=1; i < 10; i++) {if (i % 5 == 0) {continue;}num++;console.log(i+" "+num);}2016-10-24 17:25:25.549 VM11823:6 1 12016-10-24 17:25:25.550 VM11823:6 2 22016-10-24 17:25:25.551 VM11823:6 3 32016-10-24 17:25:25.551 VM11823:6 4 42016-10-24 17:25:25.552 VM11823:6 6 52016-10-24 17:25:25.552 VM11823:6 7 62016-10-24 17:25:25.552 VM11823:6 8 72016-10-24 17:25:25.555 VM11823:6 9 8var num = 0;for (var i=1; i < 10; i++) {if (i % 5 == 0) {break;}num++;console.log(i+" "+num);}2016-10-24 17:27:22.372 VM11824:6 1 12016-10-24 17:27:22.372 VM11824:6 2 22016-10-24 17:27:22.372 VM11824:6 3 32016-10-24 17:27:22.373 VM11824:6 4 4 变量作用域和内存问题执行环境和作用域作用域链延长 try-catch语句和catch块 with语句javascript没有块级作用域1234for (var i=0; i < 10; i++){doSomething(i);}alert(i); //10 对于有块级作用域的语言来说,for 语句初始化变量的表达式所定义的变量,只会存在于循环的环境之中。而对于JavaScript 来说,由for 语句创建的变量i 即使在for 循环执行结束后,也依旧会存在于循环外部的执行环境中。 垃圾收集标记清除(常用)垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。引用计数(不太常见)引用计数的含义是跟踪记录每个值被引用的次数 函数表达式面向对象程度设计原型链]]></content>
</entry>
<entry>
<title><![CDATA[Backbone]]></title>
<url>http://yoursite.com/2016/10/20/backbone/</url>
<content type="text"><![CDATA[Backbone 是一个 JavaScript 框架,可用于创建模型-视图-控制器 (model-view-controller, MVC) 类应用程序和单页界面 事件管理Backbone.Events 通过继承Events的方法来实现事件的管理 它是Backbone的核心组成的部分 基本事件方法绑定on方法 使用on方法监听默认事件 使用on方法监听属性事件 使用on方法获取属性修改前的值 使用on方法绑定多个事件 绑定once方法once()执行一次 trigger 触发事件 off()移除事件 新增事件方法监听事件listenTo监听一次listenToOnce()停止监听stopListening 特殊事件的使用特殊事件all的使用事件与View Model和Collection的关系 数据模型Model.extend()可以创建数据模型1.实例化过程中自动执行initializa函数 var Student=Backbone.Model.extend({ initialize:function(){ intnum++; console.log("您已经创建了"+intnum+"个对象"); } }); var intnum=0; var stuA=new Student();//实例化过程中自动执行initialize函数 var stuB=new Student(); //您已经创建了2个对象 2.对象模型赋值方法 通过defaults设置默认值 实例化的对象 可以通过obj.set()设置对象属性值 3.可以通过obj.get() obj.escape()获取属性值4.监听属性值的变化5.自定义模型中的方法 var Student=Backbone.Model.extend({ initialize:function(){ this.on("change:name",function(model,value){ // var oldname=this.previous("name"); var oldname=model.previous("name"); // var newname1=this.get("name"); var newname1=value; console.log("旧值是"+oldname+",新值是"+newname1); }) }, defaults:{ name:"zhangsan", age:"13" }, PrintLog:function(){ console.log(this.get("name")+this.get("age")); } }); var stu=new Student(); stu.set({ name:"lisi", age:"14" }); stu.PrintLog(); 模型对象操作 读取修改数据 验证 关闭验证在使用set()设置或修改属性 必须将validate的属性值设置为true 来通知backbone框架开启验证调用validate()方法 按照里边的规则对相应数据进行验证(有一处数据不符合规则即为验证失败,设置也会失败),验证失败,触发invalid方法,返回失败的原因显示在浏览器。 var Teacher=Backbone.Model.extend({ initialize:function(){ this.on("invalid",function(model,error){ console.log(error); }); }, validate:function(arr){ if(!_.isString(arr.name)){ return '姓名不是字符串'; } }, defaults:{ "name":"sunbaixin", "age":"34", "score":"89" } }); var tea=new Teacher(); tea.set({ name:789, age:90 },{validate:"true"}); console.log(tea.toJSON()); 输出结果: 姓名不是字符串 Object {name: "sunbaixin", age: "34", score: "89"} 3 更新数据回滚 silent:true4 删除数据 obj.unset(属性名) obj.clear()没有参数 全部清除 对象属性操作1 调用attributes对象获取所有的属性值 2 调用previous()和previousAttributes()方法 返回对象修改前上一个状态的属性值 var StudentA=Backbone.Model.extend({ initialize:function(){ }, defaults:{ name:"zhangsan", age:"13" } }); var stuA=new StudentA(); stuA.set({ name:"lisi", age:"14" }); var arr=stuA.attributes; for(var i in arr){ console.log(i+":"+arr[i]); }//name:lisi age:14 console.log(stuA.previous("name"));//zhangsan console.log(stuA.previousAttributes());//Object {name: "zhangsan", age: "13"} 同步数据到服务器在Backbone中 客户端静态页和服务器上的数据可以通过save fetch destroy等方法对服务器上的数据进行保存 获取删除等操作 模型集合自定义模型集合 var Student=Backbone.Model.extend({ defaults:{ name:"sbx", code:"34" } }); var Stus=Backbone.Collection.extend({ model:Student, good:function(){ return this.filter(function(stu){ return stu.get("code")>78}); } }) var stulist=[{ name:"lidong1", code:89 },{ name:"lidong2", code:78 },{ name:"lidong3", code:79 }]; var stu=new Stus(stulist); var stug=stu.good(); for(var i=0;i<stug.length;i++){ console.log(stug[i].toJSON()); } 操作集合中模型对象 添加 add unshift push 删除 pop shift remove 排序 sort 查找 get(id) 通过指定id获取集合中某一个集合对象 at(index) 通过指定索引号 获取集合中某一个集合对象 findWhere(attr)查找匹配的属性名称和属性值的第一个集合对象 where(attr,first) first为true 查找匹配的属性名称和属性值的第一个集合对象 first为false 查找匹配的属性名称和属性值的所有集合对象 var Student=Backbone.Model.extend({ defaults:{ name:"sbx", code:"34" }, idAttribute:"code" }; var Stus=Backbone.Collection.extend({ model:Student }) var stulist=[{ name:"lidong1", code:89 },{ name:"lidong3", code:78 },{ name:"lidong3", code:79 },{ name:"lidong4", code:79 }]; var newdata=[{ name:"lidong5", code:89 },{ name:"lidong6", code:78 },{ name:"lidong7", code:77 }]; var stu=new Stus(stulist); console.log(stu.get(79).toJSON()); console.log(stu.at(0).toJSON()); var find_model1=stu.findWhere({ code:79 }); console.log(find_model1.toJSON()); var find_model2=stu.where({ name:"lidong3" },false); for(var i=0;i<find_model2.length;i++){ console.log(find_model2[i].toJSON()); } // console.log(stu.shift()); // console.log(stu.remove(stu.models[0])) // console.log(stu.pop()); // stu.push(newdata[0]) for(var i=0;i<stu.models.length;i++){ console.log(stu.models[i].toJSON()); }]]></content>
</entry>
<entry>
<title><![CDATA[sass]]></title>
<url>http://yoursite.com/2016/10/20/sass/</url>
<content type="text"><![CDATA[sass入门]]></content>
</entry>
<entry>
<title><![CDATA[php]]></title>
<url>http://yoursite.com/2016/10/20/php/</url>
<content type="text"><![CDATA[PHP PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。PHP 能够做什么? PHP 能够生成动态页面内容 PHP 能够创建、打开、读取、写入、删除以及关闭服务器上的文件 PHP 能够接收表单数据 PHP 能够发送并取回 cookies PHP 能够添加、删除、修改数据库中的数据 PHP 能够限制用户访问网站中的某些页面 PHP 能够对数据进行加密 通过 PHP,您可以不受限于只输出 HTML。您还能够输出图像、PDF 文件、甚至 Flash 影片。您也可以输出任何文本,比如 XHTML 和 XML。 PHP基础语法PHP 脚本在服务器上执行,然后向浏览器发送回纯 HTML 结果。 1. PHP 脚本可放置于文档中的任何位置。PHP 脚本以 <?php 开头,以 ?> 结尾: 注释:PHP 语句以分号结尾(;)。PHP 代码块的关闭标签也会自动表明分号(因此在 PHP 代码块的最后一行不必使用分号)。 <!DOCTYPE html> <html> <body> <h1>我的第一张 PHP 页面</h1> <?php echo "Hello World!"; ?> </body> </html> 2 支持三种注释方式 3 变量对大小写敏感 PHP 变量规则: 变量以 $ 符号开头,其后是变量的名称 变量名称必须以字母或下划线开头 变量名称不能以数字开头 变量名称只能包含字母数字字符和下划线(A-z、0-9 以及 _) 变量名称对大小写敏感($y 与 $Y 是两个不同的变量) 4 向浏览器输出 echo() printf() 5 PHP数据类型 标量数据类型 布尔型 整型 浮点型 字符型 符合数据类型:数组 对象 6 强制类型转换 (array)(bool)或(boolean)(int)或(integer)(object)(real)或(double)或(float)(string) 7 类型自动转换 8 与类型有关的函数 gettypesettype 9 类型标识符函数 标识符 10 变量作用域 局部变量 函数参数 全局变量 静态变量(函数退出时不会丢失值) $_SERVER 11 表达式 逻辑 比较 位操作都与js类似 拼接符不同 字符串拼接符(.) 拼接赋值操作符(.=) $a='abc'.'def';//abcdef $a='abc'+'def'//0 +是赋值操作符 12 字符串插入 双引号扩起的字符串 变量和转义序列都会得到相应的解析 单引号 变量和转义序列都不会得到解析 $a=”abc”.”def”; echo “this is $a”;//this is abcdef echo ‘this is $a’;//this is $a 函数1 <?php $total=22; $cost=4; function calcute(&$total,$cost){ $total=$total+$cost; $cost+=4; } calcute($total,$cost); echo($total." ".$cost);//26,4 ?> 按值传递参数(把实参的值 传递给形参 形参是实参的拷贝) 这就意味着,函数范围内对这些值的任意改变在函数外部都会被忽略 按引用传递参数(把实参的地址传递给形参, 形参和实参是同一个对象) 函数内对参数所做的改变都会体现在函数外 2 函数库 数组1 创建数组 array(item1,item2.....); $lang=array("English","Spanish"); 关联数组 $lang=array("Spain"=>"Spanish","United"=>"English"); 2 list()提取数组 range()预定义范围的值填充数组 3 测试数组 is_array() 4 输出数组foreach 5添加删除元素 array_unshift(array,mixed ele,....) array_push() array_shift() array_pop() 6 定位数组元素 搜索数组 in_array() 搜索特定值 array_key_exists() 找到指定的键 返回bool值 array_search() 搜索指定的值 返回相应的键 array_keys() 返回一个数组 包含所有的键 array_values()返回一个数组所有值,并提供索引值 7 遍历数组 key() 获取当前数组键 current()获取当前数组值 each()返回数组的当前键值对 next()向下移动数组指针 prev()向上移动数组指针 reset() end() array_walk(array,callback()) eg:$fruits = array("d"=>"lemon","a"=>"orange","b"=>"banana","c"=>"apple"); function test_print( $value,$key ) { echo "$value<br>\n"; echo "$key<br>\n"; } array_walk( $fruits, 'test_print' ); 8 确定数组大小和唯一性 count()返回数组中值的总数 array_unique() 删除所有重复值 返回由唯一值组成的数组 array_count_values() 统计数组元素出现的频度 9数组排序 array_reverse() 逆置数组元素顺序array_flip()置换数组键和值sort()数组排序 10 合并 拆分 接合和分解数组array_merge() 面向对象的PHP1.oop :封装 继承 多态实例: <?php class Site { /* 成员变量 */ var $url; var $title; function __construct( $par1, $par2 ) { $this->url = $par1; $this->title = $par2; } /* 成员函数 */ function setUrl($par){ $this->url = $par; } function getUrl(){ echo $this->url . PHP_EOL; } function setTitle($par){ $this->title = $par; } function getTitle(){ echo $this->title . PHP_EOL; } } $runoob = new Site('www.runoob.com', '菜鸟教程'); $taobao = new Site('www.taobao.com', '淘宝'); $google = new Site('www.google.com', 'Google 搜索'); // 调用成员函数,获取标题和URL $runoob->getTitle(); $taobao->getTitle(); $google->getTitle(); $runoob->getUrl(); $taobao->getUrl(); $google->getUrl(); ?> //变量 $this 代表自身的对象。 PHP_EOL 为换行符。 2.类 对象 属性 常量 方法 属性: public 任何位置都能访问 private 只能在类内部使用 不能由实例化的对象调用 也不能由类的子类使用 protected 只能在该类及其子类中使用 abstract final 标记为final的方法可以防止被子类覆盖 static 3 构造函数和析构函数 对象实例化的时候 自动执行构造函数 <?php class Emplyee{ private $name; function __construct($Vname){ $this->setName($Vname); $this->getName(); } function setName($name){ $this->name=$name; } function getName(){ echo $this->name; } } $emply=new Emplyee("salary"); ?> 调用父类构造函数 function __construct(){ parent::__construct(); } 调用无关的构造函数 classname::__construct() 析构函数 3 静态类成员 所有类实例共享的属性和方法 静态变量 是只存在于函数作用域的变量, 不过, 在函数执行完成后,这种变量的值不会丢失,也就是说, 在下一次调用这个函数时,变量仍然会记得原来的值. 要将某个变量定义为静态的, 只需要在变量前加上 static 关键字即可. 类中静态元素的使用在类中, static 关键字有两种主要用法, 一是用来定义静态成员,一是用来定义静态方法. 在类的内部, 可以使用作用域限定符 (::) 来访问不同层次作用域的变量. 静态成员 静态成员是一种类变量, 可以把它看成时属于整个类而不是属于类的某个实例. 与一般的实例变量不同的是, 静态成员只保留一个变量值, 而这个变量值对所有的实例都是有效的, 也就是说, 所有的实例共享这个成员. $this 只表示类的当前实例, 而 self:: 表示的是类本身,在类之外的代码中不能使用这个操作符,而且它不能识别自己在继承树层次结构中的位置. 也就是说, 在扩展类中使用self 作用域时, self 可以调用基类中声明的方法, 但它调用的总是已经在扩展类中重写的方法. 与$this 不同的是, 在使用静态变量时,必须在作用域限定符后面加上$符号.在扩展类中, 在基类的方法被重写的情况下,使用 parent 作用域调用定义在基类中的方法.静态成员也可以只属于父类. 如果在子类和父类中同时声明了某个成员,也可以使用parant:: 在子类中访问父类中的变量. 在这种情况下, 父类的静态成员和子类的静态成员保存的是不同的值. 可以在 :: 操作符的左边写上类的名称来静态地访问某个成员, 这样避免创建类的实例. 不仅省略掉实例化类的代码, 而且还会更高效, 因为类的每个实例都会占用一小部分的系统资源.在使用 :: 操作符访问成员变量时, 需要再次注意对$符号的使用. 因为PHP当前不支持动态的静态变量的使用, 也就是说不支持可变的静态变量. 在使用$this->$var时, 被访问的成员是包含在$var中的变量的值. 而不用$符号访问某个变量实际上查找的是类的某个常量, 而常量是不能通过$this来访问的. PHP6 中提出的static:: 作用域使我们不再需要使用self:: 和parent::. 当希望指向最终的实现功能的类时, 就可以使用static::, 这个限定符会在代码执行之前立即计算出继承层次机构上最后那个类的成员. 之一过程被称为延迟绑定, 它使我们可以在子类中重写某个静态变量, 并且也可以从某个在父类中声明的函数中反问这个最终成员. 静态方法 静态方法和非静态方法之间有一个重要的区别: 在调用静态方法时, 不再需要拥有类的实例. 静态方法和非静态方法使用原则:一是如果某个方法中不包含$this 变量, 就应该时静态方法; 如果不需要类的实例, 可能还应该使用静态类, 这样可以免去实例化类的工作. 另, 在静态方法中时不能使用$this 变量的, 因为静态方法不属于某个特定的实例. PHP中使用作用域限定操作符时, 用变量作为类的名称时不允许的.]]></content>
</entry>
<entry>
<title><![CDATA[学习计划]]></title>
<url>http://yoursite.com/2016/10/20/learn/</url>
<content type="text"><![CDATA[学习规划@[源码|框架|工具] 1、js设计模式阅读了两本书 2、vue.js3、学习httphttp权威指南(完成) 4、MVC设计模式spane.js源码已经阅读 underscore.js源码看了90% 下一步研究backbone.js的使用 5、学习git学习更多的命令行(学习了20%) 学习开通github和博客(总结各种资源) doing.... 6、chrome devtools 使用有几个面板还不熟悉 7、学习node8、requirejs源码分析与使用9、jQuery源码分析10、学习React (+react ntive)11、ES612、构建工具* grunt * gulp * fis * webpack * rollup * browserfy 13、模块化@[esl.js|require.js|sea.js] 14、fis3学习使用(源码学习)初级使用已经完成实验]]></content>
</entry>
<entry>
<title><![CDATA[jsonp]]></title>
<url>http://yoursite.com/2016/10/20/jsonp/</url>
<content type="text"><![CDATA[JSONP跨域原理解析 可参考JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档在同一域下的内容。 JavaScript这个安全策略在进行多iframe或多窗口编程、以及Ajax编程时显得尤为重要。根据这个策略,在baidu.com下的页面中包含的JavaScript代码,不能访问在google.com域名下的页面内容;甚至不同的子域名之间的页面也不能通过JavaScript代码互相访问。对于Ajax的影响在于,通过XMLHttpRequest实现的Ajax请求,不能向不同的域提交请求,例如,在abc.example.com下的页面,不能向def.example.com提交Ajax请求,等等 然而,当进行一些比较深入的前端编程的时候,不可避免地需要进行跨域操作,这时候“同源策略”就显得过于苛刻。JSONP跨域GET请求是一个常用的解决方案,下面我们来看一下JSONP跨域是如何实现的,并且探讨下JSONP跨域的原理。 举例说明写法一: 写法二: netwrok上查看接口如下 http://api.fang.58.com/phplocal/getshangquan/?jsoncallback=jQuery1800931218545883894_1463990648558&cityid=1&cateid=70134&localid=1142&_=1463990652773 Jsonp的执行过程如下:一.首先在客户端注册一个callback (默认名字为callback,用户可自定义名字如:’jsoncallback’,但要保证服务器能够查询到这个参数名) 说明:ajax内部的处理总的来分2大块 1.基于XMLHttpRequest的ajax请求 2.基于script的jsonp跨域请求 jquery源码(源码分析参考 )若想基于script的jsonp跨域请求,根据ajax传递的参数决定 首先看url上是否有callback=?(如jsoncallback=?就可以跨域请求,不管dataType参数值是什么)如果没有的话 会查看dataType的类型,如果是jsonp url上会拼接callback=?(默认是callback,当然如果参数上有 jsonp:’jsoncallback’,那么url会拼接jsoncallback=? 总之callback=?是核心 ) 二。然后把callback的值(如:jQuery1236827957501 这个是jquery和随机数拼接在一起的 jquery源码可见)传给服务器。 expando: "jQuery" + (g.fn.jquery + Math.random()).replace(/\D/g, ""), 。。。 var e = qn.apop() || g.expando + "_" + Mn++; 注意:服务端得到callback的数值后,要用jQuery1236827957501(……)把将要输出的json内容包括起来,此时,服务器生成 json 数据才能被客户端正确接收。 三.然后以 javascript 语法的方式,生成一个function, function 名字就是传递上来的参数 ‘jsoncallback’的值 jQuery1236827957501 .最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。 jQuery1800931218545883894_1463990648558({"threelocal":[{"cate":"A","catelist":[{"listname":"anzhenqiao","localname":"安贞","id":1204,"clickcode"。。。 四.客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时javascript文档数据,作为参数, 传入到了客户端预先定义好的 callback 函数(如上例中jquery $.ajax()方法封装的的success: function (json) )里。可以理解成带有参数的函数调用 总结:可以说jsonp的方式原理上和是一致的(qq空间就是大量采用这种方式来实现跨域数据交换的)。JSONP是一种脚本注入(Script Injection)行为,所以有一定的安全隐患。 var eleScript= document.createElement("script"); eleScript.type = "text/javascript"; eleScript.src = "http://example2.com/getinfo.php"; document.getElementsByTagName("HEAD")[0].appendChild(eleScript) 实质的调用形式 其实如下例子 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>Test Jsonp</title> <script type="text/javascript"> function jsonpCallback(result) { alert(result.msg); } </script> <script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback"></script> </head> <body> </body> </html>]]></content>
</entry>
<entry>
<title><![CDATA[background;box-sizing;@2x;]]></title>
<url>http://yoursite.com/2016/10/20/css3/</url>
<content type="text"><![CDATA[介绍各种关于css和css3相关属性的使用background box-sizing backgroundbackground-imagebackground-image 可以放置多张图片 background-size 设置图片的大小100%图片原尺寸 20%图片原尺寸的20% contain 以区域最短的宽(或高)为准,成比例填充 cover 图片覆盖整个背景区域 background-clip 决定显示背景图片的哪部分 padding-box 显示内边距以内的背景 border-box 显示边框以内的背景 content-box 显示内容区域的背景 background-origin: 决定背景图片怎么放置 border-box 边框以内 开始放置 padding-box 内边距以内开始放置 content-box 内容区域开始放置 background-position:同-origin 一个原理 ,只是具体定位背景图片从哪开始放置 background-color:background-color:设置背景的图片 background-repeat:background-repeat:设置背景图片是否重复铺设 background-attchment:background-attachment: scroll|fixed|local|initial|inherit; 设备像素比devicePixelRatio简单介绍定义如下:window.devicePixelRatio是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例。公式表示就是:window.devicePixelRatio = 物理像素 / dips dip或dp,(device independent pixels,设备独立像素)与屏幕密度有关。dip可以用来辅助区分视网膜设备还是非视网膜设备。所有非视网膜屏幕的iphone在垂直的时候,宽度为320物理像素。当你使用的时候,会设置视窗布局宽度(不同于视觉区域宽度,不放大显示情况下,两者大小一致,见下图)为320px, 于是,页面很自然地覆盖在屏幕上。这样,非视网膜屏幕的iphone上,屏幕物理像素320像素,独立像素也是320像素,因此,window.devicePixelRatio等于1.而对于视网膜屏幕的iphone,如iphone4s, 纵向显示的时候,屏幕物理像素640像素。同样,当用户设置的时候,其视区宽度并不是640像素,而是320像素,这是为了有更好的阅读体验 – 更合适的文字大小。这样,在视网膜屏幕的iphone上,屏幕物理像素640像素,独立像素还是320像素,因此,window.devicePixelRatio等于2. 说明case1 :对于苹果电脑是视网膜屏幕,图片常常看起来模糊,需要适配2x,利用css3新样式,可以做到,但低版本的兼容性较差 图片问题note:ie6下png24不透明 gif和png8透明 适配2倍像素 写法为了保证在一倍像素和2倍像素下 使用icon的background-size不变@2x图片是@1x图片的2倍 合成的雪碧图也要是2倍(宽或者高度)这样 @2x下 bacground-size 设置成和@1x一样的高度或者宽度 12345678910111213141516171819202122232425.icon{ display:inline-block; position:absolute; //top:0; width:16px; height:30px; background:url('http://img.58cdn.com.cn/ui8/house/detail/images/[email protected]')no-repeat center; }@media only screen and (-webkit-min-device-pixel-ratio: 2),only screen and (min-device-pixel-ratio:2) { .icon{ background-image:url(http://img.58cdn.com.cn/ui8/house/detail/images/[email protected]); background-size: auto 80px; }}另一种写法.newaplogo { width: 270px; height: 70px; background: url(http://img.58cdn.com.cn/ui8/house/list/img/58logon.png?20160704) no-repeat; background-image: -webkit-image-set(url(http://img.58cdn.com.cn/ui8/house/list/img/58logon.png?20160704) 1x,url(http://img.58cdn.com.cn/ui8/house/list/img/[email protected]?20160704) 2x); float: left; margin-right: 30px} box-sizing兼容到ie81234567width:100px;height:100px;padding:2px;border:2px solid #000;box-sizing:content-box;//宽度和高度分别应用到元素的内容框。 //在宽度和高度之外绘制元素的内边距和边框box-sizing:border-box;//为元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制。]]></content>
</entry>
</search>