-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
140 lines (98 loc) · 97.1 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
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[使用vuejs开发的一个面试页面]]></title>
<url>%2F2017%2F03%2F09%2FinterviewTest%2F</url>
<content type="text"><![CDATA[试题链接 参考答案GitHub地址 演示效果: 第一部分是关于javascript的简答题,考的是js基础知识。涉及的内容包括数组操作,js中改变this指向的方法call()以及js原型法。 第二部分使用SPA框架开发一个滚动加载的页面,我使用的是vue.js,涉及的开发知识比较多。项目核心知识包括Vue.js,webpack,vue-scroller,axios,moment.js,xml2json.js,跨域问题,JavaScript正则匹配。数据源是http://36kr.com/feed,数据格式是xml。 正文如下。大家可以看看试题,再看看我的参考答案,以下是详细介绍,欢迎大家给参考答案点一个star~1.项目结构直接使用vue-scroller的演示demo 传送门 2.配置webpack,设置proxy代理,解决网络请求插件axios获取http://36kr.com/feed存在跨域问题。在webpack.config.js中devServer的设置添加proxy,如下: 1234567891011devServer: { historyApiFallback: true, noInfo: true, proxy: { '/feed': { target: 'http://36kr.com/', changeOrigin: true, secure: false } } } 3.移动端使用相对长度单位rem,需要在index.html中添加一段js代码,根据屏幕尺寸设置根字体大小。 123456789101112<script type="text/javascript"> window.addEventListener('resize', infinite); function infinite() { const html = document.getElementsByTagName('html')[0]; const htmlWidth = document.body.clientWidth if (htmlWidth >= 1080) { html.style.fontSize = "42px"; } else { html.style.fontSize = (42/ 1080 * htmlWidth) + 'px'; } }infinite(); </script> 4.这部分知识主要包括vue指令v-for、v-if、v-text、v-html。以及自定义事件refresh、infinite。css只要使用flex布局,比较简单不贴代码了,组件html结构如下: 123456789101112131415161718192021222324<template> <div id="app"> <scroller :on-refresh="refresh" :on-infinite="infinite" ref="my_scroller"> <div v-for="(item, index) in items" class="row"> <h1 class="itme-title" v-text="item.title.__cdata"></h1> <div class="itembox"> <span class="author" v-text="item.author"></span> <span class="category" v-text="item.category"></span> <span class="timebox" v-text="newmoment(item.pubDate.__cdata)"></span> </div> <a class="item-content" :href="item.link"> <div class="leftbox" v-html="handlerData(item.description.__cdata)"></div> <div class="rightbox"> <div class="imgbox"> <img class="img" :src="skewImg.url?skewImg.url:'/src/assets/404.jpg'"> </div> </div> </a> </div> </scroller> </div></template> 5.在vue生命周期created阶段,通过axios发起网络请求,获取数据之后,将数据经过xml2json插件转换后,保存json数据到本地数组。 12345678910111213141516171819202122232425262728 data() { return { items: [],//当前渲染数据 allData: [],//所有数据 dataLen: 0,//数据总长度 step: 10,//上拉加载时,每次载入数据的数量 times: 0,//上拉加载次数 skewImg: []//缩略图保存地址 } },created() { var dataObj = {}; var self = this; axios.get('/feed') .then(function (response) { var x2js = new X2JS(); var dataObj = response.data; var jsonObj = x2js.xml_str2json( dataObj ); var itemData = jsonObj.rss.channel.item; for (var i = itemData.length; i >= 0; i--) { self.allData.push(itemData[i]) } self.dataLen = self.allData.length; }) .catch(function (error) { console.log(error); }); } 6.渲染到页面前数据处理,若当前item有多张图片,则保存第一张图片的src地址,若没有图片则保存一个空值。然后将数据去除所有html标签,只保留300个字符长度的文本,渲染到页面中: 1234567891011handlerData(str) { var self = this; var dd = ''; var arr = str.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/i, function (match, capture) { dd = capture }); self.skewImg['url'] = dd; var str = str.substring(0,300); return str.replace(/<[^>]+>/g,""); } 7.渲染到页面前,使用moment.js格式化时间。 123newmoment(arg) { return moment(arg).format('MM 月 DD 日 hh:mm') } 8.上拉加载更多调用infinite()方法,每次上拉操作,次数times自加1,并往items数组添加step长度的数据: 12345678910111213141516infinite() { var self = this; setTimeout(() => { self.times +=1; var end = ((self.step)+1)*self.times; var sta = end - self.step; self.items = self.items.concat(self.allData.slice(sta,end)); // console.log(self.items.length) if (self.items.length >= self.allData) { this.$refs.my_scroller.finishInfinite(true) } setTimeout(() => { this.$refs.my_scroller.finishInfinite(true) }) }, 1500) } 9.下拉刷新调用reflesh()方法,重新发起一次网络请求,并且往items中填充step条数据: 12345678910111213141516171819202122232425262728refresh() { setTimeout(() => { var dataObj = {}; var self = this; axios.get('/feed') .then(function (response) { var x2js = new X2JS(); var dataObj = response.data; var jsonObj = x2js.xml_str2json( dataObj ); var itemData = jsonObj.rss.channel.item; self.items = [];//重置数据 self.allData = [];//重置数据 self.times = 1;//重置数据 for (var i = itemData.length; i >= 0; i--) { self.allData.push(itemData[i]) } self.allData.shift();//删除数组第一个数据 var end = ((self.step)+1)*self.times; var sta = end - self.step; self.items = self.allData.slice(sta,end); }) .catch(function (error) { console.log(error); }); if (this.$refs.my_scroller) this.$refs.my_scroller.finishPullToRefresh(); }, 1500) } 最后是遗留问题:应该是webpack配置有点问题,执行build打包之后,设置的proxy代理失效。求大神帮忙看看。]]></content>
</entry>
<entry>
<title><![CDATA[如何优化javascript代码提高性能]]></title>
<url>%2F2017%2F03%2F06%2Fjavascript_optimization%2F</url>
<content type="text"><![CDATA[一.Javascript代码执行效率1. DOM操作1.1 使用 DocumentFragment 优化多次 append说明:添加多个 dom 元素时,先将元素 append 到 DocumentFragment 中,最后统一将 DocumentFragment 添加到页面。 该做法可以减少页面渲染 dom 元素的次数。经 IE 和 Fx 下测试,在 append1000 个元素时,效率能提高 10%-30% , Fx 下提升较为明显。优化前:12345for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; document.body.appendChild(el);} 优化后:1234567var frag = document.createDocumentFragment();for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el);}document.body.appendChild(frag); 1.2 通过模板元素 clone ,替代 createElement 说明:通过一个模板 dom 对象 cloneNode ,效率比直接创建 element 高。性能提高不明显,约为 10% 左右。在低于 100 个元素 create 和 append 操作时,没有优势。优化前:1234567var frag = document.createDocumentFragment();for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el);}document.body.appendChild(frag); 优化后:12345678var frag = document.createDocumentFragment();var pEl = document.getElementsByTagName('p')[0];for (var i = 0; i < 1000; i++) { var el = pEl.cloneNode(false); el.innerHTML = i; frag.appendChild(el);}document.body.appendChild(frag); 1.3 使用一次 innerHTML 赋值代替构建 dom 元素 说明:根据数据构建列表样式的时候,使用设置列表容器 innerHTML 的方式,比构建 dom 元素并 append 到页面中的方式,效率有数量级上的提高。 优化前:1234567var frag = document.createDocumentFragment();for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el);}document.body.appendChild(frag); 优化后:1234567var html = [];for (var i = 0; i < 1000; i++) { html.push('' + i + '');}document.body.innerHTML = html.join(''); 1.4 使用 firstChild 和 nextSibling 代替 childNodes 遍历 dom 元素说明:约能获得 30%-50% 的性能提高。逆向遍历时使用 lastChild 和 previousSibling 。优化前:12345var nodes = element.childNodes;for (var i = 0, l = nodes.length; i < l; i++) {var node = nodes[i];……} 优化后:12345var node = element.firstChild;while (node) {……nodenode = node.nextSibling;} 2. 字符串2.1 使用 Array 做为 StringBuffer ,代替字符串拼接的操作说明: IE 在对字符串拼接的时候,会创建临时的 String 对象;经测试,在 IE 下,当拼接的字符串越来越大时,运行效率会急剧下降。 Fx 和 Opera 都 对字符串拼接操作进行了优化;经测试,在 Fx 下,使用 Array 的 join 方式执行时间约为直接字符串拼接的 1.4 倍。优化前:123456var now = new Date();var str = '';for (var i = 0; i < 10000; i++) { str += '123456789123456789';}alert(new Date() - now); 优化后:1234567var now = new Date();var strBuffer = [];for (var i = 0; i < 10000; i++) { strBuffer.push('123456789123456789');}var str = strBuffer.join('');alert(new Date() - now); 3. 循环语句3.1 将循环控制量保存到局部变量说明:对数组和列表对象的遍历时,提前将 length 保存到局部变量中,避免在循环的每一步重复取值。优化前:1234var list = document.getElementsByTagName('p');for (var i = 0; i < list.length; i++) { ……} 优化后:1234var list = document.getElementsByTagName('p');for (var i = 0, l = list.length; i < l; i++) { ……} 3.2 顺序无关的遍历时,用 while 替代 for说明:该方法可以减少局部变量的使用。比起效率优化,更能直接看到的是字符数量的优化。该做法有程序员强迫症的嫌疑。优化前:12345var arr = [1,2,3,4,5,6,7];var sum = 0;for (var i = 0, l = arr.length; i < l; i++) { sum += arr[i];} 优化后:12345var arr = [1,2,3,4,5,6,7];var sum = 0, l = arr.length;while (l--) { sum += arr[l];} 4. 条件分支4.1 将条件分支,按可能性顺序从高到低排列说明:可以减少解释器对条件的探测次数。 4.2 在同一条件子的多( >2 )条件分支时,使用 switch 优于 if说明: switch 分支选择的效率高于 if ,在 IE 下尤为明显。 4 分支的测试, IE 下 switch 的执行时间约为 if 的一半。 4.3 使用三目运算符替代条件分支优化前:12345if (a > b) {num = a;} else {num = b;} 优化后:1num = a > b ? a : b; 5. 定时器5.1 需要不断执行的时候,优先考虑使用 setInterval说明: setTimeout 每一次都会初始化一个定时器。 setInterval 只会在开始的时候初始化一个定时器优化前:12345678var timeoutTimes = 0;function timeout () { timeoutTimes++; if (timeoutTimes < 10) { setTimeout(timeout, 10); }}timeout(); 优化后:12345678var intervalTimes = 0;function interval () { intervalTimes++; if (intervalTimes >= 10) { clearInterval(interv); }}var interv = setInterval(interval, 10); 5.2 使用 function 而不是 string说明:如果把字符串作为 setTimeout 和 setInterval 的参数,浏览器会先用这个字符串构建一个 function 。 优化前:12var num = 0;setTimeout('num++', 10); 优化后:12345var num = 0;function addNum () { num++;}setTimeout(addNum, 10); 6. 其他6.1 尽量不使用动态语法元素 说明: eval 、 Function 、 execScript 等语句会再次使用 javascript 解析引擎进行解析,需要消耗大量的执行时间。 6.2 重复使用的调用结果,事先保存到局部变量 说明:避免多次取值的调用开销。优化前:12var h1 = element1.clientHeight + num1;var h2 = element1.clientHeight + num2; 优化后:123var eleHeight = element1.clientHeight;var h1 = eleHeight + num1;var h2 = eleHeight + num2; 6.3 使用直接量说明:123var a = new Array(param,param,...) -> var a = []var foo = new Object() -> var foo = {}var reg = new RegExp() -> var reg = /.../ 6.4 避免使用 with 说明: with 虽然可以缩短代码量,但是会在运行时构造一个新的 scope 。OperaDev 上还有这样的解释,使用 with 语句会使得解释器无法在语法解析阶段对代码进行优化。对此说法,无法验证。优化前:1234with (a.b.c.d) {property1 = 1;property2 = 2;} 优化后:123var obj = a.b.c.d;obj.property1 = 1;obj.property2 = 2; 6.5 巧用 || 和 && 布尔运算符优化前:123function eventHandler (e) {if(!e) e = window.event;} 优化后:123function eventHandler (e) {ee = e || window.event;} 优化前:123if (myobj) {doSomething(myobj);} 优化后:1myobj && doSomething(myobj); 6.6 类型转换 说明: 1). 数字转换成字符串,应用 “” + 1 ,性能上: (“” +) > String() > .toString() > new String() ; 2). 浮点数转换成整型,不使用 parseInt() , parseInt() 是用于将字符串转换成数字,而不是浮点数和整型之间的转换,建议使用 Math.floor() 或者 Math.round() 3). 对于自定义的对象,推荐显式调用 toString() 。内部操作在尝试所有可能性之后,会尝试对象的 toString() 方法尝试能否转化为 String 。 二.内存管理2.1 循环引用说明:如果循环引用中包含 DOM 对象或者 ActiveX 对象,那么就会发生内存泄露。内存泄露的后果是在浏览器关闭前,即使是刷新页面,这部分内存不会被浏览器释放。 简单的循环引用:1234var el = document.getElementById('MyElement');var func = function () {…}el.func = func;func.element = el; 但是通常不会出现这种情况。通常循环引用发生在为 dom 元素添加闭包作为 expendo 的时候。 如:12345function init() { var el = document.getElementById('MyElement');el.onclick = function () {……}}init(); init 在执行的时候,当前上下文我们叫做 context 。这个时候, context 引用了 el , el 引用了 function , function 引用了 context 。这时候形成了一个循环引用。 下面 2 种方法可以解决循环引用: 1) 置空 dom 对象优化前:12345function init() {var el = document.getElementById('MyElement');el.onclick = function () {……}}init(); 优化后:123456function init() {var el = document.getElementById('MyElement');el.onclick = function () {……}el = null;}init(); 将 el 置空, context 中不包含对 dom 对象的引用,从而打断循环应用。如果我们需要将 dom 对象返回,可以用如下方法:优化前:123456function init() { var el = document.getElementById('MyElement'); el.onclick = function () {……} return el;}init(); 1234567891011优化后:function init() {var el = document.getElementById('MyElement');el.onclick = function () {……}try{return el;} finally { el = null;}}init(); 2) 构造新的 context优化前:12345function init() { var el = document.getElementById('MyElement'); el.onclick = function () {……}}init(); 优化后:123456function elClickHandler() {……}function init() { var el = document.getElementById('MyElement'); el.onclick = elClickHandler;}init(); 把 function 抽到新的 context 中,这样, function 的 context 就不包含对 el 的引用,从而打断循环引用。 2.2 通过 javascript 创建的 dom 对象,必须 append 到页面中说明: IE 下,脚本创建的 dom 对象,如果没有 append 到页面中,刷新页面,这部分内存是不会回收的!示例代码:1234567891011function create () { var gc = document.getElementById('GC'); for (var i = 0; i < 5000 ; i++) { var el = document.createElement('div'); el.innerHTML = "test"; // 下面这句可以注释掉,看看浏览器在任务管理器中,点击按钮然后刷新后的内存变化 gc.appendChild(el); } } 2.3 释放 dom 元素占用的内存说明:将 dom 元素的 innerHTML 设置为空字符串,可以释放其子元素占用的内存。在 rich 应用中,用户也许会在一个页面上停留很长时间,可以使用该方法释放积累得越来越多的 dom 元素使用的内存。 2.4 释放 javascript 对象说明:在 rich 应用中,随着实例化对象数量的增加,内存消耗会越来越大。所以应当及时释放对对象的引用,让 GC 能够回收这些内存控件。对象: obj = null对象属性: delete obj.myproperty数组 item :使用数组的 splice 方法释放数组中不用的 item 2.5 避免 string 的隐式装箱说明:对 string 的方法调用,比如 ‘xxx’.length ,浏览器会进行一个隐式的装箱操作,将字符串先转换成一个 String 对象。推荐对声明有可能使用 String 实例方法的字符串时,采用如下写法:1var myString = new String('Hello World');]]></content>
</entry>
<entry>
<title><![CDATA[javascript闭包]]></title>
<url>%2F2017%2F02%2F25%2Fjavascript_closure%2F</url>
<content type="text"><![CDATA[学习Javascript闭包(Closure)闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。下面就是我的学习笔记,对于Javascript初学者应该是很有用的。 一、变量的作用域要理解闭包,首先必须理解Javascript特殊的变量作用域。变量的作用域无非就是两种:全局变量和局部变量。Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。12345 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量。1234 function f1(){ var n=999; } alert(n); // error 这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!12345 function f1(){ n=999; } f1(); alert(n); // 999 二、如何从外部读取局部变量?出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。123456 function f1(){ var n=999; function f2(){ alert(n); // 999 } } 在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!123456789 function f1(){ var n=999; function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 三、闭包的概念上一节代码中的f2函数,就是闭包。各种专业文献上的”闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成”定义在一个函数内部的函数”。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。 四、闭包的用途闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。怎么来理解这句话呢?请看下面的代码。123456789101112 function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000 在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。这段代码中另一个值得注意的地方,就是”nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。 五、使用闭包的注意点1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。 六、思考题如果你能理解下面两段代码的运行结果,应该就算理解闭包的运行机制了。代码片段一。12345678910 var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); 代码片段二。1234567891011 var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());]]></content>
</entry>
<entry>
<title><![CDATA[http_agreement]]></title>
<url>%2F2017%2F02%2F24%2Fhttp_protocol_entry%2F</url>
<content type="text"><![CDATA[HTTP 协议入门作者: 阮一峰 转载地址HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点。本文介绍 HTTP 协议的历史演变和设计思路。 一、HTTP/0.9HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。最早版本是1991年发布的0.9版。该版本极其简单,只有一个命令GET。1GET /index.html 上面命令表示,TCP 连接(connection)建立后,客户端向服务器请求(request)网页index.html。协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。123<html> <body>Hello World</body></html> 服务器发送完毕,就关闭TCP连接。 二、HTTP/1.02.1 简介1996年5月,HTTP/1.0 版本发布,内容大大增加。首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。其次,除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。再次,HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。2.2 请求格式下面是一个1.0版的HTTP请求的例子。123GET / HTTP/1.0User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)Accept: */* 可以看到,这个格式与0.9版有很大变化。第一行是请求命令,必须在尾部添加协议版本(HTTP/1.0)。后面就是多行头信息,描述客户端的情况。2.3 回应格式服务器的回应如下。12345678910HTTP/1.0 200 OKContent-Type: text/plainContent-Length: 137582Expires: Thu, 05 Dec 1997 16:00:00 GMTLast-Modified: Wed, 5 August 1996 15:55:28 GMTServer: Apache 0.84<html> <body>Hello World</body></html> 回应的格式是”头信息 + 一个空行(\r\n) + 数据”。其中,第一行是”协议版本 + 状态码(status code) + 状态描述”。2.4 Content-Type 字段关于字符的编码,1.0版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。下面是一些常见的Content-Type字段的值。123456789101112text/plaintext/htmltext/cssimage/jpegimage/pngimage/svg+xmlaudio/mp4video/mp4application/javascriptapplication/pdfapplication/zipapplication/atom+xml 这些数据类型总称为MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔。除了预定义的类型,厂商也可以自定义类型。1application/vnd.debian.binary-package 上面的类型表明,发送的是Debian系统的二进制数据包。MIME type还可以在尾部使用分号,添加参数。1Content-Type: text/html; charset=utf-8 上面的类型表明,发送的是网页,而且编码是UTF-8。客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式。 Accept: /上面代码中,客户端声明自己可以接受任何格式的数据。MIME type不仅用在HTTP协议,还可以用在其他地方,比如HTML网页。123<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><!-- 等同于 --><meta charset="utf-8" /> 2.5 Content-Encoding 字段由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。123Content-Encoding: gzipContent-Encoding: compressContent-Encoding: deflate 客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法。1Accept-Encoding: gzip, deflate 2.6 缺点HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。1Connection: keep-alive 这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。1Connection: keep-alive 一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。 三、HTTP/1.11997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。3.1 持久连接1.1 版的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。1Connection: close 目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。3.2 管道机制1.1 版还引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。3.3 Content-Length 字段一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是Content-length字段的作用,声明本次回应的数据长度。1Content-Length: 3495 上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。在1.0版中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。3.4 分块传输编码使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用”流模式”(stream)取代”缓存模式”(buffer)。因此,1.1版规定可以不使用Content-Length字段,而使用”分块传输编码”(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。1Transfer-Encoding: chunked 每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。下面是一个例子。1234567891011121314151617HTTP/1.1 200 OKContent-Type: text/plainTransfer-Encoding: chunked25This is the data in the first chunk1Cand this is the second one3con8sequence0 3.5 其他功能1.1版还新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名。1Host: www.example.com 有了Host字段,就可以将请求发往同一台服务器上的不同网站,为虚拟主机的兴起打下了基础。3.6 缺点虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为”队头堵塞”(Head-of-line blocking)。为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。 四、SPDY 协议2009年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。这个协议在Chrome浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。 五、HTTP/22015年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。5.1 二进制协议HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为”帧”(frame):头信息帧和数据帧。二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。5.2 多工HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”。举例来说,在一个TCP连接里面,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。这样双向的、实时的通信,就叫做多工(Multiplexing)。5.3 数据流因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。5.4 头信息压缩HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。5.5 服务器推送HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。]]></content>
</entry>
<entry>
<title><![CDATA[sublime text3开发环境]]></title>
<url>%2F2017%2F02%2F22%2Fsublime_text3%2F</url>
<content type="text"><![CDATA[sublime text3开发环境搭建,常用插件整理sublime是我最喜欢的编辑器,简约高效、轻便灵活、功能插件丰富. 注册码:—– BEGIN LICENSE —–Michael BarnesSingle User LicenseEA7E-8213858A353C41 872A0D5C DF9B2950 AFF6F667C458EA6D 8EA3C286 98D1D650 131A97ABAA919AEC EF20E143 B361B1E7 4C8B7F04B085E65E 2F5F5360 8489D422 FB8FC1AA93F6323C FD7F7544 3F39C318 D95E6480FCCC7561 8A4A1741 68FA4223 ADCEDE07200C25BE DBBC4855 C4CFB774 C5EC138C0FEC1CEF D9DCECEC D3A5DAD1 01316C36—— END LICENSE —— 常用设置:设置自动保存:”save_on_focus_lost”: true,设置默认缩进:”tab_size”:2… 常用插件123456789101112131415161718192021222324安装package control # tool菜单下选中package control安装 emmet # 编码快捷键 //前端神器 !important安装 jsformat # js代码格式化安装 LESS # 代码高亮安装 alignment # 对齐变量等号安装 sublime-autoprefixer # 自动补充浏览器兼容前缀安装 Bracket Highlighter # 自动代码匹配安装 jQuery # jq代码提示安装 DocBlockr # 代码注释美化 //!important安装 AutoFileName # 自动补全文件名 //!important安装 Trailing spaces # 去除多余空格 //强迫症福音安装 git # git管理安装 ColorPicker # 颜色提取 //!important安装 File Header # 新建文件时,自动创建文件头信息(开发者,时间等等)安装 rem-unit # 移动端开发神器,px单位自动转rem单位(需设置根字体大小)安装 CSScomb # 也是神器,可按照设置,重新排序css代码安装 sublime server # sublime服务环境深空灰主题 spacegray # 深空灰主题海军蓝主题 Materrial Theme # 精美的主题,推荐安装 Trmmer # 代码格式化和对齐安装 JsMinifier # 该插件基于Google Closure compiler,自动压缩js文件。安装 QuoteHTML # 让js代码中插入html代码片段变得简便安装 emmet liveStyle # 安装后还需要谷歌浏览器安装一个liveStyle插件,浏览器启动插件后,在开发者工具里调整样式直接会保存在源文件。同时源文件修改样式,会自动刷新浏览器页面。太方便了... 常用的插件都简单介绍了一下,还有几个插件安装后没有显示。例如:Vuejs Snippets / vue syntax highLight / react-native-snippets 等等。提高基于vue / react-native框架开发的效率。其中,emmet插件已经配置好微信小程序常用代码片段。如果需要使用我的sublime配置环境,可以到我的github拷贝,传送门.有使用方法描述 效果图: 补充:Webstorm 16.3激活教程。在打开的License Activation窗口中选择“License server”,在输入框输入下面的网址点击,点击Activate即可。1http://idea.iteblog.com/key.php]]></content>
</entry>
<entry>
<title><![CDATA[javascript函数]]></title>
<url>%2F2017%2F02%2F21%2Fjavascript_function%2F</url>
<content type="text"><![CDATA[函数声明(静态函数)函数声明有个特征就是函数可以函数声明提前1234hello();function hello(){console.log('hello js');} 函数表达式(Function expressions)1234var hello2 = function(){ console.log('hello2 js');}hello2(); 这种方式命名,没有函数声明提前,这个方式也是自己比较喜欢用的方式。 匿名函数( anonymous)123(function(){ console.log('message');})() 也可以直接传入变量,jQuery源码用的比较的多,用匿名函数的好处就是可以减少命名的冲突,省的为了只执行一次的函数你还要去命名123(function(e){ console.log(e);})(2) 自动执行的其他的写法1234567var auto = (function(){ console.log('auto message');})()var auto = (function(){ console.log('auto message2');}()) 回调函数(callback)就是把函数当做变量,这个算是js中比较特别的地方,nodejs的异步回调的大体就是那样1234567function person(callback,name,age){ callback(name,age);}function output(name,age){ console.log(name+':'+age);}new person(output,'zs',18); 递归函数关于递归,这个平时很少应用。简单的说就是自己调用自己:123456789function add(n){ if(n<=1){ return 1; }else{ return n+add(n-1) }}// var i= add(4);console.log(add(4)); 构造函数123456789101112131415161718192021222324252627282930313233* 构造函数首字母大写* this用法,指向本身,这个比较复杂,以后总结好了,弄明白了再细说* 闭包问题也是比较头痛的问题,留在以后。会造成内存消耗构造函数的三部曲:* 构造方法* 定义属性* 原型法定义函数,这样比较的节省内存* 函数的继承,call,apply(用在传递数组)函数的继承:function Person(name,age){ this.name=name; this.age=age;}Person.prototype.out=function(){ var self=this; console.log(this.name+':'+this.age);}function Student(name,age,id){ // Person.call(this,name,age); Person.apply(this,[name,age]);//或是用apply都行 this.id=id;}Student.prototype.output=function(){ var self=this; console.log(this.name+':'+this.age+';'+this.id);}new Person('lh',18).out();new Student('KK',18,'XUESHENG').output(); 函数的重载:主要是通过argument.length分别调用的,没有怎么用过123function f(x){}function f(x,y){}function f(x,y,z){} 总结最优的命名函数方法:用构造方法生成成员变量,用原型法生成成员方法,减少内存的消耗123456789101112function Person(name,age){ this.name=name; this.age=age; this.say(); // 这样也行(构造方法分配成员方法),比较喜欢原型法构造函数 this.say=function(){ console.log(name+age); }}Person.prototype.say=function(){ console.log(name+age);} javascript函数封装的方式1、JS封装就是尽量把使用的方式简单化,内部逻辑和使用解耦。通俗的说就是使用的时候只需要知道参数和返回值,其他条件尽量不要使用人员进行设置。2、JS封装的方法有函数方式、对象的方式、闭包的方式。 举例1)函数方式123function kk(a,b){ 内部对a,b怎么处理就不需要关心了} 2)对象方式123456function kk(a,b){ this.x = a; this.y = b;}var k = new kk(1,2);//通过面向对象的方式alert(k.x); 3)闭包方式123456789function kk(a,b){ var k = 1; return function tt(){ k++; }}var u = kk(1,2);u();//闭包实现累加u();//闭包实现累加 //简单理解如下://封装:将字段,属性,方法等封装成类//例如:将人封装成一个类,有name,age等字段,有eat方法1234567891011121314151617function Person(name, age){ this._name = name; this._age = age; this.getAge = function(){ return this.age; }; this.setAge = function(value){ this.age = value; }; this.getName = function(){ return this.name; }; this.eat=function() { alert(this._name+" Eat!"); };} //使用这个类:12var p1 = new Person("张三", 12);p1.eat();]]></content>
</entry>
<entry>
<title><![CDATA[git-command]]></title>
<url>%2F2017%2F02%2F21%2Fgit-command%2F</url>
<content type="text"><![CDATA[git常用指令123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687git init # 初始化本地git仓库(创建新仓库)git config --global user.name "xxx" # 配置用户名git config --global user.email "[email protected]" # 配置邮件git config --global color.ui true # git status等命令自动着色git config --global color.status autogit config --global color.diff autogit config --global color.branch autogit config --global color.interactive autogit subtree push --prefix=dist origin gh-pages # 将dist目录上传到gh-pages分支git config --global --unset http.proxy # remove proxy configuration on gitgit clone git+ssh://[email protected]/VT.git # clone远程仓库git status # 查看当前版本状态(是否修改)git add xyz # 添加xyz文件至indexgit add . # 增加当前子目录下所有更改过的文件至indexgit commit -m 'xxx' # 提交git commit --amend -m 'xxx' # 合并上一次提交(用于反复修改)git commit -am 'xxx' # 将add和commit合为一步git rm xxx # 删除index中的文件git rm -r * # 递归删除git log # 显示提交日志git log -1 # 显示1行日志 -n为n行git log -5git log --stat # 显示提交日志及相关变动文件git log -p -mgit show dfb02e6e4f2f7b573337763e5c0013802e392818 # 显示某个提交的详细内容git show dfb02 # 可只用commitid的前几位git show HEAD # 显示HEAD提交日志git show HEAD^ # 显示HEAD的父(上一个版本)的提交日志 ^^为上两个版本 ^5为上5个版本git tag # 显示已存在的taggit tag -a v2.0 -m 'xxx' # 增加v2.0的taggit show v2.0 # 显示v2.0的日志及详细内容git log v2.0 # 显示v2.0的日志git diff # 显示所有未添加至index的变更git diff --cached # 显示所有已添加index但还未commit的变更git diff HEAD^ # 比较与上一个版本的差异git diff HEAD -- ./lib # 比较与HEAD版本lib目录的差异git diff origin/master..master # 比较远程分支master上有本地分支master上没有的git diff origin/master..master --stat # 只显示差异的文件,不显示具体内容git remote add origin git+ssh://[email protected]/VT.git # 增加远程定义(用于push/pull/fetch)git branch # 显示本地分支git branch --contains 50089 # 显示包含提交50089的分支git branch -a # 显示所有分支git branch -r # 显示所有原创分支git branch --merged # 显示所有已合并到当前分支的分支git branch --no-merged # 显示所有未合并到当前分支的分支git branch -m master master_copy # 本地分支改名git checkout -b master_copy # 从当前分支创建新分支master_copy并检出git checkout -b master master_copy # 上面的完整版git checkout features/performance # 检出已存在的features/performance分支git checkout --track hotfixes/BJVEP933 # 检出远程分支hotfixes/BJVEP933并创建本地跟踪分支git checkout v2.0 # 检出版本v2.0git checkout -b devel origin/develop # 从远程分支develop创建新本地分支devel并检出git checkout -- README # 检出head版本的README文件(可用于修改错误回退)git merge origin/master # 合并远程master分支至当前分支git cherry-pick ff44785404a8e # 合并提交ff44785404a8e的修改git push origin master # 将当前分支push到远程master分支git push origin :hotfixes/BJVEP933 # 删除远程仓库的hotfixes/BJVEP933分支git push --tags # 把所有tag推送到远程仓库git fetch # 获取所有远程分支(不更新本地分支,另需merge)git fetch --prune # 获取所有原创分支并清除服务器上已删掉的分支git pull origin master # 获取远程分支master并merge到当前分支git mv README README2 # 重命名文件README为README2git reset --hard HEAD # 将当前版本重置为HEAD(通常用于merge失败回退)git rebasegit branch -d hotfixes/BJVEP933 # 删除分支hotfixes/BJVEP933(本分支修改已合并到其他分支)git branch -D hotfixes/BJVEP933 # 强制删除分支hotfixes/BJVEP933git ls-files # 列出git index包含的文件git show-branch # 图示当前分支历史git show-branch --all # 图示所有分支历史git whatchanged # 显示提交历史对应的文件修改git revert dfb02e6e4f2f7b573337763e5c0013802e392818 # 撤销提交dfb02e6e4f2f7b573337763e5c0013802e392818git ls-tree HEAD # 内部命令:显示某个git对象git rev-parse v2.0 # 内部命令:显示某个ref对于的SHA1 HASHgit reflog # 显示所有提交,包括孤立节点git show HEAD@{5}git show master@{yesterday} # 显示master分支昨天的状态git log --pretty=format:'%h %s' --graph # 图示提交日志git show HEAD~3git show -s --pretty=raw 2be7fcb476git stash # 暂存当前修改,将所有至为HEAD状态git stash list # 查看所有暂存git stash show -p stash@{0} # 参考第一次暂存git stash apply stash@{0} # 应用第一次暂存git grep "delete from" # 文件中搜索文本“delete from”git grep -e '#define' --and -e SORT_DIRENTgit gcgit fsck git中 gitignore 文件的正确用法使用 git 做代码管理工具时,设置 gitignore 是必不可少的流程,一些系统或者 IDE 会在目录下生成与项目不相关的文件,而这些文件我们不期望被提交到仓库之中。理解 gitignore 的 pattern 规则十分重要。 PATTERN 规则关于 Pattern 规则,可以查看 git 的相关文档:大致有以下几点:123456空行不匹配任何内容,所以可以作为块分隔符;# 开头表示注释,如果相匹配 #,可以在前面加一个反斜杠,即 \#;除非加了反斜杠,否则一连串的空格会被忽略;如果在匹配的内容前面加上 !,则这些匹配过的部分将被移出,如果要匹配以 ! 开头的内容,需要加上反斜杠,如 \!important.txt;如果一个匹配 pattern 后面有一个斜杠,如 foo/,则默认会匹配所有(包含父子文件夹)中的 foo 文件夹内容,并且它不会匹配单个的文件;如果一个匹配 pattern 不包含斜杠,如 foo,Git 会将其作为一个 shell 的查找命令匹配内容。 需要注意的 **: 如果一个 pattern 以 开头,如 /foo,最后会匹配所有文件夹下的 foo 文件(夹); 如果一个 pattern 以 / 开头,如 abc/,则表示匹配 abc 目录下的所有内容((relative to the location of the .gitignore file, with infinite depth); 如果一个 pattern 中间包含 ,如 a//b,则会匹配 a/b、a/x/b、a/x/y/b以及所有类似的内容。 gitignore 相关的问题匹配示例如果我们要匹配 ‘foo’ 目录下除去 ‘foo/bar/‘ 的内容,可以这样做:12foo/!foo/bar/ 如果要匹配所有目录下的 node_modules 文件夹,只需要这样做:1node_modules/ 如果要匹配所有的 json 文件,可以这样做:1*.json git 操作中,add 之后再加入 gitignoreGit 操作中经常会出现这样的问题,当我们 git add 之后,突然想起来要添加一个 gitignore 文件,但是一些诸如 node_modules/, cache/ 等文件已经被 add 进去了,这些文件不会被 ignore 掉,怎么办?最直接的方式是:12345# 这一步的操作相当于回到 git add 上一步git rm -r --cached .# 然后重新 addgit add .git commit -m "fixed untracked files" git 添加空文件夹Git 默认是不添加空文件夹的,如果一定要加入这个文件夹,有以下方案:12在文件夹添加文件,然后删除在文件夹中添加一个 .gitkeep 文件 让 git 不要添加 gitignore 文件,可以 add 后再 remove 掉:1git rm -r --cached .gitignore Git 操作涉及的命令巨多,但是日常开发中用到的就那么几个,把原理搞清楚,用起来得心应手。]]></content>
</entry>
<entry>
<title><![CDATA[mySQLNote]]></title>
<url>%2F2017%2F02%2F20%2FmySQLNote%2F</url>
<content type="text"><![CDATA[mySQL常用命令选择数据库:use databaseName;显示数据库:show databases;查看数据/:select * from tableName;创建数据库:create databaseName ( 列名 数据类型//创建table时 );删除数据库:drop databaseName;删除数据表:drop table tableName;插入数据:insert into target_tbl (字段1-n) values( ‘123123’,’123’,’123’,…,’n' )例子1:单表的MySQL UPDATE语句:1UPDATE [LOW_PRIORITY] [IGNORE] tbl_name SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition] [ORDER BY ...] [LIMIT row_count] 例子2:多表的UPDATE语句:1UPDATE [LOW_PRIORITY] [IGNORE] table_references SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition] 命令:alter table 表名 add字段 类型 其他;例如:在表MyClass中添加了一个字段passtest,类型为int(4),默认值为01mysql> alter table MyClass add passtest int(4) default '0' 加索引 mysql> alter table 表名 add index 索引名 (字段名1[,字段名2 …]);1例子: mysql> alter table employee add index emp_name (name); 加主关键字的索引 mysql> alter table 表名 add primary key (字段名);1例子: mysql> alter table employee add primary key(id); 加唯一限制条件的索引 mysql> alter table 表名 add unique 索引名 (字段名);1例子: mysql> alter table employee add unique emp_name2(cardnumber); 删除某个索引 mysql> alter table 表名 drop index 索引名;1例子: mysql>alter table employee drop index emp_name; 增加字段:1mysql> ALTER TABLE table_name ADD field_name field_type; 修改原字段名称及类型:1mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type; 删除字段:1MySQL ALTER TABLE table_name DROP field_name; 命令:rename table 原表名 to 新表名;12例如:在表MyClass名字更改为YouClass mysql> rename table MyClass to YouClass;]]></content>
</entry>
<entry>
<title><![CDATA[jQueryNote]]></title>
<url>%2F2017%2F02%2F20%2FjQueryNote%2F</url>
<content type="text"><![CDATA[jquery trigger()源码1234567891011121314151617181920212223242526272829303132333435363738394041/** * 事件触发器 * @param { Object } DOM元素 * @param { String / Object } 事件类型 / event对象 * @param { Array } 传递给事件处理函数的附加参数 * @param { Boolean } 是否冒泡 **/ trigger : function( elem, event, data, isStopPropagation ){ var type = event.type || event, // 冒泡的父元素,一直到document、window parent = elem.parentNode || elem.ownerDocument || elem === elem.ownerDocument && win, eventHandler = $.data( elem, type + 'Handler' ); isStopPropagation = typeof data === 'boolean' ? data : (isStopPropagation || false); data = data && isArray( data ) ? data : []; // 创建自定义的event对象 event = typeof event === 'object' ? event : { type : type, preventDefault : noop, stopPropagation : function(){ isStopPropagation = true; } }; event.target = elem; data.unshift( event ); if( eventHandler ){ eventHandler.call( elem, data ); } // 递归调用自身来模拟冒泡 if( parent && !isStopPropagation ){ data.shift(); this.trigger( parent, event, data ); } } 封装一个核心函数,实现类jquery的链式调用123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108/* 函数库封装,创建一个核心对象。Ice */ var $ = function(){ return new Ice(); };function Ice(){ //创建一个数组来保存获取的节点和节点数组 this.elem = []; //获取elem的id this.getId=function(obj){ obj = obj.noSpace(); if(obj.substring(0,1)=="#"){ nobj = obj.substring(1); nobj = document.getElementById(nobj); this.elem.push(nobj); return this; } } //获取元素elem的class this.getClass=function(obj){ obj = obj.noSpace(); if(obj.substring(0,1)=="."){ nobj = obj.substring(1); nelem = document.getElementsByClassName(nobj); for (var i=0; i < nelem.length; i++) { this.elem.push(nelem[i]); } return this; } }}//定义css()方法Ice.prototype.css=function(attr,val){ for (var i=0; i < this.elem.length; i++) { if (arguments.length==1) { if (typeof window.getComputedStyle != "undefined"){//W3C return window.getComputedStyle(this.elem[i],null)[attr]; }else if(typeof this.elem[i].currentStyle != "undefined"){//IE return this.elem[i].currentStyle[attr]; } return this.elem[i].style[attr]; } this.elem[i].style[attr] = val; } return this;}//定义html()方法Ice.prototype.html=function(str){ for (var i=0; i < this.elem.length; i++) { if (arguments.length==0) { return this.elem[i].innerHTML; } this.elem[i].innerHTML = str; } return this;}//定义click()方法Ice.prototype.click=function(fn){ for (var i=0; i < this.elem.length; i++) { this.elem[i].onclick = fn; } return this;}//定义addClass()方法Ice.prototype.addClass=function(className){ className = className.noSpace(); var reg = new RegExp('(\\s|^)'+className+'(\\s|$)'); for (var i=0; i < this.elem.length; i++) { if (!this.elem[i].className.match(reg)) {//判断类名是否存在,不存在则添加 this.elem[i].className += ' '+className; } } return this;}//定义removeClass()方法Ice.prototype.removeClass=function(className){ className = className.noSpace(); var reg = new RegExp('(\\s|^)'+className+'(\\s|$)'); for (var i=0; i < this.elem.length; i++) { if (this.elem[i].className.match(reg)) {//判断类名是否存在,存在则删除,即用空格替代 this.elem[i].className = this.elem[i].className.replace(reg,' '); } } return this;}//定义eq()方法Ice.prototype.eq=function(num){ var elems = this.elem[num]; this.elem = [];//清空元素数组 this.elem[0] = elems; return this;}//定义first()方法Ice.prototype.first=function(){ var elems = this.elem[0] this.elem = [];//清空元素数组 this.elem[0] = elems; return this;}//定义last()方法Ice.prototype.last=function(){ var la = this.elem.length-1; var elems = this.elem[la]; this.elem = [];//清空元素数组 this.elem[0] = elems; return this;} 封装document对象cookies方法12sessionStorage.setItem()&sessionStorage.getItem();localStorage.setItem()&localStorage.getItem(); //参数解析:name:cookie名 val:cookie值 expires:cookie过期时间 path:有效路径 domain:有效域名 secure:是否加密1234567891011121314151617181920212223242526272829303132333435363738394041424344454647function setCookie(name,val,expires,path,domain,secure){ var cookieName = encodeURIComponent(name)+"="+encodeURIComponent(val); if(expires instanceof Date){//setting expries day time cookieName +=";expires="+expires; } if (path) { cookieName +=";path="+path;//setting cookie path } if (domain) { cookieName +=";domian="+domain;//setting proxy name } if (secure) { cookieName +=";secure";//setting secure } document.cookies = cookieName;};function setCookieDate(day){ //get day function var date = null; if(typeof day == "number" && day>0){ date = new Date(); date.setDate(date.getDate()+7); }else{ throw new Error("你的天数不合法!请设置数字"); } return date;}setCookie("user","yang");setCookie("url","icetower.cn",setCookieDate(7));//获取cookies值function getCookie(name){ var cookieName = encodeURIComponent(name)+"="; var cookieStart = document.cookies.indexOf(cookieName); var cookieVal = null; if(cookieStart > -1){ var cookieEnd = document.cookies.indexOf(";",cookieStart); if (cookieEnd == -1) { var cookieEnd = document.cookies.length; } var val=document.cookies.substring(cookieStart+cookieName.length,cookieEnd); cookieVal=decodeURIComponent(val); } return cookieVal;};// console.log(getCookie("user"));// console.log(document.cookies); jquery点击空白,隐藏弹窗面板123456$(document).mouseup(function(e){ var _con = $(".tartet"); // 设置目标区域 if(!_con.is(e.target) && _con.has(e.target).length === 0){ $(".tartet").hide(); } });]]></content>
</entry>
<entry>
<title><![CDATA[javascript事件]]></title>
<url>%2F2017%2F02%2F20%2Fjavascript_event%2F</url>
<content type="text"><![CDATA[事件自定义使用自定义事件有助于解耦相关对象,保持功能的隔绝,在很多情况下,触发事件的代码和监听事件的代码是完全分离的.事件是与DOM交互的最常见的方式,但它也可以用于非DOM代码中–通过实现自定义事件.实现自定义事件的原理是创建一个管理事件的对象.如下代码是事件的定义:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152function EventTarget(){//存储事件处理程序,由n个键值对组成,键表示事件名,值是一个由事件处理程序组成的数组this.handlers = {};}EventTarget.prototype = {constructor:EventTarget,//添加事件addHandler:function(type,handler){ if(typeof this.handlers[type] == "undefined"){ this.handlers[type] = []; } this.handlers[type].push(handler);},//触发事件fire:function(event){ if(!event.target){ event.target = this; } if(this.handlers[event.type] instanceof Array){ var handlers = this.handlers[event.type]; for(var i=0,len=handlers.length;i < len;i++){ //将event传递给事件处理程序,event.target代表对象本身, event.type代表事件名,你可以根据情况为添加event属性 handlers[i](event); } }},//移除事件removeHandler:function(type,handler){ if(this.handlers[type] instanceof Array){ var handlers=this.handlers[type]; for(var i=0,len=handlers.length;i < len; i++){ if(handlers[i] == handler){ break; } } handlers.splice(i,1); }}};首先是定义了一个名为EventTarget的构造函数,为其定义的属性handlers用于存储事件处理程序,然后有三个操作方法添加到EventTarget的原型中,分别是addHandler fire remocveHander.addHander是向handlers中添加事件处理程序fire是触发handlers中的事件处理程序removeHandler是向handlers中移除事件处理程序注:事件处理程序通俗的讲就是事件被触发时需要执行的方法. 事件调用1234567891011var eventObj=new EventTarget(); //实例化一个EventTarget类型var handler=function(){ alert('event');}; //事件处理程序eventObj.addHandler('alert',handler); //为eventObj对象添加一个事件处理程序`handler`event.fire({type:'alert'}); //触发eventObj对象中的事件处理程序`handler`event.removeHandler('alert',handler); //删除eventObj对象中的事件处理程序`handler` 事件继承1234567891011121314151617181920212223242526272829303132当然我们也可以通过继承让其他引用类型继承EventTarget的属性和方法.//原型式继承var object=function(o){ function F(){} F.prototype=o; return new F();};//subType继承superType的原型对象var inheritPrototype=function(subType,superType){ var prototype=object(superType.prototype); prototype.constructor=subType; subType.prototype=prototype;}function Person(name,age){ //继承EventTarget的属性 EventTarget.call(this); this.name = name; this.age = age;}//继承EventTarget的方法inheritPrototype(Person,EventTarget);Person.prototype.say=function(message){ this.fire({type:'message',message:message}); //触发事件};//事件处理程序var handMessage=function(event){ alert(event.target.name + "says:" + event.message);};var person=new Person('yhlf',29);person.addHandler('message',handMessage);person.say('Hi there'); javascript阻止默认行为和事件冒泡1.阻止事件冒泡: event.stopPropagation();//现代浏览器 event.cancelBubble=true;//IE浏览器2.阻止默认行为: event.preventDefault();//现代浏览器 event.returnValue=false;//IE浏览器 封装一个事件处理函数event12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576//Event工具集,from:github.com/markyunmarkyun.Event = { //页面加载完成后 readyEvent: function(fn) { if (fn == null) { fn = document; } var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = fn; }else{ window.onload = function() { oldonload(); fn(); }; } }, //视能力分别使用 demo0 || demo1 || IE 方式来绑定事件 //参数:操作的元素,事件名称,事件处理程序 addEvent: function(element,type,handler) { if (element.addEventListener) { //事件类型、需要执行的函数、是否捕捉 element.addEventListener(type,handler,false); }else if (element.attachEvent) { element.attachEvent('on' + type, function() { handler.call(element); }); }else { element['on' + type] = handler; } }, //移除事件 removeEvent: function(element,type,handler) { if (element.removeEventListener) { element.removeEventListener(type,handler,false); }else if (element.datachEvent) { element.datachEvent('on' + type,handler); }else{ element['on' + type] = null; } }, //阻止事件(主要是事件冒泡,因为IE不支持事件捕获) stopPropagation: function(ev) { if (ev.stopPropagation) { ev.stopPropagation(); }else { ev.cancelBubble = true; } }, //取消事件的默认行为 preventDefault: function(event) { if (event.preventDefault) { event.preventDefault(); }else{ event.returnValue = false; } }, //获取事件目标 getTarget: function(event) { return event.target || event.srcElemnt; }, //获取event对象的引用,取到事件的所有信息,确保随时能使用event; getEvent: function(e) { var ev = e || window.event; if (!ev) { var c = this.getEvent.caller; while(c) { ev = c.argument[0]; if (ev && Event == ev.constructor) { break; } c = c.caller; } } retrun ev; }};]]></content>
</entry>
<entry>
<title><![CDATA[canvas笔记]]></title>
<url>%2F2017%2F02%2F20%2FcanvasNote%2F</url>
<content type="text"><![CDATA[12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667window.onload = function(){//页面加载完执行var canvas = document.getElementById(“id”);//获取canvas元素var context = canvas.getContext(“2d”);//调用canvas绘图接口,设置绘图的上下文环境var convas.width = x;var convas.height = x;//设置canvas画布大小var img = new Image();//重新定义一个图片对象img.onload = function(){//图片加载完成后执行 var img.width = convas.width; var img.height = canvas.height;//设置图片大小和canvas画布同样大小 drawImage(img,0,0);//根据图片自身大小直接绘制图形,drawImage()总共三种调用方式如下 drawImage(img,dx,dy,img.width,img.height); drawImage(img,sx,dy,img.width,img.height,dx,dy,canvas.width,canvas.height);//(sx,sy)是原图像起点坐标、(dx,dy)是目标 图像起点坐标}context.beginPath()//开始本次绘制标识context.clearRect(0,0,canvas.width,canvas.height);//清除整个画布,参数值为画布起点坐标和大小context.save();//保存画布context.arc(x,y,r,0,2Math*PI,false);//绘制一个圆形,(x,y)是圆心,r是半径,0是起始点,2π是结束点,默认fasle是按顺时针方向绘图var clippingRegion = {x:400,y:400,r:50};//定义裁剪区域context.arc(clippingRegion.x,clippingRegion.y,clippingRegion.r,0,Math.PI*2,false);//绘制裁剪区域context.clip();//将除了arc规定的这个区域以外的内容的全部剪掉context.restore();//画布恢复context.fillStyle = “color”;//图形填充颜色context.fill();//执行填充context.moveTo(x,y);//绘制线条起点位置坐标context.lineTo(x,y);//绘制线条结束位置坐标context.lineWidth = 10;//线条宽度context.lineCap = “butt";//默认,值还可以是“round”,突出圆形头,或者“square”,突出方形头context.lineJoin =“miter";//默认值尖角,“bevel”使用斜接的形式过度,”round”使用圆角形式过度context.miterLimit = 10;默认值,线条交接处,角度尖锐程度context.strokeStyle = “color”;//线条颜色context.stroke();//绘制线条content.rect(x,y,width,height);//绘制正方形content.fillRect();content.strokeRect();context.closePath()//结束本次绘制标识// var lGrd = context.createLinearGradient(0, 0, 400, 400);//创建线性渐变// lGrd.addColorStop(0, '#ff0000');// lGrd.addColorStop(1, '#0000ff');// context.fillStyle = lGrd;// context.fillRect(0, 0, 400, 400);//填充区域的起始点和宽高// var rGrd = context.createRadialGradient(600, 200, 100, 600, 200, 200);//创建径向渐变// rGrd.addColorStop(0, '#ccc');// rGrd.addColorStop(1, '#333');// context.fillStyle = rGrd;// context.fillRect(400, 400, 400, 400);/* 图形变换的方法,记得成对使用save()&&restore()方法,保存canvas绘图状态,保证图形变换后不会出错 */context.save();//保存画布context.translate(x,y);//平移的方法context.rotate(deg);//旋转的方法context.scale(x,y);//x轴和y轴缩放比例,注:scale会同时缩放外边框,左上角坐标值等副作用context.restore();//画布恢复}]]></content>
</entry>
<entry>
<title><![CDATA[正则表达式]]></title>
<url>%2F2017%2F02%2F20%2Fregex%2F</url>
<content type="text"><![CDATA[正则表达式是什么?解:在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。正则表达式也是用来进行文本匹配的工具,只不过比起通配符( *号),它能更精确地描述你的需求。 如果要精确地查找hi这个单词的话,我们应该使用 \bhi\b。 \b是正则表达式规定的一个特殊代码(好吧,某些人叫它元字符,metacharacter),代表着单词的开头或结尾,也就是单词的分界处。虽然通常英文的单词是由空格,标点符号或者换行来分隔的,但是\b并不匹配这些单词分隔字符中的任何一个,它只匹配一个位置。 . 是另一个元字符,匹配除了换行符以外的任意字符。同样是元字符,不过它代表的不是字符,也不是位置,而是数量——它指定前边的内容可以连续重复使用任意次以使整个表达式得到匹配。因此,.*连在一起就意味着任意数量的不包含换行的字符。 0\d\d-\d\d\d\d\d\d\d\d匹配这样的字符串:以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(也就是中国的电话号码。当然,这个例子只能匹配区号为3位的情形)。这里的\d是个新的元字符,匹配一位数字(0,或1,或2,或……)。-不是元字符,只匹配它本身。为了避免那么多烦人的重复,可以写这个表达式:0\d{2}-\d{8}。 \b , . , *,还有 \d.正则表达式里还有更多的元字符,比如\s匹配任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等。\w匹配字母或数字或下划线或汉字等。 字符转义:如果你想查找元字符本身的话,比如你查找.,或者,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。这时你就得使用\来取消这些字符的特殊意义。因此,你应该使用.和\。当然,要查找\本身,你也得用\. 例如:deerchao.net匹配deerchao.net,C:\Windows匹配C:\Windows。 未定论语法图表 创建一个正则表达式使用一个正则表达式字面量,如下所示:1var re = /ab+c/; 正则表达式字面量在脚本加载后编译。若你的正则表达式是常量,使用这种方式可以获得更好的性能。调用RegExp对象的构造函数,如下所示:1var re = new RegExp("ab+c"); 使用正则表达式正则表达式可以被用于RegExp的 exec和 test方法以及 String的 match、replace、search和 split方法。这些方法在JavaScript手册中有详细的解释。 使用正则表达式的方法123456**exec:** 一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回null)。**test:** 一个在字符串中测试是否匹配的RegExp方法,它返回true或false。**match:** 一个在字符串中执行查找匹配的String方法,它返回一个数组或者在未匹配到时返回null。**search:** 一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。**replace:** 一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。**split:** 一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的String方法。 当你想要知道在一个字符串中的一个匹配是否被找到,你可以使用test或search方法;想得到更多的信息(但是比较慢)则可以使用exec或match方法。如果你使用exec或match方法并且匹配成功了,那么这些方法将返回一个数组并且更新相关的正则表达式对象的属性和预定义的正则表达式对象(详见下)。如果匹配失败,那么exec方法返回null(也就是false)。 学习笔记在正则表达式中,字符分为普通字符和元字符; [] 是分类。在js中有很多默认的类。如:. 等同于 [ ^\r\n ], \s, \S, \d, \D … -在两个字符中的时候表示范围,否则表示普通字符 - () 表示分组,如果存在多个分组,使用$+数字序号表示匹配不同的分组,作用类似变量。在分组内加上?:表示忽略当前分组,如:(?: ignore).(normal)。分组也可以称为子表达式。 +表示匹配一个以上 ? 表示匹配最多一个 *表示匹配0个以上 | 是或的意思 ^ 表示匹配开头为XXX的字符 $ 表示匹配结尾为XXX的字符 {n} 其中n表示匹配n次;{n,m} 表示匹配n次到m次;{n,} 表示匹配至少n次;{0,m} 表示匹配至多m次; 前瞻:在正则表达式匹配到规则的时候,向前检查是否符合断言,后顾方向相反;符不符合特定断言称为肯定/正向匹配和否定/负向匹配; 正向前瞻:exp(?=assert) 如:’ad11’.replace(/\w(?=\d)/g,’Q’) >>> ‘aQ11’ 负向前瞻:exp(?!assert) 如: ‘adadad111’.replace(/\w(?!\d)/g,’Q’) >>> “QQQQQd11Q” 后顾:在js中不支持正则表达式后顾 正向后顾:exp(?<=assert)负向后顾:exp(?< !assert) js中的正则匹配默认是贪婪模式,在表达式后面加 ?,设置为非贪婪模式; 在表达式 var reg = /\w/gim 中, g表示global,全局匹配 i表示ignoreCase,忽略字母大小写 m表示multiple,表示多行匹配 正则表达式中,lastIndex是当前匹配字符的下一个字符的索引;source是正则表达式的文本。 正则表达式对象默认属性方法,如: .test(str) .exec(str) .replace(reg,str),其中第二个参数也可以是一个回调函数 .match(reg) .split(reg) .search(reg)]]></content>
</entry>
<entry>
<title><![CDATA[前端模块化开发的价值]]></title>
<url>%2F2017%2F02%2F20%2Fmodular_development%2F</url>
<content type="text"><![CDATA[1.前置概念AMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。例如:requireJS使用 Sea.js,在书写文件时,需要遵守 CMD (Common Module Definition)模块定义规范。一个文件就是一个模块。将javascript语言用于服务器端编程,这标志”Javascript模块化编程”正式诞生。因为老实说,在浏览器环境下,没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。 node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。CommonJS定义的模块分为:{模块引用(require)} {模块定义(exports)} {模块标识(module)}require()用来引入外部模块;exports对象用于导出当前模块的方法或变量,唯一的导出口;module对象就代表模块本身。 2.恼人的命名冲突我们从一个简单的习惯出发。我做项目时,常常会将一些通用的、底层的功能抽象出来,独立成一个个函数。并像模像样地把这些函数统一放在 util.js 里。需要用到时,引入该文件就行。这一切工作得很好,同事也很感激我提供了这么便利的工具包。直到团队越来越大,出现命名冲突。通过命名空间,的确能极大缓解冲突。但每每看到上面的代码,都忍不住充满同情。为了调用一个简单的方法,需要记住如此长的命名空间,这增加了记忆负担,同时剥夺了不少编码的乐趣。YUI3 通过沙箱机制,很好的解决了命名空间过长的问题。然而,也带来了新问题。12345YUI().use('a', 'b', function (Y) { Y.foo(); // foo 方法究竟是模块 a 还是 b 提供的? // 如果模块 a 和 b 都提供 foo 方法,如何避免冲突?}); 看似简单的命名冲突,实际解决起来并不简单。 3.烦琐的文件依赖由于当前js代码依赖于别的js文件。当项目越来越复杂,导致众多文件之间的依赖逐渐变成大问题。 通用组更新了前端基础类库,却很难推动全站升级。 业务组想用某个新的通用组件,但发现无法简单通过几行代码搞定。 一个老产品要上新功能,最后评估只能基于老的类库继续开发。 公司整合业务,某两个产品线要合并。结果发现前端代码冲突。 …… 对比requireJS相同之处RequireJS 和 Sea.js 都是模块加载器,倡导模块化开发理念,核心价值是让 JavaScript 的模块化开发变得简单自然。 主要区别如下SeaJS对模块的态度是懒执行, 而RequireJS对模块的态度是预执行 定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。 遵循的规范不同。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不同,导致了两者 API 不同。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。 推广理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。 对开发调试的支持有差异。Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。RequireJS 无这方面的明显支持。 插件机制不同。RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采取的是通用事件机制,插件类型更丰富。 小结除了解决命名冲突和依赖管理,使用 Sea.js 进行模块化开发还可以带来很多好处: 通过 exports 暴露接口。这意味着不需要命名空间了,更不需要全局变量。这是一种彻底的命名冲突解决方案。 通过 require 引入依赖。这可以让依赖内置,开发者只需关心当前模块的依赖,其他事情 Sea.js 都会自动处理好。对模块开发者来说,这是一种很好的 关注度分离,能让程序员更多地享受编码的乐趣。 模块的版本管理。通过别名等配置,配合构建工具,可以比较轻松地实现模块的版本管理。 提高可维护性。模块化可以让每个文件的职责单一,非常有利于代码的维护。Sea.js 还提供了 nocache、debug 等插件,拥有在线调试等功能,能比较明显地提升效率。 前端性能优化。Sea.js 通过异步加载模块,这对页面性能非常有益。Sea.js 还提供了 combo、flush 等插件,配合服务端,可以很好地对页面性能进行调优。 跨环境共享模块。CMD 模块定义规范与 Node.js 的模块规范非常相近。通过 Sea.js 的 Node.js 版本,可以很方便实现模块的跨服务器和浏览器共享。]]></content>
</entry>
<entry>
<title><![CDATA[html5-video控件设置]]></title>
<url>%2F2017%2F02%2F20%2Fhtml5-video%2F</url>
<content type="text"><![CDATA[控制Html5 Video的播放与暂停状态.12345678910//Play/Pause control clicked $('.btnPlay').on('click', function() { if(video[0].paused) { video[0].play(); } else { video[0].pause(); } return false; }; 显示视频播放时间和持续时间123456789//get HTML5 video time durationvideo.on('loadedmetadata', function() { $('.duration').text(video[0].duration);});//update HTML5 video current play timevideo.on('timeupdate', function() { $('.current').text(video[0].currentTime);}); 视频进度条12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849//get HTML5 video time durationvideo.on('loadedmetadata', function() { $('.duration').text(video[0].duration));});//update HTML5 video current play timevideo.on('timeupdate', function() { var currentPos = video[0].currentTime; //Get currenttime var maxduration = video[0].duration; //Get video duration var percentage = 100 * currentPos / maxduration; //in % $('.timeBar').css('width', percentage+'%');});var timeDrag = false; /* Drag status */$('.progressBar').mousedown(function(e) { timeDrag = true; updatebar(e.pageX);});$(document).mouseup(function(e) { if(timeDrag) { timeDrag = false; updatebar(e.pageX); }});$(document).mousemove(function(e) { if(timeDrag) { updatebar(e.pageX); }});//update Progress Bar controlvar updatebar = function(x) { var progress = $('.progressBar'); var maxduration = video[0].duration; //Video duraiton var position = x - progress.offset().left; //Click pos var percentage = 100 * position / progress.width(); //Check within range if(percentage > 100) { percentage = 100; } if(percentage < 0) { percentage = 0; }//Update progress bar and video currenttime$('.timeBar').css('width', percentage+'%');video[0].currentTime = maxduration * percentage / 100;}; 进阶-显示缓冲栏123456789101112//loop to get HTML5 video buffered datavar startBuffer = function() { var maxduration = video[0].duration; var currentBuffer = video[0].buffered.end(0); var percentage = 100 * currentBuffer / maxduration; $('.bufferBar').css('width', percentage+'%'); if(currentBuffer < maxduration) { setTimeout(startBuffer, 500); }};setTimeout(startBuffer, 500); 音量控制123456789101112//Mute/Unmute control clicked$('.muted').click(function() { video[0].muted = !video[0].muted; return false;});//Volume control clicked$('.volumeBar').on('mousedown', function(e) { var position = e.pageX - volume.offset().left; var percentage = 100 * position / volume.width(); $('.volumeBar').css('width', percentage+'%'); video[0].volume = percentage / 100;}); 快进/快退 倒带控制1234567891011121314151617//Fast forward control$('.ff').on('click', function() { video[0].playbackrate = 3; return false;});//Rewind control$('.rw').on('click', function() { video[0].playbackrate = -3; return false;});//Slow motion control$('.sl').on('click', function() { video[0].playbackrate = 0.5; return false;}); 其他除了主要的控制插件.还可以做一些额外的控制.例如全屏播放123456789$('.fullscreen').on('click', function() { //For Webkit video[0].webkitEnterFullscreen(); //For Firefox video[0].mozRequestFullScreen(); return false;}); 开灯关灯控制123456789101112131415161718192021222324$('.btnLight').click(function() { if($(this).hasClass('on')) { $(this).removeClass('on'); $('body').append('<div class="overlay"></div>'); $('.overlay').css({ 'position':'absolute', 'width':100+'%', 'height':$(document).height(), 'background':'#000', 'opacity':0.9, 'top':0, 'left':0, 'z-index':999 }); $('#myVideo').css({ 'z-index':1000 }); } else { $(this).addClass('on'); $('.overlay').remove(); } return false;});]]></content>
</entry>
<entry>
<title><![CDATA[sassNote]]></title>
<url>%2F2017%2F02%2F20%2FsassNote%2F</url>
<content type="text"><![CDATA[Sass用法指南Sass是一种基于ruby开发的”CSS预处理器”,可以让CSS的开发变得简单和可维护,语法和less很相近。搭配Compass,sass将会更强大。 Compass用法指南一、Compass是什么?简单说,Compass是Sass的工具库(toolkit)。Sass本身只是一个编译器,Compass在它的基础上,封装了一系列有用的模块和模板,补充Sass的功能。它们之间的关系,有点像Javascript和jQuery、Ruby和Rails、python和Django的关系。 二、安装Compass是用Ruby语言开发的,所以安装它之前,必须安装Ruby。传送门假定你的机器(Linux或OS X)已经安装好Ruby,那么在命令行模式下键入:1$ sudo gem install compass 如果你用的是Windows系统,那么要省略前面的sudo。正常情况下,Compass(连同Sass)就安装好了。 三、项目初始化接下来,要创建一个你的Compass项目,假定它的名字叫做myproject,那么在命令行键入:1$ compass create myproject 当前目录中就会生成一个myproject子目录。进入该目录:1$ cd myproject 你会看到,里面有一个config.rb文件,这是你的项目的配置文件。还有两个子目录sass和stylesheets,前者存放Sass源文件,后者存放编译后的css文件。 接下来,就可以动手写代码了。 四、Compass编译相关知识://scss编译命令1$ compass compile //scss监听命令,文件改变自动编译1$ compass watch //默认状态下,编译出来的css文件带有大量的注释。但是,生产环境需要压缩后的css文件,这时要使用–output-style参数1$ compass compile --output-style compressed //Compass只编译发生变动的文件,如果你要重新编译未变动的文件,需要使用—force参数1$ compass compile --force //expanded模式表示编译后保留原格式,其他值还包括:nested、:compact和:compressed。进入生产阶段后,就要改为:compressed模式1$ compass compile output_style = :expanded 常用的五个功能模块。编译之后可以自动完善对应的css样式代码12345@import "compass/reset";//加载reset模块,重置样式@import "compass/css3";//处理兼容性问题@import "compass/layout";//该模块提供布局功能 eg. footer@import "compass/typography";//该模块提供版式功能@import "compass/utilities";//该模块提供某些不属于其他模块的功能,eg.fix & tab eg.使用CSS3模块,通过@include 引入。编译之后,自动补充浏览器兼容写法。123456789101112131415161718$color:#222;//使用$定义变量.first{ @include border-radius(5px); @include opacity(.5); @include inline-block; @include clearfix;//清楚浮动 @include table-scaffolding;//表格 … color:$color;//引用变量 .second{ @include stretch;//指定子元素占满父元素的空间 } #footer { @include sticky-footer(54px);//指定页面的footer部分总是出现在浏览器最底端 }}]]></content>
</entry>
<entry>
<title><![CDATA[lessNote]]></title>
<url>%2F2017%2F02%2F20%2FlessNote%2F</url>
<content type="text"><![CDATA[1.less使用@来声明变量。1@bgc:#cccc; 2.混合。less可以直接引用选择器,继承其所有样式;less选择器可以传参,默认参数值即是默认属性值。调用时,传参就可以改值。123#selector(@width:20px){ width:@width;} 3.匹配模式。根据参数选值,调用对应匹配的样式。123456789#pos(r){ posiont:relative;}#pos(a){ posiont:absolute;}#pos(f){ posiont:fixed;} 4.数值运算。(包括颜色值,长度值)eg.1234@fontSize:14px; .selector{ font-size:@fontSize - 2;//12px} 5.嵌套。&符号表示其父级。12345ul{ li{...} a{...} &:active{...}} 6.避免编译,如下100px;不会经过编译。123 .selector{ width:~’100px’;} 7.变量插值。12// 定义变量@mySelector:banner; 123456// 用法.@{mySelector}{ font-weight: bold; line-height:40px; margin:0auto; } 8.!important,可以直接加在变量后,提升改属性的优先级。9.Scope (作用域)Less 中的作用域与编程语言中的作用域概念非常相似。首先会在局部查找变量和混合,如果没找到,编译器就会在父作用域中查找,依次类推。1234567@var: red;#page { @var: white; #header { color: @var; // white }} 10.Importing (导入)导入工作与你预期的一样。你可以导入一个 .less 文件,然后这个文件中的所有变量都可以使用了。对于 .less 文件而言,其扩展名是可选的。12@import "library"; // library.less@import "typo.css"; 11.Comments (注释)可以使用块注释和行注释:123/* One hell of a blockstyle comment! */@var: red; 12// Get in line!@var: white;]]></content>
</entry>
<entry>
<title><![CDATA[yml-lang]]></title>
<url>%2F2017%2F02%2F20%2Fyml-lang%2F</url>
<content type="text"><![CDATA[yml语言笔记(http://www.yaml.org)YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便。本文介绍 YAML 的语法,以 JS-YAML 的实现为例. 一、简介YAML 语言(发音 /ˈjæməl/ )的设计目标,就是方便人类读写。它实质上是一种通用的数据串行化格式。它的基本语法规则如下。12345大小写敏感使用缩进表示层级关系缩进时不允许使用Tab键,只允许使用空格。缩进的空格数目不重要,只要相同层级的元素左侧对齐即可# 表示注释,从这个字符一直到行尾,都会被解析器忽略。 YAML 支持的数据结构有三种。123对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)纯量(scalars):单个的、不可再分的值 以下分别介绍这三种数据结构。 二、对象对象的一组键值对,使用冒号结构表示。1animal: pets 转为 JavaScript 如下。1{ animal: 'pets' } Yaml 也允许另一种写法,将所有键值对写成一个行内对象。1hash: { name: Steve, foo: bar } 转为 JavaScript 如下。1{ hash: { name: 'Steve', foo: 'bar' } } 三、数组一组连词线开头的行,构成一个数组。123- Cat- Dog- Goldfish 转为 JavaScript 如下。1[ 'Cat', 'Dog', 'Goldfish' ] 数据结构的子成员是一个数组,则可以在该项下面缩进一个空格。1234- - Cat - Dog - Goldfish 转为 JavaScript 如下。1[ [ 'Cat', 'Dog', 'Goldfish' ] ] 数组也可以采用行内表示法。1animal: [Cat, Dog] 转为 JavaScript 如下。1{ animal: [ 'Cat', 'Dog' ] } 四、复合结构对象和数组可以结合使用,形成复合结构。123456789languages: - Ruby - Perl - Pythonwebsites: YAML: yaml.org Ruby: ruby-lang.org Python: python.org Perl: use.perl.org 转为 JavaScript 如下。123456{ languages: [ 'Ruby', 'Perl', 'Python' ], websites: { YAML: 'yaml.org', Ruby: 'ruby-lang.org', Python: 'python.org', Perl: 'use.perl.org' } } 五、纯量纯量是最基本的、不可再分的值。以下数据类型都属于 JavaScript 的纯量。1234567字符串布尔值整数浮点数Null时间日期 数值直接以字面量的形式表示。1number: 12.30 转为 JavaScript 如下。1{ number: 12.30 } 布尔值用true和false表示。1isSet: true 转为 JavaScript 如下。1{ isSet: true } null用~表示。1parent: ~ 转为 JavaScript 如下。1{ parent: null } 时间采用 ISO8601 格式。1iso8601: 2001-12-14t21:59:43.10-05:00 转为 JavaScript 如下。1{ iso8601: new Date('2001-12-14t21:59:43.10-05:00') } 日期采用复合 iso8601 格式的年、月、日表示。1date: 1976-07-31 转为 JavaScript 如下。1{ date: new Date('1976-07-31') } YAML 允许使用两个感叹号,强制转换数据类型。12e: !!str 123f: !!str true 转为 JavaScript 如下。1{ e: '123', f: 'true' } 六、字符串字符串是最常见,也是最复杂的一种数据类型。字符串默认不使用引号表示。1str: 这是一行字符串 转为 JavaScript 如下。1{ str: '这是一行字符串' } 如果字符串之中包含空格或特殊字符,需要放在引号之中。1str: '内容: 字符串' 转为 JavaScript 如下。1{ str: '内容: 字符串' } 单引号和双引号都可以使用,双引号不会对特殊字符转义。12s1: '内容\n字符串's2: "内容\n字符串" 转为 JavaScript 如下。1{ s1: '内容\\n字符串', s2: '内容\n字符串' } 单引号之中如果还有单引号,必须连续使用两个单引号转义。1str: 'labor''s day' 转为 JavaScript 如下。1{ str: 'labor\'s day' } 字符串可以写成多行,从第二行开始,必须有一个单空格缩进。换行符会被转为空格。123str: 这是一段 多行 字符串 转为 JavaScript 如下。1{ str: '这是一段 多行 字符串' } 多行字符串可以使用|保留换行符,也可以使用>折叠换行。123456this: | Foo Barthat: > Foo Bar 转为 JavaScript 代码如下。1{ this: 'Foo\nBar\n', that: 'Foo Bar\n' } +表示保留文字块末尾的换行,-表示删除字符串末尾的换行。123456789s1: | Foos2: |+ Foos3: |- Foo 转为 JavaScript 代码如下。1{ s1: 'Foo\n', s2: 'Foo\n\n\n', s3: 'Foo' } 字符串之中可以插入 HTML 标记。12345message: | <p style="color: red"> 段落 </p> 转为 JavaScript 如下。1{ message: '\n<p style="color: red">\n 段落\n</p>\n' } 七、引用锚点&和别名*,可以用来引用。1234567891011defaults: &defaults adapter: postgres host: localhostdevelopment: database: myapp_development <<: *defaultstest: database: myapp_test <<: *defaults 等同于下面的代码。12345678910111213defaults: adapter: postgres host: localhostdevelopment: database: myapp_development adapter: postgres host: localhosttest: database: myapp_test adapter: postgres host: localhost &用来建立锚点(defaults),<<表示合并到当前数据,*用来引用锚点。下面是另一个例子。12345- &showell Steve- Clark- Brian- Oren- *showell 转为 JavaScript 代码如下。1[ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve' ] 八、函数和正则表达式的转换这是 JS-YAML 库特有的功能,可以把函数和正则表达式转为字符串。123# example.ymlfn: function () { return 1 }reg: /test/ 解析上面的 yml 文件的代码如下。1234567891011var yaml = require('js-yaml');var fs = require('fs');try { var doc = yaml.load( fs.readFileSync('./example.yml', 'utf8') ); console.log(doc);} catch (e) { console.log(e);} 从 JavaScript 对象还原到 yaml 文件的代码如下。1234567891011121314151617var yaml = require('js-yaml');var fs = require('fs');var obj = { fn: function () { return 1 }, reg: /test/};try { fs.writeFileSync( './example.yml', yaml.dump(obj), 'utf8' );} catch (e) { console.log(e);}]]></content>
</entry>
<entry>
<title><![CDATA[vueJSNote]]></title>
<url>%2F2017%2F02%2F19%2FvueJSNote%2F</url>
<content type="text"><![CDATA[see my vueJS demo使用 Prop 传递数据组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。prop 是父组件用来传递数据的一个自定义属性。子组件需要显式地用 props 选项声明 “prop”:1234567Vue.component('child', { // 声明 props props: ['message'], // 就像 data 一样,prop 可以用在模板内 // 同样也可以在 vm 实例中像 “this.message” 这样使用 template: '<span>{{ message }}</span>'}) 然后向它传入一个普通字符串:1<child message="hello!"></child> 输出结果: hello! 使用 v-on 绑定自定义事件每个 Vue 实例都实现了事件接口(Events interface),即:使用 $on(eventName) 监听事件使用 $emit(eventName) 触发事件Vue的事件系统分离自浏览器的EventTarget API。尽管它们的运行类似,但是$on 和 $emit 不是addEventListener 和 dispatchEvent 的别名。 另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。下面是一个例子:12345<div id="counter-event-example"> <p>{{ total }}</p> <button-counter v-on:increment="incrementTotal"></button-counter> <button-counter v-on:increment="incrementTotal"></button-counter></div> 12345678910111213141516171819202122232425Vue.component('button-counter', { template: '<button v-on:click="increment">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { increment: function () { this.counter += 1 this.$emit('increment') } },})new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } }}) 非父子组件通信有时候非父子关系的组件也需要通信。在简单的场景下,使用一个空的 Vue 实例作为中央事件总线:1var bus = new Vue() // 触发组件 A 中的事件1bus.$emit('id-selected', 1) // 在组件 B 创建的钩子中监听事件123bus.$on('id-selected', function (id) { // ...}) 在更多复杂的情况下,你应该考虑使用专门的 状态管理模式.]]></content>
</entry>
<entry>
<title><![CDATA[浅谈对MVC,MVVM的理解]]></title>
<url>%2F2017%2F02%2F18%2Fabout_MVC_MVVM%2F</url>
<content type="text"><![CDATA[View 传送指令到 Controller Controller 完成业务逻辑后,要求 Model 改变状态 Model 将新的数据发送到 View,用户得到反馈所有通信都是单向的。 Angular它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。 组成部分Model、View、ViewModel View:UI界面 ViewModel:它是View的抽象,负责View与Model之间信息转换,将View的Command传送到Model; Model:数据访问层 名词解析MVC(模型-视图-控制器)Model(模型)主要与业务数据有关。View(视图)是关于构件和维护一个DOM元素。应用程序数据的可视化表示。Controller(控制器)用户更新视图,controller更新model]]></content>
</entry>
</search>