-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
370 lines (370 loc) · 182 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
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[react组件生命周期]]></title>
<url>%2F2017%2F06%2F21%2Freact%E7%BB%84%E4%BB%B6%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%2F</url>
<content type="text"><![CDATA[实例化首次实例化 getDefaultProps getInitialState componentWillMount render componentDidMount 实例化完成后的更新 getInitialState componentWillMount render componentDidMount 存在期组件已存在时的状态改变 componentWillReceiveProps shouldComponentUpdate componentWillUpdate render componentDidUpdate 销毁&清理期componentWillUnmount 生命周期共提供了10个不同的API1.getDefaultProps作用于组件类,只调用一次,返回对象用于设置默认的props,对于引用值,会在实例中共享。 2.getInitialState作用于组件的实例,在实例创建时调用一次,用于初始化每个实例的state,此时可以访问this.props。 3.componentWillMount在完成首次渲染之前调用,此时仍可以修改组件的state。 4.render必选的方法,创建虚拟DOM,该方法具有特殊的规则:1)只能通过this.props和this.state访问数据2)可以返回null、false或任何React组件3)只能出现一个顶级组件(不能返回数组)4)不能改变组件的状态5)不能修改DOM的输出 5.componentDidMount真实的DOM被渲染出来后调用,在该方法中可通过this.getDOMNode()访问到真实的DOM元素。此时已可以使用其他类库来操作这个DOM。 在服务端中,该方法不会被调用。 6.componentWillReceiveProps组件接收到新的props时调用,并将其作为参数nextProps使用,此时可以更改组件props及state。 1234567componentWillReceiveProps: function(nextProps) { if (nextProps.bool) { this.setState({ bool: true }); }} 7.shouldComponentUpdate组件是否应当渲染新的props或state,返回false表示跳过后续的生命周期方法,通常不需要使用以避免出现bug。在出现应用的瓶颈时,可通过该方法进行适当的优化。 在首次渲染期间或者调用了forceUpdate方法后,该方法不会被调用 8.componentWillUpdate接收到新的props或者state后,进行渲染之前调用,此时不允许更新props或state。 9.componentDidUpdate完成渲染新的props或者state后调用,此时可以访问到新的DOM元素。 10.componentWillUnmount组件被移除之前被调用,可以用于做一些清理工作,在componentDidMount方法中添加的所有任务都需要在该方法中撤销,比如创建的定时器或添加的事件监听器。]]></content>
<categories>
<category>react</category>
</categories>
<tags>
<tag>react</tag>
</tags>
</entry>
<entry>
<title><![CDATA[react子组件使用props(一)]]></title>
<url>%2F2017%2F06%2F20%2Freact%20%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BD%BF%E7%94%A8props(%E4%B8%80%EF%BC%89%2F</url>
<content type="text"><![CDATA[子组件显示父组件穿过来的props有两种方式: 1、直接使用这种方式,父组件改变props后,子组件重新渲染,由于直接使用的props,所以我们不需要做什么就可以正常显示最新的props 12345class Child extends Component { render() { return <div>{this.props.someThings}</div> }} 2、转换成自己的state这种方式,由于我们使用的是state,所以每当父组件每次重新传递props时,我们需要重新处理下,将props转换成自己的state,这里就用到了 componentWillReceiveProps。 每次子组件接收到新的props,都会重新渲染一次,除非你做了处理来阻止(比如使用:shouldComponentUpdate),但是你可以在这次渲染前,根据新的props更新state,更新state也会触发一次重新渲染,但react不会这么傻,所以只会渲染一次,这对应用的性能是有利的。 1234567891011121314class Child extends Component { constructor(props) { super(props); this.state = { someThings: props.someThings }; } componentWillReceiveProps(nextProps) { this.setState({someThings: nextProps.someThings}); } render() { return <div>{this.state.someThings}</div> }}]]></content>
<categories>
<category>react</category>
</categories>
<tags>
<tag>react</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6 新特性(一)]]></title>
<url>%2F2017%2F06%2F08%2FES6%E6%96%B0%E7%89%B9%E6%80%A7%EF%BC%88%E4%B8%80%EF%BC%89%2F</url>
<content type="text"><![CDATA[let与const新的变量声明定义方式,let 和 const 都不存在变量提升,有暂时性死区,只能在声明后使用,且不能重复声明。let 声明的变量,在声明之后还可以进行新的赋值const 声明的变量,其变量指向的那个内存地址不得改动。故如果声明的变量是简单类型的数据(数值、字符串、布尔值),则不能改变它的值;如果声明的变量是对象或者数组,由于const只要保证指向其内存地址的指针不变,故可以改变对象的属性和数组的值。 1234567891011const foo = {};// 为 foo 添加一个属性,可以成功foo.prop = 123;foo.prop // 123// 将 foo 指向另一个对象,就会报错foo = {}; // TypeError: "foo" is read-onlyconst a = [];a.push('Hello'); // 可执行a.length = 0; // 可执行a = ['Dave']; // 报错 字符串模板方便字符串的拼接,可以与引号混用,支持多行文本,支持 html 标签。 12345678var s1 = 'hi';var getName = () => { return 'fwp';};var conf = { fav: 'coding'};console.log(`${s1}, my name is ${getName()}, I like ${conf.fav}`); //hi, my name is fwp, I like coding 增强的对象字面量设计了很多简写 12345678910111213141516const _bookNum = 4;const basicConfig = { level: 5}const config = { // 直接指定原型对象 __proto__: basicConfig, // 属性简写 _bookNum, // 方法简写 getBookNum() { return this.bookNum; }} => 操作符操作符左边为输入的参数,而右边则是进行的操作以及返回的值Inputs=>outputs。我们知道在JS中回调是经常的事,而一般回调又以匿名函数的形式出现,每次都需要写一个function,甚是繁琐。当引入箭头操作符后可以方便地写回调了。 12345var arr = [1, 2, 3];arr.forEach(v => console.log(v)); //相当于下面代码arr.forEach(function(v) { console.log(v);}); 在未使用箭头函数前,我们在过程函数中使用父级 this,需要将其显式缓存到另一个中间变量中,因为过程函数有独立的 this 变量,会覆盖父级;使用箭头函数后,不但简写了一个过程函数( forEach 的参数),还省略掉了 this 的中间变量的定义。因为箭头函数没有独立执行上下文( this ),所以其内部引用 this 对象会直接访问父级。 箭头函数不但没有独立 this,他也没有独立的 arguments,所以如果需要取不定参的时候,要么使用 function,要么用 ES6 的另一个新特性 rest。 箭头函数语法很灵活,在只有一个参数或者只有一句表达式做方法体时,可以省略相应括号。 Rest + Spread主要是应用 … 运算符,完成值的聚合和分解。 12345678910111213141516// 1. rest 得到的是一个真正的数组而不是一个伪数组const getOptions = function(...args){ console.log(args.join); // function};// 2. rest 可以配合箭头函数使用,达到取得所有参数的目的const getOptions = (...args) => { console.log(args); // array};// 3. spread 可以用于解构时,聚合所得的值const [opt1, ...opts] = ['one', 'two', 'three', 'four'];// 4. spread 可以用于数组定义const opts = ['one', 'two', 'three', 'four'];const config = ['other', ...opts]; 类(class)ES6 中实现的一个语法糖,用于简化基于原型集成实现类定义的场景。 1234567891011121314151617181920212223242526272829//ES5 中生成实例对象的传统方法是通过构造函数function Point(x, y) { this.x = x; this.y = y;}Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')';};var p = new Point(1, 2);//ES6 通过类class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; }}//ES6 的类,完全可以看作构造函数的另一种写法//类的数据类型就是函数,类本身就指向构造函数class Point { // ...}typeof Point // "function"Point === Point.prototype.constructor // true 构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。 类的一些特点一、类的内部所有定义的方法,都是不可枚举的 123456789101112class Point { constructor(x, y) { // ... } toString() { // ... }}Object.keys(Point.prototype); // []Object.getOwnPropertyNames(Point.prototype); // ["constructor","toString"] 二、类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 实际上把整个语言升级到了严格模式。 三、constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象。 1234567class Foo { constructor() { return Object.create(null); }}new Foo() instanceof Foo; // false 上面代码中,constructor函数返回一个全新的对象,结果导致实例对象不是Foo类的实例。 四、类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。 五、与 ES5 一样,实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。 六、与 ES5 一样,类的所有实例共享一个原型对象。 七、ES6 不支持私有属性和私有方法,可以用 Symbol 来定义它们,或者采用#(目前,有一个提案,为class加了私有属性。在属性名之前,使用#表示)。 八、与 ES5 一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为 123456789101112131415class MyClass { constructor() { // ... } get prop() { return 'getter'; } set prop(value) { console.log('setter: '+value); }}let inst = new MyClass();inst.prop = 123; // setter: 123inst.prop; // 'getter' 九、类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。父类的静态方法,可以被子类继承;静态方法也是可以从super对象上调用的。 1234567891011class Foo { static classMethod() { return 'hello'; }}Foo.classMethod() // 'hello'var foo = new Foo();foo.classMethod(); // TypeError: foo.classMethod is not a function 十、静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性。目前,只能通过如下方法定义一个类的静态属性,而不能在Class内部定义。(目前只有个提案,可以允许在类的内部定义静态属性) 12345678910class Foo {}Foo.prop = 1;Foo.prop; // 1class Foo { prop: 2 //无效写法1 static prop: 2 //无效写法2}Foo.prop; //undefined 十一、new 是从构造函数生成实例的命令。ES6 为 new 命令引入了一个 new.target 属性,该属性一般用在在构造函数之中,返回 new 命令作用于的那个构造函数。如果构造函数不是通过 new 命令调用的,new.target 会返回 undefined。Class 内部调用 new.target,返回当前 Class;子类继承父类时,new.target 会返回子类。利用这个属性,可以确保构造函数只能通过 new 命令调用 12345678910111213141516171819function Person(name) { if (new.target !== undefined) { this.name = name; } else { throw new Error('必须使用new生成实例'); }}// 另一种写法function Person(name) { if (new.target === Person) { this.name = name; } else { throw new Error('必须使用 new 生成实例'); }}var person = new Person('张三'); // 正确var notAPerson = Person.call(person, '张三'); // 报错 利用 new.target 还可以写出不能独立使用、必须继承后才能使用的类 1234567891011121314151617class Shape { constructor() { if (new.target === Shape) { throw new Error('本类不能实例化'); } }}class Rectangle extends Shape { constructor(length, width) { super(); // ... }}var x = new Shape(); // 报错var y = new Rectangle(3, 4); // 正确 PromiseES6 提供的用于异步操作的解决方案 12345678910111213141516171819202122//创建一个Promise实例var promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); }});//Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数promise.then(function(value) { // success}, function(error) { // failure});//Promise可以用 catch 来捕捉错误promise.then(function(data) { //cb // success}).catch(function(err) { // error}); Promise.all()Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。 1var p = Promise.all([p1, p2, p3]); Promise.all方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。(Promise.all方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。) p的状态由p1、p2、p3决定,分成两种情况。(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给 p 的回调函数。(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给 p 的回调函数。 参考: FED-ES6你可能不知道的事基础篇 阮一峰ES6教程]]></content>
<categories>
<category>javascript</category>
</categories>
<tags>
<tag>js</tag>
<tag>es6</tag>
</tags>
</entry>
<entry>
<title><![CDATA[js 模块化小结]]></title>
<url>%2F2017%2F06%2F05%2Fjs%E6%A8%A1%E5%9D%97%E5%8C%96%E5%B0%8F%E7%BB%93%2F</url>
<content type="text"><![CDATA[一、模块与组件的区别1. 模块模块通常指的是实现某个特定功能的js模块,如一个实现时间格式化的js文件。把多个功能实现放在一个js文件中,随着需要实现的功能越来越多,js文件也越来越复杂,不利于开发与维护,所以要把js文件进行功能拆分,形成多个实现特定功能的js文件,这就是模块。 2. 组件组件比模块更大的概念,一个组件通常包括html模板、css样式和js三部分。通常我们可以将一个页面拆分成多个组件,一个组件可以引入多个js模块,组件可以为多个页面所复用。 二、使用模块化开发的好处 解决命名冲突问题(也可以通过命名空间来缓解,但是代码会变繁琐) 避免过多的文件依赖(文件依赖:使用某个js文件前必须引入其他文件) 模块版本管理,通过配置结合构建工具,可以轻松实现模块的版本管理。 提高代码的可维护性 前端性能优化(可实现异步加载模块) 跨环境共享模块(可实现模块的跨服务器和浏览器共享) 模块化开发的演进过程 普通的函数封装 封装成对象 私有公有成员分离 (使用自执行函数,避免变量污染) 模块的维护和扩展(用多个自执行函数把模块分离开来,使用开闭原则—去增添功能,而尽量不要修改原来的代码,) 可以添加模块的第三方依赖(比如添加jQuery的$,$作为一个编程的接口,降低程序之间的耦合度) 具体做法可以参考:阮一峰 - 模块的写法 三、几个主要的模块化规范1. CommonJSCommonJS 主要是用于服务器端的模块化规范。node.js的模块化就是基于这个规范实现的。通过 require() 方法加载模块,通过exports对象导出当前模块的方法或变量。 123456// 加载模块并应用var math = require('math');math.add(2, 3);// 导出模块exports.XXX = function(){}module.exports = function(){} 只要模拟出require、exports、module,在浏览器端也能应用模块化(例子:browerify工具,browerify 将所有模块放入一个数组,id 属性是模块的编号,source 属性是模块的源码,deps 属性是模块的依赖。)但是,由于一个重大的局限,使得CommonJS规范不适用于浏览器环境:例如上述例子,math.add方法要在math模块加载完成后才能使用,也就是说,如果加载时间很长,整个应用就会停在那里等待。 这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于”假死”状态。 因此,浏览器端的模块,不能采用”同步加载”(synchronous),只能采用”异步加载”(asynchronous)。这就是AMD规范诞生的背景。 2. AMDAMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。AMD加载模块方法: require([module], callback); 第一个参数 [module] 是一个数组,表示需要加载的模块第二个参数callback,则是加载成功之后的回调函数上述 math 的例子改成 AMD 的形式如下: 12345678910111213141516171819202122232425262728 require(['math'], function (math) { math.add(2, 3); }); ``` AMD 规范规定用define函数来定义模块,假定现在有一个math.js文件,它定义了一个math模块。那么,math.js就要这样写: ```javascript define(id, [modules], callback) // 其中 id 是为此模块定义的名称 // 假设这个模块没有依赖其他模块 define(function (){ var add = function (x,y){ return x+y; }; return { // 将新定义的模块暴露出去 add: add }; }); // 假设这个模块依赖了其他模块 define(['myLib'], function(myLib){ function foo(){ myLib.doSomething(); } return { foo : foo }; }); AMD 规范规定依赖模块要首先给出(即如上代码),但是也可以使用require 按需加载,如下: 12345define( function( require ){ var m1 = require( 'module1' ), m2 = require( 'module2' ); ...}); 目前,主要有两个 Javascript 库实现了 AMD 规范:require.js 和 curl.js require.js 主要为了解决两个问题: 实现js文件的异步加载,避免网页失去响应 管理模块之间的依赖性,便于代码的编写和维护 具体用法可以参考:阮一峰 - require.js 的用法、AMD api中文版、AMD api英文版、require.js api 3. CMD通用模块定义 (Common Module Definition) 是 sea.js 在推广过程中对模块定义的规范化产出。在CMD中,一个模块就是一个文件。define( factory ); 全局函数define,用来定义模块。参数 factory 可以是一个函数,也可以为对象或者字符串。当 factory 为对象、字符串时,表示模块的接口就是该对象、字符串。define 函数的完整参数如下: define( id?, deps?, factory ); 字符串 id 为模块标识,数组 deps 为模块依赖, factory函数里可以有3个参数:require, exports, module require 用来引入模块依赖,默认是顺序执行的,可以使用require.async(id, callback?) 来实现模块的异步加载 exports 用来向外提供模块接口,一些属性和方法,用法和 node.js 上一样 module 是factory的第三个参数,它是一个对象,上面存储了一些与当前模块相关联的属性与方法: 1)module.id为模块的唯一标识。 2)module.uri 根据模块系统的路径解析规则得到模块的绝对路径。 3)module.dependencies表示模块的依赖。 4)module.exports 当前模块对外提供的接口 sea.js 安全遵循了 CMD 规范,同 node.js 写法类似,使用 define 定义模块,require 引入模块,use 使用模块 1234567891011// 加载一个模块 seajs.use('./a');// 加载模块,加载完成时执行回调seajs.use('./a',function(a){ a.doSomething();});// 加载多个模块执行回调seajs.use(['./a','./b'],function(a , b){ a.doSomething(); b.doSomething();}); AMD 和 CMD 的区别 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible. CMD推崇依赖就近,AMD 推崇依赖前置。虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。 AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。 另外具体的 sea.js 和 require.js 的区别可以参考:sea.js 与 require.js 的差异 ES6 中的模块import 导入,export 导出 ES6 模块的特点:一、与 CommonJS 加载方式不同:1)CommonJS 和 AMD 只能在“运行时加载”模块的方法,它们会首先整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取需要的方法,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”;2)ES6 是直接从模块加载对应的方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。二、export:1)CommonJS 模块输出的是值的缓存,不存在动态更新;2)export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。三、import:import 语句是在编译时就加载好的,所以在调用模块内部无法对import 进来的变量、属性等都无法修改。四、其他还有模块继承、模块间常量共享等等。具体可以参考:阮一峰 - ES6 Module]]></content>
<categories>
<category>javascript</category>
</categories>
<tags>
<tag>js</tag>
</tags>
</entry>
<entry>
<title><![CDATA[http协议]]></title>
<url>%2F2017%2F05%2F25%2F%E7%BD%91%E7%BB%9C-HTTP%E5%8D%8F%E8%AE%AE%2F</url>
<content type="text"><![CDATA[HTTP协议简介HyperText Transfer Protocol 超文本传输协议HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。 HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息 URL地址分析URL,全称是UniformResourceLocator, 中文叫统一资源定位符,是互联网上用来标识某一处资源的地址。以下面这个URL为例,介绍下普通URL的各部分组成: http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name 从上面的URL可以看出,一个完整的URL包括以下几部分:1.协议部分:该URL的协议部分为“http:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在”HTTP”后面的“//”为分隔符2.域名部分:该URL的域名部分为“www.aspxfans.com”。一个URL中,也可以使用IP地址作为域名使用3.端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口4.虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是“/news/”5.文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名6.锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分7.参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。 HTTP状态码状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别: 1xx:指示信息–表示请求已接收,继续处理2xx:成功–表示请求已被成功接收、理解、接受3xx:重定向–要完成请求必须进行更进一步的操作4xx:客户端错误–请求有语法错误或请求无法实现5xx:服务器端错误–服务器未能实现合法的请求 常见状态码: 200 OK //客户端请求成功400 Bad Request //客户端请求有语法错误,不能被服务器所理解401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用403 Forbidden //服务器收到请求,但是拒绝提供服务404 Not Found //请求资源不存在,eg:输入了错误的URL500 Internal Server Error //服务器发生不可预期的错误503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常 HTTP请求方式HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。 GET 请求指定的页面信息,并返回实体主体。 HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 PUT 从客户端向服务器传送的数据取代指定的文档的内容。 DELETE 请求服务器删除指定的页面。 CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 OPTIONS 允许客户端查看服务器的性能。 TRACE 回显服务器收到的请求,主要用于测试或诊断。get和post的区别HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。GET是向服务器发索取数据的一种请求,而POST是向服务器提交数据的一种请求;GET是获取信息,而不是修改信息,类似数据库查询功能一样,数据不会被修改GET 请求的一些特点: Get请求的参数会跟在url后进行传递,请求的数据会附在URL之后,以?分割URL和传输数据,参数之间以&相连,%XX中的XX为该符号以16进制表示的ASCII,如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密。Get传输的数据有大小限制,HTTP本身对Get数据大小没有限制,但是因为GET是通过URL提交数据,那么GET可提交的数据量就跟URL的长度有直接关系了,不同的浏览器对URL的长度的限制是不同的。GET请求的数据会被浏览器缓存起来,用户名和密码将明文出现在URL上,其他人可以查到历史浏览记录,数据不太安全。在服务器端,用Request.QueryString来获取Get方式提交来的数据 POST请求的特点: Post请求则作为http消息的实际内容发送给web服务器,数据放置在HTML Header内提交,Post没有限制提交的数据。Post比Get安全,当数据是中文或者不敏感的数据,则用get,因为使用get,参数会显示在地址,对于敏感数据和不是中文字符的数据,则用post;POST可能修改服务器上的资源的请求,在服务器端,用Post方式提交的数据只能用Request.Form来获取 123456789101112131415161718**GET请求**GET /books/?sex=man&name=Professional HTTP/1.1Host: www.wrox.comUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)Gecko/20050225 Firefox/1.0.1Connection: Keep-Alive注意最后一行是空行**POST请求**POST / HTTP/1.1Host: www.wrox.comUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)Gecko/20050225 Firefox/1.0.1Content-Type: application/x-www-form-urlencodedContent-Length: 40Connection: Keep-Alivename=Professional%20Ajax&publisher=Wiley 参考:http://www.cnblogs.com/ranyonsue/p/5984001.html]]></content>
<categories>
<category>网络</category>
</categories>
<tags>
<tag>http</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css animation]]></title>
<url>%2F2017%2F05%2F24%2Fcss%20animation%2F</url>
<content type="text"><![CDATA[如果要使用animation动画,需要使用@keyframes规则。@keyframes 规则用于创建动画。在 @keyframes 中规定某项 CSS 样式,就能创建由当前样式逐渐改为新样式的动画效果。 12345678// @keyframes duration | timing-function | delay | iteration-count | direction | fill-mode | play-state | name animation: 3s ease-in 1s 2 reverse both paused slidein;// @keyframes duration | timing-function | delay | nameanimation: 3s linear 1s slidein;// @keyframes duration | name animation: 3s slidein; ###animation属性 animation-name 自定义的@keyframes 动画的名称 animation-duration 动画完成一个周期所花费的时间,默认是0 animation-timing-function 动画的速率函数,默认是‘ease’ animation-delay 动画延迟时间,默认是0 animation-iteration-count 动画循环次数,默认是1 animation-direction 动画是否在下一个周期逆向播放,默认是normal animation-fill-mode 动画播放结束后的状态 and animation-play-state 动画是否正在运行或暂停,默认是‘running’ ###各个属性详解 ####animation-timing-function:定义动画的速度曲线 ease:动画以低速开始,然后加快,在结束前变慢。 linear:匀速 ease-in:动画以低速开始。 ease-out:动画以低速结束。 ease-in-out:动画以低速开始和结束,相对于ease缓慢,速度更均匀。 step-start:按keyframes设置逐帧显示,第一帧为keyframes设置的第一帧。 step-end:按keyframes设置逐帧显示,第一帧为样式的初始值。 steps([, [ start | end ]]?):把keyframes里设置的一帧等分为几帧,start为第一次显示第一帧,end第一次显示样式的初始值,例如:steps(4,start) cubic-bezier(, , , ):在 cubic-bezier函数中自己的值。可能的值是从 0 到 1 的数值。贝兹曲线限制了首尾两控制点的位置,通过调整中间两控制点的位置可以灵活得到常用的动画效果 ####animation-iteration-count动画迭代次数,默认就1次,可以设置2次,3次,4次,…infinite表示无限 ####animation-duration指一个动画周期持续时间。单位秒s或毫秒ms. ####animation-delay指动画延时执行时间。单位秒s或毫秒ms. ####animation-direction指动画时间轴上帧的前进方向。 normal:默认值,表示一直向前,最后一帧结束后回到第一帧 reverse:与normal的运行方向相反 alternate:往前播放完了之后,然后再倒带,倒带到头了再往后播放 alternate-reverse:与alternate的运行方向相反 ####animation-fill-mode设置动画结束后的状态 none:默认值。不设置对象动画之外的状态,DOM未进行动画前状态 forwards:设置对象状态为动画结束时的状态,100%或to时,当设置animation-direcdtion为reverse时动画结束后显示为keyframes第一帧 backwards:设置对象状态为动画开始时的状态(测试显示DOM未进行动画前状态) both:设置对象状态为动画结束或开始的状态,结束时状态优先 ####animation-play-state paused:设置该属性使动画暂停 running:设置该属性使动画继续播放 动画运行状态,暂停或继续播放,属性为:running(默认)以及paused. 一般用在使用animation实现视频播放效果的时候 ###@keyframes控制动画animation实现动画效果需要两步:1)用keyframes声明动画 2)用animation调用动画keyframes的写法:@keyframes开头,后面紧跟着动画名称animation-name。接着定义各个帧下需要动画显示的属性的值,如: 1234567891011121314151617181920212223242526272829303132@keyframes test { 0% { background: #c00 } 50% { background: orange } 100% { background: yellow }}//其中,0%可用from代替,100%可用to代替@keyframes test { from { background: #c00 } 50% { background: orange } to { background: yellow }}//如果省略某个状态,浏览器会自动推算中间状态,所以以下写法都是合法的@keyframes test { 50% { background: orange } 100% { background: yellow }}@keyframes test { 100% { background: yellow }}//还可以把多个状态写在一行@keyframes test1 { from, to { transform: none } 50% { transform: scale(1.2) }}//浏览器从一个状态过渡到另一个状态都是平滑过渡,step函数可以实现分步过渡div: hover { animation: 1s rainbow infinite steps(10)} ###过渡函数steps的解释用来实现状态间的分步过渡 steps(n, [start | end]) n是个自然数,steps函数把动画分成n等份 step-start 等同于 steps(1,start) ,动画分成 1 步,动画执行时以左侧端点为开始 step-end 等同于 steps(1,end) ,动画分成 1 步,动画执行时以结尾端点为开始 示例: 12345678@keyframes ani{ 0%{...} 50%{...} 100%{...}}.xxx:hover{ animation:ani 2s steps(10) ;} 上面的代码指的是0%-50%之间有10个steps,50%-100%之间也有10个steps;而不是整个0%-100%只有10个steps 参考:MDN - css animation 属性w3school - css3 animation 属性]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
<tag>css3</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css3 transition]]></title>
<url>%2F2017%2F05%2F22%2Fcss%20transition%2F</url>
<content type="text"><![CDATA[transition允许我们当元素从一种样式变换为另一种样式时,为元素添加过渡动画。transition这个属性其实是 transition-property(变换的属性), transition-duration(变换延续时间), transition-timing-function(速率变化函数), 和 transition-delay(变换延迟时间)的缩写属性。下面是一些示例: 123456789101112131415/* 应用于1个属性上 *//* property name | duration */transition: margin-left 4s;/* property name | duration | delay */transition: margin-left 4s 1s;/* property name | duration | timing function | delay */transition: margin-left 4s ease-in-out 1s;/* 应用于2个属性上 */transition: margin-left 4s, color 1s;/* 应用于所有改变了的属性上 */transition: all 0.5s ease-out; transition-property(过渡属性) 可以单独指定元素哪些属性改变时执行过渡(transition),可以触发浏览器reflow或repaint的属性那些CSS属性可以应用动画,可参见:mdn给出的可用属性这里列出所有的CSS属性,如果可以做动画,那么会说明是如何设置。 可以指定为all,元素任何可过渡(transition)属性值变化时都将执行过渡(transition)效果。 可以指定为none时,动画立即停止。 初始默认值为all transition-duration(过渡持续时间)用来指定元素过度过程的持续时间,时间值,1s(秒),4000ms(毫秒)。其默认值是0s,也可以理解为无过渡(transition)效果。 transition-timing-function(过渡时间函数)指定CSS属性的变换速率,预设的有:ease, linear, ease-in, ease-out, ease-in-out, cubic-bezier(x1, y1, x2, y2),默认值时ease。 ease:(逐渐变慢)默认值,等同于贝塞尔曲线(0.25, 0.1, 0.25, 1.0). linear:(匀速/线性),等同于贝塞尔曲线(0.0, 0.0, 1.0, 1.0). ease-in:(加速),等同于贝塞尔曲线(0.42, 0, 1.0, 1.0). ease-out:(减速),等同于贝塞尔曲线(0, 0, 0.58, 1.0) ease-in-out:(加速然后减速),等同于贝塞尔曲线(0.42, 0, 0.58, 1.0) cubic-bezier:通过贝塞尔曲线来计算“转换”过程中的属性值 transition-delay(过渡延迟函数)指定一个动画开始执行的时间,即当改变元素属性值后多长时间开始执行“转换效果”,初始默认值为0 其他情况:当属性值列表长度不一致时以 transition-property 的值列表长度为标准,如果某个属性值列表长度短于它的,则重复值以长度一致, 例如: 1234567891011121314151617181920212223 div { transition-property: opacity, left, top, height; transition-duration: 3s, 5s; } 等同于 div { transition-property: opacity, left, top, height; transition-duration: 3s, 5s, 3s, 5s; } ``` 如果某个属性的值列表长于 transition-property 的,将被截短,例如: ```css div { transition-property: opacity, left; transition-duration: 3s, 5s, 2s, 1s; } 等同于 div { transition-property: opacity, left; transition-duration: 3s, 5s; } 执行效果触发1. 通过css伪类CSS中伪类执行动画包括: 2. 通过js修改样式或追加删除样式一般是鼠标事件操作和定时操作(window.setTimeout(),window.setInterval() 还应注意当一个元素使用过渡(transition)后,立即使用.appendChild()将其加入到DOM中或删除其display: none;。这被视为如果初始状态从来没有存在过那么元素总是在它的最终状态。克服这个限制最简单的办法是使用极少毫米数的window.setTimeout() transitionend事件transitionend 事件会在 CSS transition 过渡完成时触发. 当transition完成前被移除或者取消,比如移除css的transition-property 属性,此事件将不会被触发。各个浏览器下事件的支持情况如下: Chrome:1.0 开始 webkitTransitionEndFirefox (Gecko):4.0 (2.0) 开始 transitionendInternet Explorer:10开始 transitionendOpera:10.5 开始 oTransitionEnd; 12 开始 otransitionend; 12.10 开始 transitionendSafari (WebKit):3.2 开始 webkitTransitionEnd transitionend 事件会在每个过渡属性完成时都触发该事件而且浏览器下还有不一致的地方,比如border过渡的时候,webkit下只触发一次,输出: 过渡属性: border; 时间:2 而firefox输出: 过渡属性: border-left-color; 时间:2过渡属性: border-bottom-color; 时间:2过渡属性: border-right-color; 时间:2过渡属性: border-top-color; 时间:2过渡属性: border-left-width; 时间:2过渡属性: border-bottom-width; 时间:2过渡属性: border-right-width; 时间:2过渡属性: border-top-width; 时间:2 建议在使用的时候判断是否所有的属性是否已经过渡完成,或者判断特定的属性名,再来执行该事件。 transition和animation的区别 transition完成后会保留过渡后的状态,而animation会跳至默认状态 后者更精细,具体到每一祯都可以控制,而前者是平滑过渡。]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
<tag>css3</tag>
</tags>
</entry>
<entry>
<title><![CDATA[有关session、cookie和jwt验证]]></title>
<url>%2F2017%2F05%2F21%2F%E6%9C%89%E5%85%B3session%E3%80%81cookie%E3%80%81jwt%2F</url>
<content type="text"><![CDATA[session指的是一个终端用户与交互系统进行通信的时间间隔(会话)例如:用户访问某个网站,从他登录到退出的时间段就是session由于http是是一种无状态的协议,故有这样一个情况:用户首次登录某个网站后,当用户再次向服务器端发送请求时还要进行登录验证,为了避免用户重复登录的麻烦,就要用到基于session或基于token的验证了。其原理就是让浏览器记住用户登录的信息,在下次请求时由浏览器代替用户进行登录验证。 一 基于session的验证1. 简要过程 生成全局唯一标识符(sessionid); 开辟数据存储空间。一般会在内存中创建相应的数据结构,但这种情况下,系统一旦掉电,所有的会话数据就会丢失,如果是电子商务网站,这种事故会造成严重的后果。不过也可以写到文件里甚至存储在数据库中,这样虽然会增加I/O开销,但session可以实现某种程度的持久化,而且更有利于session的共享; 将session的全局唯一标示符发送给客户端。问题的关键就在服务端如何发送这个session的唯一标识上。联系到HTTP协议,数据无非可以放到请求行、头域或Body里,基于此,一般来说会有两种常用的方式:cookie和URL重写。 Cookie 服务端只要设置Set-cookie头就可以将session的标识符传送到客户端,而客户端此后的每一次请求都会带上这个标识符,服务器端可以为cookie设置失效时间,一般会设置失效时间为0,即浏览器进程有效时间。至于浏览器怎么处理这个0,每个浏览器都有自己的方案,但差别都不会太大(一般体现在新建浏览器窗口的时候)。 URL重写所谓URL重写就是重写URL。在返回用户请求的页面之前,将页面内所有的URL后面全部以get参数的方式加上session标识符(或者加在path info部分等等),这样用户在收到响应之后,无论点击哪个链接或提交表单,都会在再带上session的标识符,从而就实现了会话的保持。这样做可以在客户端禁止使用cookie的时候也进行session认证。 2. 在express中使用sessionexpress-session 是基于express框专门用于处理session的中间件。由于session的认证机制离不开cookie,需要同时使用cookieParser 中间件。express-session的常用参数:secret:一个String类型的字符串,作为服务器端生成session的签名name:返回客户端的key的名称,默认为connect.sid,也可以自己设置resave:(是否允许)当客户端并行发送多个请求时,其中一个请求在另一个请求结束时对session进行修改覆盖并保存。默认为true。但是(后续版本)有可能默认失效,所以最好手动添加。saveUninitialized:初始化session时是否保存到存储。默认为true,但是(后续版本)有可能默认失效,所以最好手动添加。cookie:设置返回到前端key的属性,默认值为{ path: ‘/’, httpOnly: true, secure: false, maxAge: null }。express-session的一些方法:Session.destroy():删除session,当检测到客户端关闭时调用。Session.reload():当session有修改时,刷新session。Session.regenerate():将已有session初始化。Session.save():保存session。 3. 基于session验证存在的问题1)存储: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存或文件、数据库中,而随着认证用户的增多,服务端的开销会明显增大。2)扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在特定的这台服务器上,才能拿到授权的资源,这样在分布式的应用上,限制了负载均衡器的能力。这也限制了应用的扩展能力。3)CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。 二 基于token的验证(jwt)基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。基本过程1)用户使用用户名密码来请求服务器2)服务器进行验证用户的信息3)服务器通过验证发送给用户一个token4)客户端存储token(可采用cookie或sessionStorage、localStorage),并在每次请求时附送上这个token值5)服务端验证token值,并返回数据这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略。 1. JWT的构成JWT是由三段信息构成的,将这三段信息用.链接一起就构成了Jwt字符串。第一部分称为头部(header), 第二部分称为载荷(payload), 第三部分是签证(signature). 123456789101112131415161718192021// 1. Headers// 包括类别(typ)、加密算法(alg);{ "alg": "HS256", "typ": "JWT"}// 2. Claims// 包括需要传递的用户信息;{ "sub": "1234567890", "name": "John Doe", "admin": true}// 3. Signature// 根据alg算法与私有秘钥进行加密得到的签名字串;// 这一段是最重要的敏感信息,只能在服务端解密;HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), SECREATE_KEY) (1)头部headerjwt的头部承载两部分信息:声明类型,这里是jwt;声明加密的算法 通常直接使用 HMAC SHA256。完整的头部就像下面这样的JSON: 1234{ 'typ': 'JWT', 'alg': 'HS256'} 将头部进行base64编码(该加密是可以对称解码的),构成了第一部分 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 (2)载荷payload载荷就是存放有效信息的地方,这些有效信息包含三个部分:标准中注册的声明、公共的声明、私有的声明。1)标准中注册的声明 (建议但不强制使用) :iss: jwt签发者sub: jwt所面向的用户aud: 接收jwt的一方exp: jwt的过期时间,这个过期时间必须要大于签发时间nbf: 定义在什么时间之前,该jwt都是不可用的.iat: jwt的签发时间jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。2)公共的声明 :公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。不建议添加敏感信息,因为该部分在客户端可解密。3)私有的声明 :私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解码的,意味着该部分信息可以归类为明文信息。定义一个payload: 12345{ "sub": "1234567890", "name": "John Doe", "admin": true} 然后将其进行base64加密,得到Jwt的第二部分。 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 签证signaturejwt的第三部分是一个签证信息,这个签证信息由三部分组成:header (base64后的)、payload (base64后的)、secret。这个部分需要base64编码后的header和base64编码后的payload使用.连接组成的字符串,然后通过header中声明的编码方式进行加盐secret组合加密,然后就构成了jwt的第三部分。 12var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ 将header、payload和signature三部分用.连接起来就形成了整个jwt字符串。secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。 2. 使用jwt客户端发送请求,可以将token设为请求地址参数或请求body参数或在请求头部分设置Authorization字段(推荐)传给服务器: 12345fetch('api/user/1', { headers: { 'Authorization': 'Bearer ' + token }}) 服务器端收到请求后,根据请求头部token的header部分的加密算法和plaload加上自己的secret生成第三部分内容。然后再与客户端发送过来的第三部分内容对比。express使用jwt服务器端在验证用户登录成功后,设置token,并返回给客户端: 12345678910111213141516var express = require('express');var jwt = require('jwt-simple');var app = express();app.set('jwtTokenSecret', 'YOUR_SECRET_STRING');var expires = moment().add('days', 7).valueOf();var token = jwt.encode({ iss: user.id, exp: expires}, app.get('jwtTokenSecret'));res.json({ token : token, expires: expires, user: user.toJSON()}); jwt.encode()函数有2个参数。第一个就是一个需要编码的token对象,第二个是一个编码的密钥。Moment.js被用来设置token将在7天之后失效。最后通过res.json()方法返回这个JSON对象给客户端。客户端接受到token后存储,待下次请求时将token传给服务器端验证。 3. jwt的优点和安全相关问题优点:1)因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。2)因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。3)便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。4)它不需要在服务端保存会话信息, 所以它易于应用的扩展。安全相关注意事项:1)不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。2)保护好secret私钥,该私钥非常重要。3)如果可以,请使用https协议。4)使用jwe,及rsa加密。可能发生的安全问题:XSS: XSS是Web中最常见的一种漏洞,其主要原因是对用户输入信息不加过滤,导致用户(被误导)恶意输入的Js代码在访问该网页时被执行,而Js可以读取当前网站域名下保存的Cookie信息。针对这种攻击,无论将jwt存储在Cookie还是localStorage中,信息都有可能被窃取,为了防止XSS攻击,需要对用户输入的所有信息进行过滤。XSRF:主要利用Cookie是按照域名存储,同时访问某域名时浏览器会自动携带该域名所保存的Cookie信息这一特征。如果执意要将JWT存储在Cookie中,服务端则需要额外验证请求来源,或者在提交表单中加入随机签名并在处理表单时进行验证。 参考链接: 什么是jwtnodejs中使用jwt]]></content>
<categories>
<category>web</category>
</categories>
<tags>
<tag>session</tag>
<tag>cookie</tag>
<tag>jwt</tag>
</tags>
</entry>
<entry>
<title><![CDATA[网络体系结构及TCP/TP协议]]></title>
<url>%2F2017%2F05%2F21%2F%E7%BD%91%E7%BB%9C-%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%E5%8F%8ATCP-IP%2F</url>
<content type="text"><![CDATA[OSI模型及TCP/IP模型及各层协议1.OSI 6层体系结构物理层-》数据链路层-》网络层-》传输层-》会话层-》表示层-》应用层每一层协议如下: 物理层:RJ45、CLOCK、IEEE802.3 (中继器,集线器)数据链路:PPP、FR、HDLC、VLAN、MAC (网桥,交换机)网络层:IP、ICMP、ARP、RARP、OSPF、IPX、RIP、IGRP、 (路由器)传输层:TCP、UDP、SPX会话层:NFS、SQL、NETBIOS、RPC表示层:JPEG、MPEG、ASII应用层:FTP、DNS、Telnet、SMTP、HTTP、WWW、NFS 每一层的作用如下: 物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)数据链路层:将比特组装成帧和点到点的传递(帧Frame)网络层:负责数据包从源到宿的传递和网际互连(包PackeT)传输层:提供端到端的可靠报文传递和错误恢复(段Segment)会话层:建立、管理和终止会话(会话协议数据单元SPDU)表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)应用层:允许访问OSI环境的手段(应用协议数据单元APDU) 2.TCP/IP 4层体系结构网络接口层-》网际层-》传输层-》应用层 3. 5层体系结构物理层-》数据链路层-》网络层-》传输层-》应用层 TCP/IP协议簇1.TCP协议:Transmission Control Protocol 传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议TCP三次握手和四次挥手三次握手: 第一次握手:客户端发送syn包(syn=1, seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=1,seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送SYN(syn=0, seq=x+1)及确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。 四次挥手: 与建立连接的“三次握手”类似,断开一个TCP连接则需要“四次握手”。第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接受数据。第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。 2.IP协议IP协议是用于将多个包交换网络连接起来的,它在源地址和目的地址之间传送一种称之为数据包的东西,它还提供对数据大小的重新组装功能,以适应不同网络对包大小的要求IP实现两个基本功能:寻址和分段。IP可以根据数据包包头中包括的目的地址将数据包传送到目的地址,在此过程中IP负责选择传送的道路,这种选择道路称为路由功能。如果有些网络内只能传送小数据包,IP可以将数据包重新组装并在报头域内注明。 3.UDP协议User Datagram Protocol 用户数据报协议在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。 4.TCP与UDP的区别TCP提供面向连接的、可靠的数据流传输,而UDP提供的是非面向连接的、不可靠的数据流传输。TCP传输单位称为TCP报文段,UDP传输单位称为用户数据报。TCP注重数据安全性,UDP数据传输快,因为不需要连接等待,少了许多操作,但是其安全性却一般。TCP和UDP分别对应的协议TCP对应的协议: FTP:定义了文件传输协议,使用21端口。 Telnet:一种用于远程登陆的端口,使用23端口,用户可以以自己的身份远程连接到计算机上,可提供基于DOS模式下的通信服务。 SMTP:邮件传送协议,用于发送邮件。服务器开放的是25号端口。 POP3:它是和SMTP对应,POP3用于接收邮件。POP3协议所用的是110端口。 HTTP:是从Web服务器传输超文本到本地浏览器的传送协议。UDP对应的协议: DNS:用于域名解析服务,将域名地址转换为IP地址。DNS用的是53号端口。 SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。 TFTP:(Trival File Tran敏感词er Protocal),简单文件传输协议,该协议在熟知端口69上使用UDP服务。5. TCP建立连接为什么会采用三次握手,若采用二次握手可以吗? “已失效的连接请求报文段”的产生在这样一种情况下: client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。 本来这是一个早已失效的报文段,但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。 于是就向client发出确认报文段,同意建立连接。 假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。 由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据,但server却以为新的运输连接已经建立,并一直等待client发来数据。 这样,server的很多资源就白白浪费掉了。 采用“三次握手”的办法可以防止上述现象发生。 例如刚才那种情况,client不会向server的确认发出确认,server由于收不到确认,就知道client并没有要求建立连接。” 参考: http://blog.csdn.net/whuslei/article/details/6667471 以及牛客网]]></content>
<categories>
<category>网络</category>
</categories>
<tags>
<tag>tcp/ip</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css3 transform]]></title>
<url>%2F2017%2F05%2F21%2Fcss3%20transform%2F</url>
<content type="text"><![CDATA[转换(transform)通过 CSS3 转换,我们能够对元素进行移动、缩放、转动、拉长或拉伸。transform:[transform-functions] 2d转换transform方法包括: translate() - 移位 rotate() - 旋转 scale() - 放大或缩小 skew() - 偏斜 matrix() - 综合变换 1. translate通过 translate() 方法,根据给定的 left(x 坐标) 和 top(y 坐标) 位置参数,元素从其当前位置移动。值 translate(50px,100px) 把元素从左侧移动 50 像素,从顶端移动 100 像素。值 translate(50px) 相当于 translateX(50px)兼容写法: 1234567div { transform: translate(50px,100px); -ms-transform: translate(50px,100px); //IE 9 -webkit-transform: translate(50px,100px); //Safari and Chrome -o-transform: translate(50px,100px); //Opera -moz-transform: translate(50px,100px); //Firefox} 同时有 translateX() 方法和 translateY() 方法 2. rotate通过 rotate() 方法,元素顺时针旋转给定的角度。允许负值,元素将逆时针旋转。值 rotate(30deg) 把元素顺时针旋转 30 度。相当于rotateZ(30deg)。兼容写法: 1234567div { transform: rotate(30deg); -ms-transform: rotate(30deg); //IE 9 -webkit-transform: rotate(30deg); //Safari and Chrome -o-transform: rotate(30deg); //Opera -moz-transform: rotate(30deg); //Firefox} 3. scale通过 scale() 方法,根据给定的宽度(X 轴)和高度(Y 轴)参数,元素的尺寸会增加或减少。尺寸是number类型,可以是小数。值 scale(2) 把宽高都扩大2倍; scale(2,4) 把宽度转换为原始尺寸的 2 倍,把高度转换为原始高度的 4 倍。兼容写法同上,transform 后的 function改成 scale(2, 4) 即可。同时有 scaleX() 方法和 scaleY() 方法 4. skew通过 skew() 方法,根据给定的水平线(X 轴)和垂直线(Y 轴)参数,元素偏斜/翻转给定的角度。值 skew(30deg,20deg) 围绕 X 轴把元素翻转 30 度,围绕 Y 轴翻转 20 度。值 skew(30deg) 相当于 skewX(30deg) 围绕 X 轴把元素翻转 30 度。同时有 skewX() 方法和 skewY() 方法 5. matrixmatrix() 方法把所有 2D 转换方法组合在一起。matrix() 方法需要六个参数,包含数学函数,允许旋转、缩放、移动以及倾斜元素。matrix方法是根据一个33的矩阵和另一个31矩阵相乘来实现图形变换的,上述提到过的translate、rotate、scale、skew方法都可以转换成matrix,其实现原理都是由matrix而来。matrix(a, b, c, d, tx, ty)六个参数对应的矩阵如下: a c tx b d ty 0 0 1 transform:其中tx、ty表示需要移动的x,y坐标,上述矩阵与由transform中心x、y而定的另一个矩阵相乘,最终会得到移动后的x、y坐标。如:transform: matrix(1, 0, 0, 1, 30, 30), 假设transform中心是(0, 0) 1 0 30 0 1*0+0*0+30*1 30 0 1 30 * 0 = 0*0+1*0+30*1 = 30 0 0 1 1 0*0+0*0+1*1 1 故等同于transform:translate(30px, 30px), 要实现translate效果只需改变matrix的后两位参数tx、ty的值 scale:缩放同translate类似也只需改变matrix的两个参数,即matrix(1, 0, 0, 1, tx, ty)中两个1所在位置的参数,其中前者是横向缩放比例,后者是纵向缩放比例matrix(sx, 0, 0, sy, 0, 0)等同于scale(sx, sy) rotate:假设是rotate(θ), matrix(cosθ, sinθ, -sinθ, cosθ, 0, 0), 结合矩阵公式,可以算出中心点应该在的x、y位置 12x' = x*cosθ-y*sinθ+0 = x*cosθ-y*sinθy' = x*sinθ+y*cosθ+0 = x*sinθ+y*cosθ skew:skew(θx, θy) 等同于 matrix(1, tan(θy), tan(θx), 1, 0, 0) 用matrix可以实现以上方法不能实现的更复杂的变换,如镜像变换,假设我们要根据y=kx进行镜像变换(其中k是斜率),那么matrix函数应该这样写: matrix((1-k*k) / (1+k*k), 2k / (1 + k*k), 2k / (1 + k*k), (k*k - 1) / (1+k*k), 0, 0) matrix的参数是计算出来的,已知点(x, y)坐标,求其对称点(x’, y’)的坐标: (y-y’) / (x - x’) = -1/ k → ky-ky’ = -x+x’(x + x’) / 2 k = (y + y’)/2 → kx+kx’ = y+y’得到x’ = (1-kk)/(kk+1) x + 2k/(kk+1) yy’ = 2k/(kk+1) x + (kk-1)/(kk+1) y再结合矩阵计算公式:x’ = ax+cy+txy’ = bx+dy+ty计算出:a = (1-kk)/(kk+1);b = 2k/(kk+1);c = 2k/(kk+1);d = (kk-1)/(k*k+1); 2d变换中,可以通过设置transform-origin来改变变换的中心点。(3d也适用) 3d转换1. translate比起2d转换多了个translateZ和translate3d(x,y,z)的方法,translateZ控制元素朝我们远近移动,朝远处移动元素就变小,朝近处移动元素就变大。 3d变换中有个叫做透视(perspective)的属性,若我们设置perspective:201px,则其子元素设置的translateZ值越小,则子元素的大小就越小(因为元素远去,我们眼睛看到的就会变小);translateZ值越大,该元素也会越来越大,当translateZ值非常接近201像素,但是不超过201像素的时候(如200像素),该元素的大小就会撑满整个屏幕(如果父辈元素没有类似overflow:hidden的限制的话);当translateZ值再变大,超过201像素的时候,该元素看不见了。 perspective属性有两种书写形式,一种用在舞台元素上(动画元素们的共同父辈元素);第二种就是用在当前动画元素上,与transform的其他属性写在一起。 perspective-origin属性就是透视的中心点 2. scalescale有scale3d和scaleZ的方法 3. rotaterotate3d(x,y,z,angle),其中x、y、z是相对于各个轴旋转角度的系数,即相对x轴旋转xangle度,相对于y轴旋转yangle度,相对于z轴旋转z*angle度。 4. matrixmatrix3d是综合上述的方法,它有16个参数,从而构成一个4*4的矩阵。 5. 其他属性(1)transform-styletransform-style属性也是3D效果中经常使用的,其两个参数,flat|preserve-3d. 前者flat为默认值,表示平面的;后者preserve-3d表示3D透视。(2)backface-visibility在现实世界中,我们无法穿过物体A看到其后面的物体B或C或D;但是,在CSS3的3D世界中,默认情况下,我们是可以看到背后的元素。因此,为了切合实际,我们常常会设置backface-visibility:hidden,使后面元素不可见。 6. 实际应用图片的旋转木马效果因为要正好绕成一个圈,因此,图片rotateY值正好0~360等分,于是,如果有9张图片,则每个图片的旋转角度累加40(360 / 9 = 40)度即可 123456789img:nth-child(1) { transform: rotateY( 0deg ); }img:nth-child(2) { transform: rotateY( 40deg ); }img:nth-child(3) { transform: rotateY( 80deg ); }img:nth-child(4) { transform: rotateY( 120deg ); }img:nth-child(5) { transform: rotateY( 160deg ); }img:nth-child(6) { transform: rotateY( 200deg ); }img:nth-child(7) { transform: rotateY( 240deg ); }img:nth-child(8) { transform: rotateY( 280deg ); }img:nth-child(9) { transform: rotateY( 320deg ); } 这样以后,9张图的角度虽然不一样,但是它们都站在同一个点上,早就挤作一团。9张图分别面朝东南西北等共9个不同方位,只要将它们都向前移动4~5步(即使用translateZ),它们之间的空间就会拉开了,呈现出圆形。translateZ方法的参数通过计算得出,假设上述每个img的宽度都为178px,距离r的值则为: r = (128 / 2) / Math.tan((40 / 2) / 180 * Math.PI) ≈ 175.8 为了好看,图片之间可以留了点间距,则使用的translateZ的值为175.8 + 20 = 195.8最后只要写js代码,每次点击让容器每次沿y轴旋转40度就可以了。]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
<tag>css3</tag>
</tags>
</entry>
<entry>
<title><![CDATA[http缓存机制]]></title>
<url>%2F2017%2F05%2F21%2Fhttp%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6%2F</url>
<content type="text"><![CDATA[什么是cache?浏览器缓存(Browser Caching)是为了加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。chrome控制台下的Frames即展示的是浏览器的http文件级缓存。cache的作用:1、减少延迟,让你的网站更快,提高用户体验。2、避免网络拥塞,减少请求量,减少输出带宽。过程:主要是针对重复的http请求,在有缓存的情况下判断过程分3步:1) 判断expires,如果未过期,直接读取http缓存文件,不发http请求,否则进入下一步。2) 判断是否含有etag,有则带上if-none-match发送请求,未修改返回304,修改返回200,否则进入下一步。3) 判断是否含有last-modified,有则带上if-modified-since发送请求,无效返回200,有效返回304,否则直接向服务器请求。 200 OK(From Cache)浏览器没有向服务器端发送请求,而是直接使用了浏览器自己本地的缓存数据。200 OK指浏览器向服务器发送请求并获得了最新更新的数据。触发时机:直接点击链接访问或输入网址按回车访问 304(Not Modified)浏览器首先向服务器发送请求,确认数据是否发生改变,若没有改变,则加载浏览器自己的缓存数据。触发时机:刷新页面、设置了长缓存或ETags 当你第一次访问时,服务器会返回给你200状态码,同时在头里追加ETag值给你。浏览器拿到后将其缓存。下一次再访问时,因浏览器已经有该地址的ETag值了。会将其缓存的ETag值内容放在请求头的If-None-Match中,服务器检查其自身内容的ETag值是否与其一致,如果一致就会返回304状态码,告诉你内容和你保存的一致,没有发生改变过。 http缓存基础知识http报文中与缓存相关的首部字段通用首部字段Cache-Control:控制缓存的行为Pragma:http1.0,值为‘no-cache’禁用缓存请求首部字段if-Match:比较ETag是否一致if-None-Match:比较ETag是否不一致if-Modified-Since:比较资源最后更新时间是否一致if-Unmodified-Since:比较资源最后更新时间是否不一致相应首部字段ETag:资源的匹配信息实体首部字段Expires:http1.0,实体主体过期的时间last-Modified:资源最后一次修改的时间 设置缓存行为 http1.0通过Expires设置缓存过期时间(为一个GMT时间),如果还没过该时间点则不发送请求;通过Pragma来禁用缓存。优先级Pragma > Expires http1.1新增Cache-Control字段来控制缓存,Cache-Control在请求和响应报文中都能使用。优先级Cache-Control > Pragma > Expires请求中的取值: no-cache:告知服务器不使用缓存,要求向原服务器发起请求 no-store:所有内容都不会被保存到缓存或Internet临时文件中 max-age=delta-seconds:告知服务器希望接收一个存在时间不大于delta-seconds秒的资源 max-stale[=delta-seconds]:告知服务器愿意接收一个超过缓存时间的资源,若没有设置delta-seconds表示任意超出时间 min-fresh=delta-seconds:告知服务器希望接收一个在小于delta-seconds秒内更新过的资源 no-transform:告知服务器希望获取的数据没有被转换(如压缩) only-if-cached:告知服务器希望获取缓存的内容,而不向原服务器发送请求 cache-extension:自定义扩展值,若服务器不识别该值将被忽略 响应中的取值 public:表明任何情况下都得缓存该资源(即使是需要http认证的资源) Private[=”field-name”]:表面报文中field-name(若没有设置则为全部)中的数据开放给某些用户(服务器指定的share-user,如代理服务器)做缓存使用,其他用户不能缓存这些数据 no-cache:不直接使用缓存,要求向服务器发起请求 no-store:所有内容都不会被保存到缓存或Internet临时文件中 no-transform:告知客户端缓存文件时不得对实体数据做任何转换 only-if-cached:告知(代理)服务器客户端希望获取缓存的内容,不向原服务器发送请求 must-revalidate:当前资源一定是向原服务器发送验证请求的,若请求失败会返回504 proxy-revalidate:与must-revalidate类似,指仅能用于共享缓存(如代理) max-age=delta-seconds:告知客户端该资源在delta-seconds秒内是新鲜的,无需向服务器发送请求 s-maxage=delta-seconds:同max-age,但仅用于共享缓存 cache-extension:自定义扩展值 以上取值能组合起来使用,如:Cache-Control: max-age=3600, must-revalidate组合的形式还能做一些浏览器行为不一致的兼容处理。例如在IE我们可以使用 no-cache 来防止点击“后退”按钮时页面资源从缓存加载,但在 Firefox 中,需要使用 no-store 才能防止历史回退时浏览器不从缓存中去读取数据,故我们在响应报头加上如下组合值即可做兼容处理:Cache-Control: no-cache, no-store http缓存策略max-age与last-modified(if-modified-since)结合1. 浏览器第一次请求资源1)浏览器查询无cache内容,发送请求到服务器2)服务器接收到请求,响应并设置Cache-Control:max-age=XXX,Last-Modified:XXX GMT3)浏览器接收到响应,展示内容并缓存响应内容(状态码为200 ok)2. 浏览器在max-age时间内请求资源浏览器查询有缓存,于是检查max-age,还未过期直接读取响应给用户(状态码为200 ok form XX cache)3. 浏览器在max-age时间外请求资源1)浏览器查询有缓存,于是检查max-age,发现已经过期,发现资源带有Last-Modified,于是在请求首部加上If-Modified-Since字段(值为),发送请求给服务器2)服务器接收到请求发现有If-Modified-Since,于是和被请求资源的最后修改时间进行比较。若修改时间较新则返回新资源内容(状态码为200 ok);若发现时间一致,则只返回状态码304 Not Modified而不带整个资源3)浏览器接收到响应,根据响应状态选择是否使用缓存 仅使用max-age前两种情况和使用max-age和last-modified类似,服务器接收到请求后设置max-age,缓存过期后浏览器会再次向服务器发起请求 max-age与ETag结合前两种情况和使用max-age和last-modified类似,服务器接收到请求后设置max-age和ETag(由开发者自己确定的验证标识)第三种:缓存过期后,发现资源带有ETag,于是在请求头中添加If-None-Match(和ETag值相同),发送请求给服务器,服务器收到请求后将If-None-Match的值与被请求资源的验证串进行对比。若不一致则返回新的资源(状态码200 ok);若一致则只返回状态码304 Not Modified,不返回资源浏览器接收到服务器的响应后,根据响应状态决定是否使用缓存 浏览器缓存兼容及不同操作参考浏览器缓存详解 参考链接 cache策略实现原理浅谈浏览器http的缓存机制]]></content>
<categories>
<category>网络</category>
</categories>
<tags>
<tag>http</tag>
<tag>缓存</tag>
</tags>
</entry>
<entry>
<title><![CDATA[浏览器9种缓存机制]]></title>
<url>%2F2017%2F05%2F16%2F%E6%B5%8F%E8%A7%88%E5%99%A89%E7%A7%8D%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6%2F</url>
<content type="text"><![CDATA[一、http缓存http缓存是基于HTTP协议的浏览器文件级缓存机制。即针对文件的重复请求情况下,浏览器可以根据协议头判断从服务器端请求文件还是从本地读取文件,chrome控制台下的Frames即展示的是浏览器的http文件级缓存。详细介绍请看http缓存机制 二、websqlWeb Sql 数据库API实际上不是HTML5规范的组成部分,而是以一个独立规范形式出现,在HTML5之前就已经存在了。(现已不推荐使用)其特点: 将数据以数据库的形式存储在客户端,根据需求去读取; 与Storage的区别是:Storage和Cookie都是以键值对的形式存在的; Web Sql 更方便于检索,允许sql语句查询; 这个数据库是集成在浏览器里面的,目前主流浏览器基本都已支持;websql API主要包含三个核心方法: openDatabase:这个方法使用现有数据库或新建数据库来创建数据库对象 transaction:这个方法允许我们根据情况控制事务提交或回滚 executeSql:这个方法用于执行SQL语句 采用transaction和executeSql配合可以执行sql语句 db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)'); tx.executeSql('INSERT INTO t1 (id, log) VALUES (1, "foobar")'); tx.executeSql('INSERT INTO t1 (id, log) VALUES (2, "logmsg")'); }); 三、IndexedDBIndexedDB是一个事务型数据库系统,类似于基于SQL的RDBMS。 然而不同的是它使用固定列表,IndexedDB是一个基于JavaScript的面向对象的数据库。 IndexedDB允许您存储和检索用键索引的对象.Web SQL Database实际上已经被废弃,而HTML5的支持的本地存储实际上变成了Web Storage(Local Storage和Session Storage)与IndexedDB。Web Storage使用简单字符串键值对在本地存储数据,方便灵活,但是对于大量结构化数据存储力不从心,IndexedDB是为了能够在客户端存储大量的结构化数据,并且使用索引高效检索的API。 IndexedDB APIIndexedDB分别为同步和异步访问提供了单独的API。同步API本来是要用于仅供Web Workers内部使用,但是还没有被任何浏览器所实现。异步API在Web Workers内部和外部都可以使用。 异步API操作数据库: window.indexedDB.open(dbname, 版本号)-打开或创建一个数据库,该方法返回一个 IDBRequest 对象 (IDBOpenDBRequest);异步操作通过在 IDBRequest 对象上触发事件来和调用程序进行通信。 所有异步请求都有一个 onsuccess 回调和一个 onerror 回调,前者在数据库操作成功时调用,后者在一个操作未成功时调用。 修改数据库或对象存储的代码必须位于 upgradeneeded 事件处理函数中;修改数据库会触发 upgradeneeded 事件(通过onupgradeneeded函数监听)。 删除数据库:indexDB.deleteDatabase(dbname)操作对象存储:对象存储是一个数据记录集合。要在现有数据库中创建一个新对象存储,则需要对现有数据库进行版本控制。为此,请打开要进行版本控制的数据库。除了数据库名称之外,open 方法还接受版本号作为第二个参数。 创建对象存储:createObjectStore(name, option) 操作对象:添加-IDBObjectStore.add();获取-IDBObjectStore.get();删除-IDBObjectStore.delete();更新-IDBObjectStore.put()等 关于索引:创建-IDBObjectStore.createIndex();打开-IDBObjectStore.index();删除-IDBObjectStore.deleteIndex(); 关于游标:IDBObjectStore.openCursor();IDBObjectStore.openKeyCursor() 使用事务:db.transaction(objectname, mode),默认mode是readonly,其余选项还有readwrite和versionchange,示例代码: var trans1 = db.transaction(“foo”, “readwrite”); var trans2 = db.transaction(“foo”, “readwrite”); var objectStore2 = trans2.objectStore(“foo”) var objectStore1 = trans1.objectStore(“foo”) objectStore2.put(“2”, “key”); objectStore1.put(“1”, “key”); 四、localStoragelocalStorage是html5的一种新的本地缓存方案,目前用的比较多,一般用来存储ajax返回的数据,加快下次页面打开时的渲染速度。无时间限制,但不能存大量数据;数据量超过存储范围会报错且自动删除靠前的数据。localStorage.setItem(key, value)localStorage.getItem(key)localStorage.removeItem(key)localStorage.clear() 五、sessionStoragesessionStorage和localstorage类似,但是浏览器关闭则会全部删除,api和localstorage相同。 六、application cacheHTML5 引入了应用程序缓存,这意味着web应用可进行缓存,并可在没有因特网连接时进行访问。三个优势:离线浏览 - 用户可在应用离线时使用它们速度 - 已缓存资源加载得更快减少服务器负载 - 浏览器将只从服务器下载更新过或更改过的资源。所有主流浏览器均支持应用程序缓存,除了 IE。 使用应用程序缓存要在html标签上加上mainfest属性 1234<!DOCTYPE HTML><html manifest="demo.appcache">...</html> 以下是demo.appcache文件的一个示例 123456789101112CACHE MANIFEST //文件将在首次下载后进行缓存# 2012-02-21 v1.0.0/theme.css/logo.gif/main.jsNETWORK: //文件需要与服务器的连接,且不会被缓存login.aspFALLBACK: //文件规定当页面无法访问时的回退页面//第一个 URI 是资源,第二个是替补/html5/ /404.html 七、cachestorageCacheStorage是在ServiceWorker的规范中定义的。它主要用来存储 Response 对象,即是对 HTTP 响应做缓存的。CacheStorage 是多个 Cache 的集合,而每个 Cache 可以存储多个 Response 对象。 主要API CacheStorage.match() - 判断是否和cache中某个对象匹配,若匹配则返回一个Promise对象 cacheStorage.has() - 如果包含指定cache对象,则返回一个promise对象。 cacheStorage.open() - 打开一个cache对象,成功则返回一个promise对象。 cacheStorage.delete() - 删除cache对象,成功则返回一个promise对象,否则返回false。 cacheStorage.keys() - cache.addAll(), cache.put()八、cookie服务器端设置cookie向客户端颁发,cookie一般通过http请求中在头部一起发送到服务器端。一条cookie记录主要由键、值、域、过期时间、大小组成,一般保存用户的认证信息。cookie最大长度和域名个数由不同浏览器决定。可能会受到CSRF/XSRF(Cross-site request forgery)攻击九、flash缓存这种方式基本不用,这一方法主要基于flash有读写浏览器端本地目录的功能,同时也可以向js提供调用的api,则页面可以通过js调用flash去读写特定的磁盘目录,达到本地数据缓存的目的。 参考:浏览器九种缓存机制介绍]]></content>
<categories>
<category>web</category>
</categories>
<tags>
<tag>缓存</tag>
<tag>web</tag>
</tags>
</entry>
<entry>
<title><![CDATA[display:inline-block存在问题及其解决方法]]></title>
<url>%2F2017%2F05%2F14%2Fdisplay-inline-block%E9%97%AE%E9%A2%98%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%2F</url>
<content type="text"><![CDATA[display:inline-block是介于inline和block之间的一个取值,其使元素既可以设置width、height、padding、margin等,又保持了inline元素不占整行的特性。通过设置元素为inline-block,可以实现多列布局、导航栏等效果,但是会出现以下问题: 元素之间会出现空白间距 有内容的元素与无内容的元素渲染方式不一样 现象原因及解决方法空白间距空白间距是由换行或回车所产生空白符所致。空白间距的大小是由font-size来决定的,所以要消除空白间距,只需要把父元素的font-size设置为0即可,子元素的font-size需要重新设置。如果需要兼容IE6、7,需设置*word-spacing: -1px 有内容元素与无内容元素不在一行显示有内容元素和无内容元素的对齐方式不同,有内容元素以bottom为基准,无内容元素以top为基准。故只要在有内容元素上设置vertical-align:top或者在无内容元素上设置vertical-align: bottom 元素内连续的英文句子不断行,超出范围纯连续字母和数字不会换行,只能最后加上 word-wrap: break-word 强制自动换行搞定。 应用场景 网页的导航栏 排列布局,如3列布局]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
</tags>
</entry>
<entry>
<title><![CDATA[html5新标签及API]]></title>
<url>%2F2017%2F05%2F14%2Fhtml5%E6%96%B0%E6%A0%87%E7%AD%BE%E5%8F%8AAPI%2F</url>
<content type="text"><![CDATA[新增标签结构标签(1)section:独立内容区块,可以用h1~h6组成大纲,表示文档结构,也可以有章节、页眉、页脚或页眉的其他部分;(2)article:特殊独立区块,表示这篇页眉中的核心内容;(3)aside:标签内容之外与标签内容相关的辅助信息;(4)header:某个区块的头部信息/标题;(5)hgroup:头部信息/标题的补充内容;(6)footer:底部信息;(7)nav:导航条部分信息(8)figure:独立的单元,例如某个有图片与内容的新闻块。 表单标签(1)email:必须输入邮件;(2)url:必须输入url地址;(3)number:必须输入数值;(4)range:必须输入一定范围内的数值;(5)Date Pickers:日期选择器;input type类型选择:a. date:选取日、月、年b. month:选取月、年c. week:选取周和年d. time:选取时间(小时和分钟)e. datetime:选取时间、日、月、年(UTC时间)f. datetime-local:选取时间、日、月、年(本地时间)(6)search:搜索常规的文本域;(7)color:颜色(拾色器)(8)tel:电话号码 媒体标签(1)video:视频(2)audio:音频(3)embed:嵌入内容(包括各种媒体),Midi、Wav、AU、MP3、Flash、AIFF等。 其他标签(1)mark:标注(像荧光笔做笔记)(2)progress:进度条;<progress max="最大进度条的值" value="当前进度条的值">(3)time:数据标签,给搜索引擎使用;发布日期<time datetime="2014-12-25T09:00">9:00</time>更新日期<time datetime="2015- 01-23T04:00" pubdate>4:00</time>(4)ruby和rt:对某一个字进行注释;<ruby><rt>注释内容</rt><rp>浏览器不支持时如何显示</rp></ruby>(5)wbr:软换行,页面宽度到需要换行时换行;(6)canvas:使用JS代码做内容进行图像绘制;(7)command:按钮;(8)deteils :展开菜单;(9)dateilst:文本域下拉提示;(10)keygen: 加密; 新增属性(1)manifest属性:定义页面需要用到的离线应用文件,一般放在html标签里(2)charset属性: meta属性之一,定义页面的字符集(3)sizes属性: link新增属性,当link的rel=”icon”时,用以设置图标大小(4)base属性:<base href="http://localhost/" target="_blank">表示当在新窗口打开一个页面时,会将href中的内容作为前缀添加到地址前(5)defer属性: script标签属性,表示脚本加载完毕后,只有当页面也加载完毕才执行(推迟执行), h5之前就有(6)async属性: script标签属性,脚本加载完毕后马上执行(运行过程中浏览器会解析下面的内容),即使页面还没有加载完毕(异步执行)(7)media属性: a元素属性:表示对何种设备进行优化(8)hreflang属性: a的属性,表示超链接指向的网址使用的语言(9)ref属性: a的属性,定义超链接是否是外部链接(10)reversed属性: ol的属性,定义序号是否倒叙(11)start属性: ol的属性,定义序号的起始值(12)scoped属性: 内嵌CSS样式的属性,定义该样式只局限于拥有该内嵌样式的元素,适用于单页开发(13)seamless属性: iframe元素,新增了seamless无边距无边框 新增实用方法和属性1. getElementsByClassName()方法该方法接收一个参数,即一个包含一或多个类名的字符串,返回带有指定类的所有元素的NodeList。传入多个类名时,类名的先后顺序不重要。2. classList 属性element.classList属性返回由element元素的classname组成的类数组,只读属性,可以通过以下方法操作: add(value):将给定的字符串值添加到列表中。如果值已经存在,就不添加了。 contains(value):表示列表中是否存在给定的值,如果存在则返回true,否则返回false。 remove(value):从列表中删除给定的字符串。 toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。 3. 自定义数据属性HTML5 规定可以为元素添加非标准的属性,但要添加前缀data-,目的是为元素提供与渲染无关的信息,或者提供语义信息。这些属性可以任意添加、随便命名,只要以data-开头即可。data属性可以通过element.dataset.来获取4. outerHTML 属性outerHTML 属性和innerHTML 类似;不同的是,outerHTML包括调用节点在内,而innerHTML不包括。*5. insertAdjacentHTML()方法插入元素,它接收两个参数:插入位置和要插入的HTML文本。第一个参数必须是下列值之一:“beforebegin”,在当前元素之前插入一个紧邻的同辈元素;“afterbegin”,在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素;“beforeend”,在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素;“afterend”,在当前元素之后插入一个紧邻的同辈元素。 新增APIDrag&Drop API (拖放)使用dataTransfer 接口来支持拖放数据存储,它的使用方式一般为 event.dataTransfer。 dataTransfer.effectAllowed[=value]。该属性返回拖曳对象允许的拖曳时的反馈效果 【放在可移动元素start事件上】dataTransfer.dropEffect[=value]。该属性返回已设置的拖放时反馈效果。【放在目标容器over事件上】dataTransfer.items。返回一个关于拖曳数据的DataTransferItemList对象。dataTransfer.setDragImage(element, x, y)。指定拖曳元素时随鼠标移动的图片,x、y分别是图片相对于鼠标的横坐标和纵坐标。dataTransfer.addElement(element)。将元素添加到被拖曳的列表里。如果你想让某个元素跟随被拖曳元素一同被拖曳,可以使用这个方法。dataTransfer.types。返回在dragstart事件触发时为元素存储数据的格式。如果是系统文件的拖曳,则返回files。dataTransfer.setData(format, data)。为元素添加数据,在dragstart事件触发时可以用它为被拖曳元素存储数据。数据格式一般有两种:text/plain(设置format为字符串text即可,主要用于文本数据)和text/uri-list(设置format为字符串url即可,主要用于url)。data=dataTransfer.getData(format)。返回存储的数据。如果数据不存在,则返回空字符串。dataTransfer.clearData([format])。删除指定格式的数据。如果不指定格式,则删除所有数据。dataTransfer.files。如果是拖曳系统文件,返回正在被拖曳的文件列表对象。可以通过它获得所拖曳的文件数据。【拖拽上传】 History API(历史记录)提供了两个新方法pushState()和replaceState(),它们允许我们添加和改变当前浏览器的地址。pushState()和replaceState()参数一样,参数说明如下:1、state:存储JSON字符串,可以用在popstate事件中。2、title:现在大多数浏览器不支持或者忽略这个参数,最好用null代替3、url:任意有效的URL,用于更新浏览器的地址栏,并不在乎URL是否已经存在地址列表中。更重要的是,它不会重新加载页面。 history.pushState({username: “html5”}, “user account”, “user.html”); 用于向history对象添加当前页面的记录,并且改变浏览器地址栏的URLhistory.replaceState({username: “html5” }, “user account”, “user.html”); 类似于pushState(),只是将当前页面状态替换为新的状态 Notification API (桌面通知) 构造函数:new Notification,2个参数:消息的标题,消息主体对象,其中消息主体对象包括消息框的图标(icon)和消息内容(body)。requestPermission(callback)方法:请求用户授权Notification.permission属性:取值default-用户没有接收或拒绝授权请求,不能显示通知;granted-用户接受授权请求,允许显示通知;denied-用户拒绝授权请求,不允许显示通知4个事件处理函数:onshow函数-在消息展示时执行onclick函数-在用户点击消息后被调用onclose函数-在消息框被关闭时被调用onerror函数-发生错误时被调用,如果没有被授权而继续创建消息通知,也会执行onerror函数 Communication API (跨域通信)以往的浏览器,跨域存在安全问题(CSRF攻击,Cross-Site Request Forgery跨站请求伪造),现在使用Communication API可以很好的避免这个问题。用postMessage函数将消息跨域传递,通过监听message事件接收消息 WebSocket API提供了全双工通信方式,我们从此可以在Web应用中实现实时的数据传输和获取。支持双向、双工通信。可以实现实现微博新消息通知、邮件推送、实时游戏和聊天等功能。 Web Worker简单来说,就是通过JavaScript创建一个后台进程(或者叫工作者进程),执行一些特殊的任务(比如耗时比较长的数据处理),并且提供主进程和新进程之间数据交换接口:postMessage和onmessage。它起到互不阻塞执行的效果,避免了传统的JavaScript执行长时间操作时界面无响应的弊端,提高了性能及用户体验。 Storage API主要涉及localStorage API、sessionStorage API、applicationCacheAPI(离线存储)和服务器端Manifest文件等概念。 Canvas和WebGLDevice API使HTML5 标签可以直接调用类似摄像头、电源、系统、文件、网络等。Geolocation API(地理位置API)File API来帮助我们在Web页面中访问本地文件,它可以在Web应用中展现文件,或者选择并读取文件。Media Capture API增强了HTML表单,提供了对音频、图像和视频进行采集的功能。PC上还未实现,欧朋手机浏览器实现HTML5标签打开摄像头。Contact API主要应用在移动设备上,提供对用户通用通讯录的访问Calendar API与ContactAPI非常类似,提供了对用户通用日历的存取方式,主要应用在移动设备上。System Information API用于为Web应用提供访问系统各种运行时属性的方式,主要也应用在移动设备上。(都还未有浏览器实现)Messaging API定义了一个简单的API来发送和接收电子邮件、短信和彩信,主要应用在移动设备上。]]></content>
<categories>
<category>html</category>
</categories>
<tags>
<tag>html</tag>
<tag>html5</tag>
</tags>
</entry>
<entry>
<title><![CDATA[html5新特性]]></title>
<url>%2F2017%2F05%2F12%2Fhtml5%E6%96%B0%E7%89%B9%E6%80%A7%2F</url>
<content type="text"><![CDATA[html5简介html5是html最新的修订版本,2014年10月由万维网(W3C)完成标准制定。希望能减少网页浏览器对于如flash等丰富性网络应用服务(Plug-in-Based Rich Internet Application, RIA)的依赖,并提供更多能加强网络应用的标准集。 html5为了支持多媒体引进了如video、audio和canvas标记,同时集成了SVG内容;为了丰富文档内容引进了section、article、header、nav等元素;同时有些如a、cite、menu元素被重新定义或标准化,有些元素如big、center、font等被移除。 html5的一些新特性 语义化 本地存储特性:localstorage,Indexed DB等 设备兼容性:Geolocation功能 连接特性:更有效的服务器推送技术,Server-Sent Event和WebSockets 网页多媒体特性:支持网页的Audio、Video等多媒体功能 三维、图形及特效特性:SVG、Canvas、WebGL及CSS3的3D功能 性能与集成特性:XMLHttpRequest2异步及跨域请求(用户不用等待资源加载完后再做操作,提高性能) CSS3特性html5提供的新元素和属性 增加语义化标签,取消过时的html4标记:剔除一些修饰性的标签,直接使用css 将内容和展示分离:b和i标签依旧保留,但意义是为了将一段文字标示出来,并非为了展示特殊样式 一些全新的表单输入:date、url、email等类型 全新的Tag:多媒体对象不再全绑定在object或embed tag中,视频有视频的tag,音频有音频的tag 本地数据库:Indexed DB等 Canvas对象:直接在浏览器上绘制矢量图,使用户脱离flash html5的优缺点优点: 是网络标准 多设备跨平台,可移植性好,自适应网页设计 对搜索引擎友好 及时更新(html5游戏更新就像更新页面一样快) 提高可用性,改进用户体验 缺点:浏览器兼容性 新特性8点:1.语义化2.连通性:和服务器之间通过新技术进行通信3.离线&存储:让网页在客户端本地存储数据以及更高效地离线运行4.多媒体:video,audio等,使网页摆脱flash等外部媒体5.2D/3D绘图:SVG,Canvas6.性能&集成:性能优化和计算机硬件使用7.设备访问:能够处理各种输入输出设备8.样式(css3) 语义化1.新的节段和提纲标签:section, article, nav, header, footer, aside, hgroup等2.表单控件:calendar,input type属性(如color,date,datetime,datetime-local,email,tel,url,search,month,week,number,range),output等 3.HTML5拖放(Drag,Drop)浏览器支持:IE9+,Firefox,Opera12+,Chrome,Safari5+(Safari5.1.2不支持)draggable 要将允许拖动的元素的该属性设置为true;ondragstart 事件调用函数drag(event),它规定了被拖动的数据,用event.dataTransfer.setData(datatype, value)方法设置被拖动数据的数据类型和值;ondragover 事件规定在什么地方放置被拖动的数据,默认是无法将数据/元素放置到其他元素中的,如果要允许,必须阻止对元素的默认处理(调用event.preventDefault()阻止默认操作);ondrop 放置拖放数据时触发,首先要阻止事件默认行为(event.preventDefault()),然后通过event.dataTransfer.getData(datatype)获取被拖放的元素的value,最后把被拖放的元素加到目标元素中(event.target.appendChild(ele)) 多媒体1.视频标签:video1.video支持的三种视频格式以及浏览器支持情况Ogg(带有Theora视频编码和Vorbis音频编码的Ogg文件):Firefox3.5+,Opera10.5+,Chrome5.0+支持,Safari和IE不支持;MPEG4(带有H.264视频编码和AAC音频编码的MPEG4文件):IE9+,Chorme5+,Safari3+支持,Firefox和Opera不支持;WebM(带有VP8视频编码和Vorbis音频编码的WebM文件):Firefox4+,Opera10.6+,Chorme6+支持,IE和Safari不支持实例: 12345<video width="320", height="240" controls="controls"> <source src="movie.ogg" type="video/ogg"> <source src="movie.mp4" type="video/mp4">Your browser does not support the video tag.</video> 2.一些属性autoplay,controls,height,width,loop(是否在视频播放完毕后返回开头),preload(若使用了autoplay属性则这个忽略属性),src等3.DOM方法,属性和事件方法:play(), pause(), load(), canPlayType等属性:currentSrc, currentTime, videoWidth, videoHeight, duration, ended, error, paused, muted, seeking, volume, height, width等事件:play, pause, progress, error, timeupdate, ended, abort, emptied, waiting, loadedmetadata等 2.音频标签audio1.音频标签支持的三种音频格式Ogg Vorbis:Firefox3.5+,Opera10.5+,Chrome3+支持,IE9和Safari3.0不支持MP3:IE9+,Chrome3+,Safari3+支持,Firefox3.5和Opera10.5不支持Wav:Firefox3.5+,Opera10.5+,Safari3.0+支持,IE9和Chrome3.0不支持实例: 12345<audio> <source src="song.ogg" type="audio/ogg"> <source src="song.mp3" type="audio/mpeg">Your browser does not support the audio tag.</audio> 2.属性autoplay, controls, loop, preload, src等 track 元素支持字幕和章节WebRTC 能即时通信,允许连接到其他人,在浏览器中直接控制视频会议而不需要一个插件或者外部的应用程序Camera API 操作计算机摄像头,并从中存储图像 2d/3d绘图1. SVG(2d)SVG 指可伸缩矢量图形 (Scalable Vector Graphics) SVG 用来定义用于网络的基于矢量的图形 SVG 使用 XML 格式定义图形 SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失 SVG 是万维网联盟的标准 SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体 与其他图像格式相比,使用 SVG 的优势在于:SVG 可被非常多的工具读取和修改(比如记事本)SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。 SVG 是可伸缩的SVG 图像可在任何的分辨率下被高质量地打印SVG 可在图像质量不下降的情况下被放大SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)SVG 可以与 Java 技术一起运行SVG 是开放的标准SVG 文件是纯粹的 XMLSVG 的主要竞争者是 Flash。与 Flash 相比,SVG 最大的优势是与其他标准(比如 XSL 和 DOM)相兼容。而 Flash 则是未开源的私有技术。支持DOM事件处理等 2.Canvas依赖分辨率不支持事件处理器弱的文本渲染能力能够以 .png 或 .jpg 格式保存结果图像最适合图像密集型的游戏,其中的许多对象会被频繁重绘 离线缓存和Web存储1. sessionStorage和localStoragesessionStorage 和 localStorage 是 HTML5 Web Storage API 提供的,可以方便的在 web 请求之间保存数据。有了本地数据,就可以避免数据在浏览器和服务器间不必要地来回传递。sessionStorage、 localStorage 、 cookie 都是在浏览器端存储的数据,其中 sessionStorage 的概念很特别,引入了一个“浏览器窗口”的概念。 sessionStorage 是在同源的同窗口(或 tab )中,始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后, sessionStorage 即被销毁。同时“独立”打开的不同窗口,即使是同一页面, sessionStorage 对象也是不同的。cookies会发送到服务器端,其余两个不会。 Microsoft 指出 Internet Explorer 8 增加 cookie 限制为每个域名 50 个,但 IE7 似乎也允许每个域名 50 个 cookie 。 Firefox 每个域名 cookie 限制为 50 个。 Opera 每个域名 cookie 限制为 30 个。 Firefox 和 Safari 允许 cookie 多达 4097 个字节,包括名( name )、值( value )和等号。 Opera 许 cookie 多达 4096 个字节,包括:名( name )、值( value )和等号。 Internet Explorer 允许 cookie 多达 4095 个字节,包括:名( name )、值( value )和等号。 区别: - Cookie 每个域名存储量比较小(各浏览器不同,大致 4K ) 所有域名的存储量有限制(各浏览器不同,大致 4K ) 有个数限制(各浏览器不同) 会随请求发送到服务器 - LocalStorage 永久存储 单个域名存储量比较大(推荐 5MB ,各浏览器不同) 总体数量无限制 - SessionStorage 只在 Session 内有效 存储量更大(推荐没有限制,但是实际上各浏览器也不同) sessionStorage和localStorage用法 setItem( key, value) getItem( key ) removeItem(key) clear() 用.和[]获取键值 storage事件: 当键值改变或者clear的时候,就可以触发 2.应用程序缓存HTML5 引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问。除了IE,所有主流浏览器都支持应用程序缓存为应用带来三个优势:离线浏览 - 用户可在应用离线时使用它们速度 - 已缓存资源加载得更快减少服务器负载 - 浏览器将只从服务器下载更新过或更改过的资源。用法:必须在文档的html标签中包含manifest属性,或者在manifest文件中配置 123456<!DOCTYPE HTML><html manifest="demo.appcache"><body> The content of the document......</body></html> 完整的manifest文件: 1234567891011CACHE MANIFEST # 2012-02-21 v1.0.0 /theme.css /logo.gif /main.js NETWORK: login.asp FALLBACK: /html5/ /404.html manifest 文件可分为三个部分:CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)manifest 文件需要配置正确的 MIME-type,即 “text/cache-manifest”。必须在 web 服务器上进行配置一旦文件被缓存,则浏览器会继续展示已缓存的版本,即使您修改了服务器上的文件。为了确保浏览器更新缓存,您需要更新 manifest 文件。 性能&集成1. Web Worker能够把 JavaScript 计算委托给后台线程,通过允许这些活动以防止使交互型事件变得缓慢实例:实现一个定时计数的功能,不影响用户在该页面操作交互 123456789101112131415161718192021222324252627282930313233<!DOCTYPE html><html><body> <p>Count numbers: <output id="result"></output></p> <button onclick="startWorker()">Start Worker</button> <button onclick="stopWorker()">Stop Worker</button> <br /><br /> <script> var w; function startWorker() { if(typeof(Worker)!=="undefined") { if(typeof(w)=="undefined") { w=new Worker("demo_workers.js"); } w.onmessage = function (event) { document.getElementById("result").innerHTML=event.data; }; } else { document.getElementById("result").innerHTML="Sorry, your browser does not support Web Workers..."; } } function stopWorker() { w.terminate(); } </script></body></html> 其中demo_workers.js代码如下: 12345678var i=0;function timedCount(){ i=i+1; postMessage(i); setTimeout("timedCount()",500);}timedCount(); 由于 web worker 位于外部文件中,它们无法访问下例 JavaScript 对象:window 对象,document 对象,parent 对象 通信1.WebSocket设备访问1.使用Camera API2.触控事件3.使用地理位置定位1234567if (navigator.geolocation){ navigator.geolocation.getCurrentPosition(showPosition);}else{ x.innerHTML="Geolocation is not supported by this browser.";} 有getCurrentPosition(),watchPosition(),clearWatch(watchele)方法 1234var watchID = navigator.geolocation.watchPosition(function(position) { do_something(position.coords.latitude, position.coords.longitude);});navigator.geolocation.clearWatch(watchID); 4.检测设备方向要接收设备方向变化信息,要注意监听deviceorientation事件 window.addEventListener(“deviceorientation”, handleOrientation, true); 方向事件对象包含四个值:event.absoluteevent.alpha: 表示设备沿z轴上的旋转角度,范围为0~360。event.beta: 表示设备在x轴上的旋转角度,范围为-180~180。它描述的是设备由前向后旋转的情况。event.gamma: 表示设备在y轴上的旋转角度,范围为-90~90。它描述的是设备由左向右旋转的情况。 5.指针锁定API样式css3: border-radius, box-shadow, transform(translate), transition, animation, @font-face等]]></content>
<categories>
<category>html</category>
</categories>
<tags>
<tag>html</tag>
<tag>html5</tag>
</tags>
</entry>
<entry>
<title><![CDATA[跨域资源共享CORS]]></title>
<url>%2F2017%2F05%2F09%2F%E8%B7%A8%E5%9F%9F%E8%B5%84%E6%BA%90%E5%85%B1%E4%BA%ABCORS%2F</url>
<content type="text"><![CDATA[CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。CORS需要浏览器和服务器的同时支持,目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。 两种请求浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。 1. 简单请求 (1) 请求方法是以下三种方法之一: HEAD GET POST(2)HTTP的头信息不超出以下几种字段: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain 对于简单请求,浏览器直接发出CORS请求,就是在头信息之中,增加一个Origin字段。Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。 如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。 如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。 1234Access-Control-Allow-Origin: http://api.bob.comAccess-Control-Allow-Credentials: trueAccess-Control-Expose-Headers: FooBarContent-Type: text/html; charset=utf-8 1)Access-Control-Allow-Origin该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个,表示接受任意域名的请求。2)Access-Control-Allow-Credentials该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。3)Access-Control-Expose-Headers该字段可选。CORS请求时,XHR对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。*使用cookie浏览器要向服务器端上传cookie,不仅服务器端的Access-Control-Allow-Credentials值要设置为true,开发者必须在AJAX请求中设置withCredentials属性为true。 12var xhr = new XMLHttpRequest();xhr.withCredentials = true; 如果省略withCredentials设置,有的浏览器还是会一起发送Cookie。这时,可以显式关闭withCredentials,设置其值为false。如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。 2. 非简单请求非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json的请求。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。 预检请求浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。浏览器会自动判断请求是否为简单请求,若为非简单请求,浏览器自动发出“预检”请求。“预检”请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。除了Origin字段,”预检”请求的头信息包括两个特殊字段。1)Access-Control-Request-Method该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。2)Access-Control-Request-Headers该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。 预检请求的回应服务器收到”预检”请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。如果浏览器否定了”预检”请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段浏览器确认了“预检”请求,回应中会包括以下字段: 12345Access-Control-Allow-Origin: http://api.bob.comAccess-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: X-Custom-HeaderAccess-Control-Allow-Credentials: trueAccess-Control-Max-Age: 1728000 1)Access-Control-Allow-Methods该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次”预检”请求。2)Access-Control-Allow-Headers如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在”预检”中请求的字段。3)Access-Control-Allow-Credentials该字段与简单请求时的含义相同,即是否允许发送cookie。4)Access-Control-Max-Age该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。 “预检”通过后,正常请求一旦服务器通过了”预检”请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。 3. 与JSONP对比CORS与JSONP的使用目的相同,但是比JSONP更强大。JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。 参考链接:阮一峰CORS详解]]></content>
<categories>
<category>web</category>
</categories>
<tags>
<tag>web</tag>
</tags>
</entry>
<entry>
<title><![CDATA[浏览器同源策略]]></title>
<url>%2F2017%2F05%2F08%2F%E6%B5%8F%E8%A7%88%E5%99%A8%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5%2F</url>
<content type="text"><![CDATA[一、含义最初的含义:A网页设置的cookie,B网页不能打开,除非这两个网页同源。(提交表单不受同源策略的限制)同源定义: 协议相同域名相同端口相同 非同源的限制: Cookie、LocalStorage 和 IndexDB 无法读取DOM无法获得ajax无法发送(要跨域) 二、cookie对于cookie来说:两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享 Cookie。举例来说,A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那么只要设置相同的document.domain,两个网页就可以共享Cookie。 12345document.domain = 'example.com';//A网页设置cookiedocument.cookie = "test1=hello";//B网页读取cookievar allCookie = document.cookie; 服务器也可以在设置Cookie的时候,指定Cookie的所属域名为一级域名,这样二级域名和三级域名不用做任何设置,都可以读取这个Cookie。 三、iframe如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。如果两个窗口一级域名相同,只是二级域名不同,那么设置上一节介绍的document.domain属性,就可以规避同源政策,拿到DOM。对于完全不同源的网站,存在一下3种方法: 片段识别符(fragment identifier)window.name跨文档通信API(Cross-document messaging) 1. 片段识别符片段标识符(fragment identifier)指的是,URL的#号后面的部分,比如http://example.com/x.html#fragment的#fragment。如果只是改变片段标识符,页面不会重新刷新。父窗口可以把信息,写入子窗口的片段标识符,子窗口通过监听hashchange事件得到通知。 123456789//父窗口var src = originURL + '#' + data;document.getElementById('myIFrame').src = src;//子窗口window.onhashchange = checkMessage;function checkMessage() { var message = window.location.hash;// ...} 同样的,子窗口也可以改变父窗口的片段标识符。 1parent.location.href= target + "#" + hash; 2. window.name浏览器窗口有window.name属性。这个属性的最大特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属性,后一个网页可以读取它。父窗口先打开一个子窗口,载入一个不同源的网页,该网页将信息写入window.name属性,接着,子窗口跳回一个与主窗口同域的网址,然后,主窗口就可以读取子窗口的window.name了。 123456//子窗口设置window.namewindow.name = data;//子窗口跳到一个与父窗口同源的网站location = 'http://parent.url.com/xxx.html';//父窗口读取var data = document.getElementById('myFrame').contentWindow.name; 这种方法的优点是,window.name容量很大,可以放置非常长的字符串;缺点是必须监听子窗口window.name属性的变化,影响网页性能。 3. window.postMessageHTML5为了解决同源策略问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。 1otherWindow.postMessage(message, targetOrigin, [transfer]); otherWindow:其他窗口的一个引用;message:将要发送到其他 window的数据;targetOrigin:通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串”“(表示无限制)或者一个URI;transfer(可选):是一串和message 同时传递的 Transferable 对象。这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。*其他window可以监听派遣的message 1234567891011window.addEventListener("message", receiveMessage, false);function receiveMessage(event){// For Chrome, the origin property is in the event.originalEvent// object. var origin = event.origin || event.originalEvent.origin; if (origin !== "http://example.org:8080") return; // ...} message事件的事件对象event,提供以下三个属性。data:从其他 window 中传递过来的对象;origin:调用 postMessage 时消息发送方窗口的 origin;source:对发送消息的窗口对象的引用。示例A窗口: 12345678910111213141516171819202122/** In window A's scripts, with A being on <http://example.com:8080>:*/var popup = window.open(...popup details...);// When the popup has fully loaded, if not blocked by a popup blocker:// This does nothing, assuming the window hasn't changed its location.popup.postMessage("The user is 'bob' and the password is 'secret'", "https://secure.example.net");// This will successfully queue a message to be sent to the popup, assuming// the window hasn't changed its location.popup.postMessage("hello there!", "http://example.org");function receiveMessage(event){ // Do we trust the sender of this message? (might be// different from what we originally opened, for example). if (event.origin !== "http://example.org") return; // event.source is popup // event.data is "hi there yourself! the secret response is: rheeeeet!"} 另一个窗口: 1234567891011121314151617181920/** In the popup's scripts, running on <http://example.org>:*/// Called sometime after postMessage is calledfunction receiveMessage(event){ // Do we trust the sender of this message? if (event.origin !== "http://example.com:8080") return; // event.source is window.opener // event.data is "hello there!" // Assuming you've verified the origin of the received message (which // you must do in any case), a convenient idiom for replying to a // message is to call postMessage on event.source and provide // event.origin as the targetOrigin. event.source.postMessage("hi there yourself! the secret response " + "is: rheeeeet!", event.origin);} 安全问题:用于接收消息的任何事件监听器必须首先使用origin和source属性来检查消息的发送者的身份。 4. localStorage将接受到的message的data存入localStorage,同时可以将自己的localStorage作为信息发送出去。 12345678910111213141516171819202122232425262728293031//子窗口window.onmessage = function(e) { if (e.origin !== 'http://bbb.com') return; var payload = JSON.parse(e.data); switch (payload.method) { case 'set': localStorage.setItem(payload.key, JSON.stringify(payload.data)); break; case 'get': var parent = window.parent; var data = localStorage.getItem(payload.key); parent.postMessage(data, 'http://aaa.com'); break; case 'remove': localStorage.removeItem(payload.key); break; }};//父窗口var win = document.getElementsByTagName('iframe')[0].contentWindow;var obj = { name: 'Jack' };// 存入对象win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://bbb.com');// 读取对象win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");window.onmessage = function(e) { if (e.origin != 'http://aaa.com') return; // "Jack" console.log(JSON.parse(e.data).name);}; 四、Ajax同源政策规定,AJAX请求只能发给同源的网址,否则就报错。除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制。 JSONPWebSocketCORS 1. JSONP与服务器端进行跨域通信的常用方法,只能应用于GET请求。基本思想:通过添加一个script文件请求数据,服务器将数据放置在一个回调函数中。 1234567window.onload = function () { addScriptTag('http://example.com/ip?callback=foo');}//定义foo函数function foo(data) { console.log('Your public IP address is: ' + data.ip);}; 2. WebSocketWebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。WebSocket请求的头信息中有个origin字段,该字段规定了请求的请求源,服务器端可以根据这个字段判断是否接受请求。 3. CORSCORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。 参考: MDN window.postMessagehttps://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage http://www.techug.com/post/same-origin-policy.html]]></content>
<categories>
<category>web</category>
</categories>
<tags>
<tag>web</tag>
</tags>
</entry>
<entry>
<title><![CDATA[web语义化]]></title>
<url>%2F2017%2F05%2F06%2Fweb%E8%AF%AD%E4%B9%89%E5%8C%96%2F</url>
<content type="text"><![CDATA[web语义化其实是让大家按照一定的规范描述web内容,从而让机器能够更好的理解我们发布的内容,对内容进行处理与挖掘。同时,在团队开发的时候,使开发者们能够更好地互相理解。 ###一、语义化的构成网页的语义构成:元素(html标签)+属性+属性值(+文档结构)html网页类似于一个word文档,也要有标题,章节,图表等,每个元素及属性都表达不同的语义。 ####1. html标签的语义(1) sections元素article:独立的文档、页面、应用、站点,可以是一篇贴子、一篇文章、一条评论等。section:按主题内容分组,通常会有标题(heading)并非语义化的div使用时机:当你希望这个元素内容体现在文档的提纲中时使用nav:页面导航aside:侧边栏,表示与周围内容不太密切相关的内容h1~h6:各级标题header:用来描述最近父级区域的头部,一组介绍性描述或导航信息(目录/搜索框/logo/标题等),不影响文档提纲的生成footer:用来描述最近父级区域的尾部,一般介绍作者信息/相关文档/版权信息等,不影响文档提纲的生成address:代表与最近父级article或整个文档关联的联系人信息 (2) 分组内容p:段落,但不优先考虑使用,如果有其他语义更明确的标签则用其他标签如addresshr:html5中将它重定义为不同主题内容间的分隔符,区块内容之间不需要用hr来分隔pre:表示已排版的内容,如代码片段等blockquote:表示引用其他来源的内容,署名必须放在blockquote标签外,cite标签用来标示该引用来源的urlol/ul/li:有序/无序列表,ol下li元素的value属性表示该li的序号值 12345<ol> // 18. a <li value="18">a</li> // 20. b <li value="20">b</li> // 21. c <li>c</li></ol> dl/dt/dd:名值对的列表,一般用于术语定义表/元数据/FAQ等figure:一般用来表示插图/图表/照片/代码等,通常会有一个标题(figcaption)div:本身无语义,可以和class、lang、title等属性结合,为一系列连续的内容增加语义,不优先考虑使用main:文档的主内容/应用的核心功能,在文档中唯一出现 (3)文本级语义元素em: 表示侧重点的强调,在浏览器上一般渲染为斜体,根据em位置不同,文本语义可能不同,例如: 123<p><em>Bats</em> can fly.</p><p>Bats <em>can</em> fly.</p><p>Bats can <em>fly</em>.</p> strong: 表示内容的重要性,在浏览器上一般渲染为粗体,strong位置不同,文本本身含义不变i: 表示另一种叙述方式,如画外音/分类学名词/外来语/舞台指示/船名等等,建议与class/lang属性搭配使用b: 表示某种需要引起注意但又没有其他额外语义的内容,如摘要中的关键词/评价中的产品名称/文章的开篇内容等,建议与class搭配使用small: 通常是免责声明/许可证声明/注意事项等s: 表示不再准确或不再相关的内容,与del元素含义不同,渲染为带删除线的文字u:表示用非文本进行的标注的内容,如中文专名(人名、地名、朝代、国名、机构等)/拼写检查的错误内容等cite:引用的内容的标题(书/l论文/散文/电影/歌曲等)q:引用的来自其他来源的段内内容,这里cite属性表示该来源的url(blockquote是整段,q可以是段内ji即在p标签内),可以直接使用引号abbr:表示缩写,其title属性的值为全称,建议在第一次使用缩写词汇时用abbr+title属性dfn:表示一个术语的定义实例(使搜索引擎容易搜到特定术语)time:表示一个机器可读的时间,其datetime属性必须是预定义的几种时间格式之一,如果不含datetime属性,则会解析其文本内容值code:代码片段samp:计算机程序的输出kbd:用户输入的内容/按键ins/del:表示对当前文档内容进行的增添与修改,cite指向某个修改的说明文档的url,datetime属性表示修给发生的时间span:本身无语义,可以与class、lang属性结合track:为多媒体元素指定文本轨,其kind属性用来描述文本轨的类型(subtitles/captions/descriptions等) (4) 表格元素tablecaption:表格的标题,当table是外部figure元素的唯一子元素,应首选figcaptiontbody、thead、tfootcol、colgroup、trtd、th ####2. 全局属性id:标识符,不应依赖其语义处理相应元素class:应该命名为能描述元素内容的名称tilte:链接 - 描述目标信息;图片 - 版权/描述;引用 - 来源信息;交互元素 - 操作指南等lang:内容的语言 ####3. 元数据(1)head元素:里面包括一组元数据,title属性表示文档对外的标题(2)meta元素:name/http-equiv/charset。name属性决定种类,content属性表示内容 ####4. 链接link、a等(1)link元素:描述文档与其他资源的关系,必须包含rel和href属性(2)a元素:存在href时为超链接,缺少href时为链接占位符,也有rel属性 ###二、语义化的好处 ####1. 利于搜索引擎优化(SEO)各大搜索引擎如Google、Yahoo、Bing等约定对对 schema.org上所列出来的标签进行解析。网页上把不同的资源用搜索引擎容易识别的标签给标记出来,利于搜索引擎对资源进行分类,并在搜索结果中更好的呈现出来。搜索引擎根据语义标签能更快更准确的获取到信息,就能更快的展示给用户想要的信息,这就是它有利于搜索引擎优化的一个方面。 ####2. 清晰的页面结构让文档能在去除样式或样式丢失时也呈现出清晰的结构。 ####3. 利于机器识别屏幕阅读器等机器能够更好地识别含有语义的标签,这样对于某些特殊用户也更加方便。 ####4. 更好地处理在不同设备上的渲染使用语义标记可以确保手机、pad等设备以一种有意义的方式来渲染网页。 ####5. 利于团队开发和代码维护 ###语义化与常见SEO优化操作 head标签放网页的标题,每个页面的title不同。 meta keywords列举出几个重要的关键词。 meta description网页内容的高度概括。 每个页面只能出现一次H1标签,H2标签可以多次:H1权重很高,普遍认为仅次于title,一般资讯详情页的标题、商品详情页的标题,都放在H1里。 图片一定要添加alt属性,title属性可选:搜索引擎不认识图片上的内容,只能通过alt属性来判断,如果是商品列表页,所有商品都加了alt和title的话,容易造成堆砌关键词,所以我一般是只加alt属性。 换行标签只用来在文本间进行换行,标签间的换行通过margin等等。 搜索引擎抓取seo内容是从上到下,重要内容html代码放在最前面 搜索引擎看不懂js, 重要内容不要用js输出 尽量少使用iframe框架 谨慎使用display:none,搜索引擎会过滤掉这里面的内容 不断精简代码]]></content>
<categories>
<category>web</category>
</categories>
<tags>
<tag>语义化</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css position]]></title>
<url>%2F2017%2F05%2F01%2Fcss%20position%2F</url>
<content type="text"><![CDATA[position是用来定位的属性,其取值包括:static、relative、absolute、fixed、sticky static:默认值,该关键字指定元素使用正常的布局行为,即元素在文档流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。 相对定位relative:该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。 position:relative 未定义对 table-*-group, table-row, table-column, table-cell, table-caption 元素应用的效果。相对定位的元素并没有脱离文档流。 绝对定位absolute:不为元素预留空间,通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置。当这样的祖先元素不存在时,则相对于根级容器定位。 绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。 绝对定位的元素脱离了文档流。 若同时给定了left、right、top、bottom的值,会自动计算出元素的宽和高;若给定了width、height值,则以width、height值为宽高,忽略right和bottom的值,定位由left和top值而定(在direction 为 ltr的情况下)。 固定定位fixed:不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。 fixed 属性会创建新的层叠上下文。当元素祖先的 transform 属性非 none 时,相对元素则由viewport改为该祖先。 该定位方式常用于创建在滚动屏幕时仍固定在相同位置的元素。 固定定位的元素脱离了文档流。 其宽高和定位的取值方式同absolute一样。 粘性定位sticky(css3新增):效果类似于相对定位和固定定位的混合。它的定位取决于:1. 其在文档流中应该在的位置 2. 其最近的块级祖先元素的边界。 取值left或right,top或bottom,当元素距离父容器大于给定的(left、right、top、bottom)值时,为相对定位;当元素滚动距离父容器到达给定值时变为固定定位,之后会一直固定在这个距离不变。 元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于viewport来计算元素的偏移量。 当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky 对 table 元素的效果与 position: relative 相同。 须指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。 粘性定位的元素并不脱离文档流。 粘性定位常用于定位字母列表的头部元素。标示 B 部分开始的头部元素在滚动 A 部分时,始终处于 A 的下方。而在开始滚动 B 部分时,B 的头部会固定在屏幕顶部,直到所有 B 的项均完成滚动后,才被 C 的头部替代 定位取值除了static,每个定位方式都有left、right、top、right这四个取值。 当取值冲突时: 如果同时指定 top 和 bottom(非 auto),优先采用 top。 如果同时指定 left 和 right,若 direction 为 ltr(英语、汉语等),则优先采用 left;若 direction 为 rtl(阿拉伯语、希伯来语等),则优先采用 right。]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css盒子模型]]></title>
<url>%2F2017%2F04%2F20%2Fcss%E7%9B%92%E5%AD%90%E6%A8%A1%E5%9E%8B%2F</url>
<content type="text"><![CDATA[网页设计中常听的属性名:内容(content)、填充(padding)、边框(border)、边界(margin), CSS盒子模式都具备这些属性。这些属性我们可以用日常生活中的常见事物——盒子作一个比喻来理解,所以叫它盒子模式。css盒子模型有两种:W3C标准盒子模型(标准模式)和IE标准盒子模型(怪异模式) W3C标准盒子模型一个块的总宽度= width + margin(左右) + padding(左右) + border(左右) IE标准盒子模型一个块的总宽度= width + margin(左右)(即width已经包含了padding和border值) 怪异模式触发方式 怪异模式主要表现在IE内核的浏览器 不对doctype进行定义 设置box-sizing: border-box]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
</tags>
</entry>
<entry>
<title><![CDATA[瀑布流布局]]></title>
<url>%2F2017%2F04%2F19%2F%E7%80%91%E5%B8%83%E6%B5%81%E5%B8%83%E5%B1%80%2F</url>
<content type="text"><![CDATA[一般瀑布流的实现常见有三种方式: 传统的多列浮动 css3样式定义 js计算绝对布局 传统的多列浮动方式固定要展示的列数,每一列中间的数据作为一组单独计算,插入数据时分别插入不同列中。优点: 布局最为简单,一般只依赖与一个浮动布局 不需要知道内容的高度,所以当有图片未加载时也不影响 缺点: 只适用于特定的屏幕,当屏幕size变化时,无法动态实现列数的更改 拓展不易 css3实现方式利用css3中特有属性,在高级浏览器中实现瀑布流效果 优缺点优点: 直接使用css样式,最为简洁,不依赖于任何js 拓展方便,直接往容器内部添加内容即可 自适应,屏幕变化,布局也会变化 当各个item的宽度不一致时,这种方式也适用 像一些特殊的如固定的两列瀑布流也可以很方便实现(固定显示两列,每一列可以横着有多个item) 缺点: 需要高级浏览器支持(其实这个现在已经不算缺点了) 这种方式和普通瀑布流的原理有区别,不是分别往不同列中插入数据,而是先往一列中插入数据,达到一定高度后再往其它列中插入数据,有时候用这种方式会达不到预期效果(这个是比较关键的,这种方式有时候体验达不到预期) 实现方法css3中增加了一个新的属性:column,来实现等高的列的布局效果。该属性有column-width宽度,column-count数量等,并且能根据窗口自适应。css实现瀑布流分为两种效果,普通横向瀑布流与固定列数的瀑布流 普通横向瀑布流这种瀑布流方式常常用于和js绝对布局方式比较,但是虽然从显示上来说,效果差不多,但是从用户体验的角度讲,这个不符合平常的习惯(插入数据方式,js绝对布局是从左到右,css3是从上到下)css3实现等宽布局: 12345678910111213 .container { /*宽*/ -webkit-column-width: 200px; -moz-column-width: 200px; -o-colum-width: 200px; colum-width: 200px; /*间距*/ -webkit-column-gap: 10px; -moz-column-gap: 10px; -o-column-gap: 10px; column-gap: 10px;} 固定列数布局1234567891011 .container { -webkit-column-count: 3; -moz-column-count: 3;-o-column-count: 3; column-count:3; -webkit-column-gap: 10px; -moz-column-gap: 10px; -o-column-gap: 10px;column-gap: 10px; } js绝对布局实现方式利用js,动态计算元素的插入位置,利用绝对布局absolute进行定位,根据屏幕的不同可以动态调整。 优缺点优点: 便于拓展,方便数据的添加 自适应,屏幕变化,布局也会变化 缺点: 计算时需要知道内容高度,如果包含图片,需要等图片加载完毕再计算,否则会存在误差 各个item的宽度需要一致 实现方法实现等宽随机高度,瀑布流布局实现思路如下: 获取元素容器的总宽度allWith,每一个瀑布流元素的列宽度itemWidth(如果大于allwidth,会有一个默认值替代) 计算当前容器可以显示的列数 column Math.floor(allwidth/itemWidth) 向下取整 添加一个元素前,计算每一列当前的高度,寻找当前高度最小的列,然后根据列的序号k,确定item的left和top,left=k*itemWidth,top=当前列的高度,然后当前列插入这个元素,当前列的高度加上这个元素的高 所有元素插入完毕后,容器的高度会调整为最大列的高度 初始化就是先读取页面的所有元素,然后一个一个插入,加载更多就是在已有的元素基础上,插入新的元素计算]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
<tag>布局</tag>
</tags>
</entry>
<entry>
<title><![CDATA[三列布局、三栏式布局]]></title>
<url>%2F2017%2F04%2F18%2F%E4%B8%89%E5%88%97%E5%B8%83%E5%B1%80%E3%80%81%E4%B8%89%E6%A0%8F%E5%BC%8F%E5%B8%83%E5%B1%80%2F</url>
<content type="text"><![CDATA[两侧定宽,中间自适应浮动1. 利用calc()12345678.left, .right { float: left; width: 100px;}.center { float: left; width: calc(100% - 200px);} 2. center外侧增加一层12345678910111213 .left, .right { float: left; width: 100px;}.center { margin: 0 100px; background: #00f;}.center-wraper { float: left; width: 100%; margin: 0 -100px;} 绝对定位12345678910111213141516171819 .parent { position: relative; height: 100px;}.left, .right { position: absolute; width: 100px;}.left { left: 0;}.right { right: 0;}.center { position: absolute; left: 100px; right: 100px;} inline-block1. 利用calc()1234567891011121314 .parent { font-size: 0; } .left,.right,.center { display:inline-block; vertical-align: top; font-size: 16px;}.left, .right { width: 100px;}.center { width: calc(100% - 200px);} 2. center外侧加一层12345678910111213141516171819 .parent { font-size: 0; } .left, .right, .center-wraper { display:inline-block; vertical-align: top; font-size: 16px;}.left, .right { width: 100px;}.center-wraper { width: 100%; margin: 0 -100px;}.center { margin:0 100px; background: #00f;} table1234567891011 .parent { display: table; width: 100%; table-layout: fixed;} .left, .right, .center { display:table-cell;}.left, .right { width: 100px;} flex123456789 .parent { display: flex; }.left, .right { width: 100px;}.center { flex: 1;} grid1234.parent { display:grid; grid-template-columns:100px 1fr 100px; } 三栏式布局(圣杯、双飞翼)为了让中间的主要内容先加载,将main放到一个位置,left和right随后。 浮动1. 圣杯布局圣杯布局使用float、负margin和relative,不需要添加额外标签。.main元素设置padding,为两侧定宽元素留出位置。内容元素设置100%宽度,占据中间位置。而两侧定宽元素通过设置负margin和relative的偏移属性配合,到达相应位置。缺点: 并没有实现等高布局;使用了相对定位,扩展性不好。如果想高度保持一致可以给left main right都加上min-height 12345678910111213141516171819202122232425262728//html结构<div class='parent'> <div class='main'>main</div> <div class='left'>left</div> <div class='right'>right</div></div>//css.parent { padding: 0 100px; overflow: hidden;}.main{ width: 100%; float: left;}.left,.right{ float: left; width: 100px; position: relative;}.left{ margin-left: -100%; left: -100px;}.right{ margin-left: -100px; right: -100px;} 2. 双飞翼布局双飞翼布局在圣杯布局的基础上,通过为.main元素外添加一层div结构,不使用相对定位。在.main元素上设置margin。两侧的定宽列通过负margin来占据.main元素的margin区域。 123456789101112131415161718192021222324252627282930313233//html结构<div class='parent'> <div class='main-wraper'> <div class='main'> main </div> </div> <div class='left'>left</div> <div class='right'>right</div></div>//css.parent { overflow: hidden;}.main-wraper { float: left; width: 100%;}.main{ margin: 0 100px;}.left, .right{ float: left; width: 100px; }.left{ margin-left: -100%; left: -100px;}.right{ margin-left: -100px; right: -100px;} 绝对定位可以设置子元素的top:0;bottom:0;使得所有子元素的高度都和父元素的高度相同,实现等高效果。 123456789101112131415161718192021.parent { position: relative; height: 100px;}.main{ left: 100px; right: 100px;}.left, .right, .main { position: absolute; top: 0; bottom: 0;}.left{ left: 0; width: 100px;}.right{ right: 0; width: 100px;} flexflex中的伸缩项目默认都拉伸为父元素的高度,可实现等高效果。通过改变伸缩项目的order,可以实现元素顺序调换的效果 1234567891011121314.parent { display: flex;}.left,.right { width: 100px;}.right{ order: 2;}.main{ order: 1; flex: 1; margin: 0 20px;} grid通过grid-area调换left,main,right的位置 12345678.parent { display:grid; grid-template-columns:100px 1fr 100px; grid-gap:20px;}.main { grid-area:1/2/2/3;}]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
<tag>布局</tag>
</tags>
</entry>
<entry>
<title><![CDATA[两列布局-左右两侧自适应]]></title>
<url>%2F2017%2F04%2F17%2F%E4%B8%A4%E5%88%97%E5%B8%83%E5%B1%80-%E5%B7%A6%E5%8F%B3%E4%B8%A4%E4%BE%A7%E8%87%AA%E9%80%82%E5%BA%94%2F</url>
<content type="text"><![CDATA[左侧由内容撑开,右侧撑满整个页面 浮动左侧浮动,右侧设置overflow 12345678 .left { float: left; background: #f00;}.right { background: #0f0; overflow: hidden;} flexie9以下不支持 123456.parent { display: flex;}.right { flex: 1;} gridie10以下不支持 1234.parent{ display:grid; grid-template-columns:auto 1fr;}]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
<tag>布局</tag>
</tags>
</entry>
<entry>
<title><![CDATA[两列布局-左侧定宽,右侧自适应]]></title>
<url>%2F2017%2F04%2F17%2F%E4%B8%A4%E5%88%97%E5%B8%83%E5%B1%80-%E5%B7%A6%E4%BE%A7%E5%AE%9A%E5%AE%BD%EF%BC%8C%E5%8F%B3%E4%BE%A7%E8%87%AA%E9%80%82%E5%BA%94%2F</url>
<content type="text"><![CDATA[浮动float浮动布局的缺点是浮动后会造成文本环绕、元素被覆盖等效果,以及需要及时清除浮动。如果各浮动元素的高度不同时,可能会出犬牙交错的效果. 1. 左侧浮动,右侧设置margin-left1234567.left: { float: left; width: 200px;}.right { margin-left: 200px;} 缺点1:IE6-浏览器下3像素bug,具体表现在右侧首行文字会向右偏移3px。解决办法是在left元素上设置margin-right: -100px缺点2:当右侧容器中有元素清除浮动时,会使该元素不与左侧浮动元素同行,从而出现文字下沉现象。 2. 左侧浮动,右侧设置margin且增加一层wraper为了解决上述方法中的两个缺点,可以通过增加结构来实现。右侧增加一层wraper并设置浮动,且wraper宽度必须设置为100%,若不设置,float后元素的宽度会由内容撑开,同时还需设置负margin值,使得两列元素在同一行。 123456789101112 .left { float: left; width: 200px;}.right { margin-left: 200px;}.right-wraper { float: left; margin-left: -200px; width: 100%;} 3. 使用css3中的calc()12345678.left { float: left; width: 200px;}.right { float: left; width: calc(100% - 200px);} 4. 左侧浮动,右侧设置overflow设置overflow为hidden可以触发BFC,阻止浮动造成的后果。 1234567.left: { float: left; width: 200px;}.right { overflow: hidden;} 绝对定位absolute布局的缺点是由于父元素需要设置为relative,且子元素设置为absolute,所以父元素的高度并不是由子元素撑开的,需要单独设置。1. 左侧绝对定位,右侧设置margin-left2. 左侧绝对定位,右侧绝对定位 123456789101112131415161718.parent { position: relative; height: 200px;}.left: { position: absolute; left: 0; width: 200px;}.right { margin-left: 200px;}或.right { position: absolute; left: 200px; right: 0;} inline-block使用inline-block的主要缺点是需要设置垂直对齐方式vertical-align,则需要处理换行符解析成空格的间隙问题。解决间隙:一般将父级元素的font-size设为0,然后在子元素中将font-size设为默认大小。 1. 利用calc()123456789101112131415 .parent { font-size: 0; } .left { display: inline-block; width: 200px; font-size: 16px; vertical-align: top;}.right { display: inline-block; width: calc(100% - 200px); font-size: 16px; vertical-align: top;} 2. 右侧外层wraper123456789101112131415161718192021 .parent { font-size: 0; } .left { position: relative; display: inline-block; width: 200px; font-size: 16px; vertical-align: top;}.right-wraper { display: inline-block; margin-left: -200px; width: 100%; font-size: 16px; vertical-align: top;}.right { margin-left: 200px; } table使用table布局的缺点是元素被设置为table后,内容撑开宽度,所以需要设置width:100%。若要兼容IE7-浏览器,需要改为结构。由于table-cell元素无法设置margin,若需要在元素间设置间距,需要增加结构。 123456789101112 .parent { display: table; table-layout: fixed; width: 100%;}.left { display: table-cell; width: 200px;}.right { display: table-cell;} flexflex弹性盒模型是非常强大的布局方式。但由于其性能消耗较大,适合于局部小范围的布局.IE9以下不支持 123456789 .parent { display: flex;}.left { width: 200px;}.right { flex: 1;} gridIE10以下不支持 12345 .parent { display: grid; grid-template-columns: 200px 1fr; background: gray;}]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
<tag>布局</tag>
</tags>
</entry>
<entry>
<title><![CDATA[浏览器渲染路径]]></title>
<url>%2F2017%2F04%2F11%2F%E6%B5%8F%E8%A7%88%E5%99%A8%E6%B8%B2%E6%9F%93%E8%B7%AF%E5%BE%84%2F</url>
<content type="text"><![CDATA[当浏览器从服务器端获取到html文件后,要对其进行渲染,以像素点的方式在屏幕中绘制出页面的内容,经过的那些步骤叫关键渲染路径。关键渲染路径分为六步: 创建DOM树 -> 创建CSSOM树 -> 执行脚本 -> 生成渲染树 -> 生成布局 -> 绘制 创建DOM树DOM(文档对象模型)树是HTML页面完全解析后的一种表示方式。从根元素开始,页面上每个元素或者文本都会创建一个对应的节点。每个节点都包含了这个元素的所有属性,并且嵌套在元素内的元素会被解析成外层元素对应的节点的子节点。HTML可以部分执行并显示,也就是说,浏览器并不需要等待整个HTML全部解析完毕才开始显示页面。但是,其他的资源有可能阻塞页面的渲染,比如CSS,JavaScript等。 创建CSSOM树CSSOM(CSS对象模型)树是对附在DOM结构上的样式的一种表示方式。它与DOM树的呈现方式相似,只是每个节点都带上样式 ,包括明确定义的和隐式继承的。CSS是一种渲染阻塞资源(render blocking resource),它需要完全被解析完毕之后才能进入生成渲染树的环节。CSS并不像HTML那样能执行部分并显示,因为CSS具有继承属性, 后面定义的样式会覆盖或者修改前面的样式。如果我们只使用样式表中部分解析好的样式,我们可能会得到错误的页面效果。标签link rel=”stylesheet”>接受media属性,该属性规定了此处的CSS文件适用于哪种设备。如果我们有个设备属性值为orientation: landscape(横向)的样式,当我们竖着浏览页面的时候,这个CSS资源是不会起作用的,也就不会阻塞渲染的过程了。CSS也会阻塞脚本(js)运行。 执行javaScriptJavaScript是一种解析阻塞资源(parser blocking resource),它能阻塞HTML页面的解析。当页面解析到标签,不管脚本是內联的还是外联,页面解析都会暂停,转而加载JavaScript文件(外联的话)并且执行JavaScript。这也是为什么如果JavaScript文件有引用HTML文档中的元素,JavaScript文件必须放在那个元素的后面。为了避免JavaScript文件阻塞页面的解析,我们可以在标签上添加async属性,使得JavaScript文件异步加载(异步加载就是在执行过程同时加载,这里说的是在解析html页面时,同时加载js文件,从而使得js文件不阻塞页面解析)。 生成渲染树渲染树是DOM和CSSOM的结合,是最终能渲染到页面的元素的树形结构表示。也就是说,它包含能在页面中最终呈现的元素,而不包含那些用CSS样式隐藏的元素,比如带有display:none;属性的元素。 生成布局对渲染树上的每个元素,计算它的坐标,称之为布局。浏览器采用一种流方法,布局一个元素只需通过一次,但是表格元素需要通过多次。布局决定了视口的大小,为CSS样式提供了依据,比如百分比的换算或者视口的总像素值。视口大小是由meta标签的name属性为viewport的内容设置所决定的,如果缺少这个标签,默认的视口大小为980px。 绘制页面上可见的内容就会转化为屏幕上的像素点。绘制过程所需要花费的时间取决于DOM的大小以及元素的CSS样式。有些样式比较耗时,比如一个复杂的渐变背景色比起简单的单色背景需要更多的时间来渲染。 当用户与网页交互,或者脚本程序改动修改网页时,前文提到的一些操作将会重复执行,因为网页的内在结构已经发生了改变。]]></content>
<categories>
<category>web</category>
</categories>
<tags>
<tag>web</tag>
</tags>
</entry>
<entry>
<title><![CDATA[浮动及其清除方法]]></title>
<url>%2F2017%2F04%2F11%2Fclearfix%2F</url>
<content type="text"><![CDATA[浮动元素会脱离文档流并向左/向右浮动,直到碰到父元素或者另一个浮动元素。浮动可以理解为让某个div元素脱离标准流,漂浮在标准流之上,和标准流不是一个层次。 浮动的特征: 浮动会脱离文档:不影响普通元素的布局 浮动可以内联排列:浮动元素会向左或右浮动,直到碰到另一个浮动元素,这是浮动可以内联排列的原因;如果每个浮动元素高度不一样,会出现‘卡住’的情况 浮动会导致父元素高度坍塌 清除浮动主要有两种方式,clear清除浮动和BFC清除浮动 clear清除浮动clear官方定义如下: clear : none | left | right | both 取值: none : 默认值。允许两边都可以有浮动对象 left : 不允许左边有浮动对象 right : 不允许右边有浮动对象 both : 两边都不允许有浮动对象 clear清除浮动只能影响使用clear的元素本身,不能影响其他元素 要解决父元素高度塌陷问题,需通过在别的元素上清除浮动来实现,而不是在浮动元素上。 123456<div class='container'> <div class='float'></div> <div class='float'></div> <div class='float'></div> <div style='clear:both'></div></div> clear清除浮动的通用方法:利用:after伪元素来实现方法1: 12345678910.clearfix { content: '.'; display: block, height: 0; visibility: hidden; clear: both;}.clearfix { *zoom: 1; } 1) display:block 使生成的元素以块级元素显示,占满剩余空间;2) height:0 避免生成内容破坏原有布局的高度。3) visibility:hidden 使生成的内容不可见,并允许可能被生成内容盖住的内容可以进行点击和交互;4)通过 content:”.”生成内容作为最后一个元素,至于content里面是点还是其他都是可以的,firefox直到7.0 content:”” , 仍然会产生额外的空隙;5)zoom:1 触发IE hasLayout。通过分析发现,除了clear:both用来闭合浮动的,其他代码无非都是为了隐藏掉content生成的内容,这也就是其他版本的闭合浮动为什么会有font-size:0,line-height:0。 更好的方法1:相对于空标签闭合浮动的方法代码似乎还是有些冗余,通过查询发现Unicode字符里有一个“零宽度空格”,也就是U+200B ,这个字符本身是不可见的,所以我们完全可以省略掉 visibility:hidden了。 123456789.clearfix { content: '200B'; display: block, height: 0; clear: both;}.clearfix { *zoom: 1; } 更好的方法2: 12345678910111213 //全浏览器通用的clearfix方法,引入zoom以支持IE6/7 //加入:before以解决现代浏览器上边距折叠的问题.clearfix:before,.clearfix:after { display: table; content: '',}.clearfix:after { clear: both;}.clearfix { *zoom: 1;} 上面的方法用到了before伪元素,很多人对这个有些迷惑,到底我什么时候需要用before呢?为什么方案一没有呢?其实它是用来处理margin边距重叠的,由于内部元素 float 创建了BFC,导致内部元素的margin-top和 上一个盒子的margin-bottom 发生叠加。如果这不是你所希望的,那么就可以加上before,如果只是单纯的闭合浮动,after就够了。 BFC清除浮动(不推荐使用)BFC容器是一个隔离的容器,和其他元素互不干扰;所以我们可以用触发两个元素的BFC来解决垂直边距折叠问题。BFC可以包含浮动(引起元素高度重新计算),通常用来解决浮动父元素高度坍塌的问题。BFC触发方式可以给父元素添加以下属性来触发BFC: 设置父元素float overflow为 hidden | auto | scroll display为 table-cell | table-caption | inline-block | flex | inline-flex position为 absolute | fixed fieldset元素 可以给父元素设置overflow:auto来简单的实现BFC清除浮动,要兼容IE还需要加上zoom,或者设置overflow:hidden(对SEO不友好且元素阴影或下拉菜单等会被截断)可以设置父元素也浮动,但是会影响父元素相邻的元素,我们不可能一直浮动到body 浮动的适用场景文字环绕效果浮动最初就是为了实现文字环绕效果而诞生的 页面布局浮动可以实现常规的多列布局(更推荐使用inline-block)以及自适应的多列布局 多个元素内联排列浮动可以实现类似inline-block的排列,比如菜单多个元素内联排列。但推荐使用inline-block。]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
</tags>
</entry>
<entry>
<title><![CDATA[排序算法总结]]></title>
<url>%2F2017%2F03%2F28%2F%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95%E6%80%BB%E7%BB%93%2F</url>
<content type="text"><![CDATA[排序分为内部排序和外部排序,内部排序常见算法有:冒泡排序、插入排序、选择排序、快速排序、归并排序、希尔排序、堆排序等,总结如下表 时间复杂度 排序方法平均情况最坏情况最好情况空间复杂度稳定性 冒泡排序O(n^2)O(n^2)O(n)O(1)稳定 直接插入排序O(n^2)O(n^2)O(n)O(1)稳定 简单选择排序O(n^2)O(n^2)O(n^2)O(1)不稳定 快速排序O(nlogn)O(n^2)O(nlogn)O(logn)不稳定 归并排序O(nlogn)O(nlogn)O(nlogn)O(n)稳定 希尔排序O(nlogn)O(nlogn)O(1)不稳定 堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不稳定 基数排序O(d(n+r))O(d(n+r))O(d(n+r))O(n+r)稳定 稳定性,就是有两个相同的元素,排序先后的相对位置是否变化稳定性的好处:排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。基数排序就 是这样,先按低位排序,逐次按高位排序,低位相同的元素其顺序再高位也相同时是不会改变的。 1. 冒泡排序把小的元素往前调或者把大的元素往后调。每次遍历都与相邻的元素比较或交换,通过一趟排序把最大(最小)的数冒出来;稳定性分析:如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。具体实现: 1234567891011121314151617181920212223242526272829303132//没有优化的冒泡排序public void BubbleSort(int arr[]) { int length = arr.length; int temp = 0; for(int i = 0; i < length - 1; i++) { for(int j = 0; j < length - i - 1; j++) { if(arr[j] > arr[j+1]) { temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } }}//加入flag标志位,若flag=0,说明整个序列已排好序public void BubbleSort2(int arr[]) { int flag = 0; for(int i = 0; i < length - 1; i++) { flag = 0; for(int j = 0; j < length - i - 1; j++) { if(arr[j] > arr[j+1]) { temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; flag = 1; } } if(flag == 0) { break; } }} 2. 直接插入排序在一个已经有序的小序列的基础上,一次插入一个元素。刚开始,这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比较,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。稳定性分析:从上述排序过程中可以看出它是稳定的。扩展: 二分插入排序:每次插入时,从中间位置开始比较,每次比较缩小一半范围。这种方法最坏情况比直接插入好,最好情况比直接插入差。直接插入排序实现: 12345678910111213public void Insertsort(int a[], int n) { int i, j; for (i = 1; i < n; i++) { if (a[i] < a[i - 1]) { int temp = a[i]; for (j = i - 1; j >= 0 && a[j] > temp; j--) a[j + 1] = a[j]; //后移 a[j + 1] = temp; } }} 3. 简单选择排序首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置;然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。稳定性分析:举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。具体实现: 1234567891011121314151617181920public void selectionSort(int[] list) {// 需要遍历获得最小值的次数// 要注意一点,当要排序 N 个数,已经经过 N-1 次遍历后,已经是有序数列 for (int i = 0; i < list.length - 1; i++) { int temp = 0; int index = i; // 用来保存最小值得索引 // 寻找第i个小的数值 for (int j = i + 1; j < list.length; j++) { if (list[index] > list[j]) { index = j; } } // 将找到的第i个小的数值放在第i个位置上 temp = list[index]; list[index] = list[i]; list[i] = temp; System.out.format("第 %d 趟:\t", i + 1); printAll(list); }} 4. 希尔排序也叫递减增量排序,是插入排序的一种更高效的改进版本。希尔排序是不稳定的排序算法。 5. 快速排序快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。步骤为:(1)从序列中挑出一个元素,作为”基准”(pivot).(2)把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作。(3)对每个分区递归地进行步骤1~3,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。稳定性分析:在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法。具体实现如下: 12345678910111213141516171819202122232425262728293031public class QuickSort { public static int partition(int left, int right, int a[]) { int key = a[left]; while(left < right) { while(left < right && a[right] >= key) { right--; } a[left] = a[right]; while(left < right && a[left] < key) { left++; } a[right] = a[left]; } a[left] = key; return left; } public static void quicksort(int left, int right, int a[]) { if(left < right) { int middle = partition(left, right, a); quicksort(left, middle-1, a); quicksort(middle+1, right, a); } } public static void main(String[] args) { int[] a = {49, 38, 65, 97, 76, 13, 27, 49}; quicksort(0, a.length-1, a); for(int i = 0, len = a.length; i < len; i++) { System.out.print(a[i]+" "); } }} 6.归并排序将待排序序列R[0…n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。归并排序其实要做两件事:(1)“分解”——将序列每次折半划分。(2)“合并”——将划分后的序列段两两合并后排序。合并过程:设两个有序序列分别为 R[low, mid] 和 R[mid+1, high]先将他们合并到一个局部的暂存数组R2中,合并完成后再将R2复制回R中。为了方便描述,我们称 R[low, mid] 第一段,R[mid+1, high] 为第二段。每次从两个段中取出一个记录进行关键字的比较,将较小者放入R2中。最后将各段中余下的部分直接复制到R2中。经过这样的过程,R2已经是一个有序的序列,再将其复制回R中,一次合并排序就完成了具体实现: 123456789101112131415161718192021222324252627282930313233343536373839404142public class mergeSort { public static void merge(int low, int mid, int high, int[] arr) { int[] tempArr = new int[arr.length]; int left = low; int center = mid + 1; int newLow = low; while(low <= mid && center <= high) { if(arr[low] <= arr[center]) { tempArr[left++] = arr[low++]; } else { tempArr[left++] = arr[center++]; } } while(low <= mid) { tempArr[left++] = arr[low++]; } while (center <= high) { tempArr[left++] = arr[center++]; } while (newLow <= high) { arr[newLow] = tempArr[newLow]; newLow++; } } public static void mergesort(int low, int high, int[] arr) { if(low >= high) return; int mid = (low + high) / 2; mergesort(low, mid, arr); mergesort(mid+1, high, arr); merge(low, mid, high, arr); } public static void main(String[] args) { int[] array = {1, 3, 4, 2, 6, 8, 5, 9, 7}; mergesort(0, array.length-1, array); for(int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); } }} 7.堆排序二叉堆是完全二叉树或者是近似完全二叉树。二叉堆满足二个特性:1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>排序算法</tag>
</tags>
</entry>
<entry>
<title><![CDATA[阿里实习内推一面]]></title>
<url>%2F2017%2F03%2F23%2F%E9%98%BF%E9%87%8C%E5%AE%9E%E4%B9%A0%E5%86%85%E6%8E%A8%E4%B8%80%E9%9D%A2%2F</url>
<content type="text"><![CDATA[1.html5中sessionStorage和localStoragesessionStorage 和 localStorage 是 HTML5 Web Storage API 提供的,可以方便的在 web 请求之间保存数据。有了本地数据,就可以避免数据在浏览器和服务器间不必要地来回传递。sessionStorage、 localStorage 、 cookie 都是在浏览器端存储的数据,其中 sessionStorage 的概念很特别,引入了一个“浏览器窗口”的概念。 sessionStorage 是在同源的同窗口(或 tab )中,始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后, sessionStorage 即被销毁。同时“独立”打开的不同窗口,即使是同一页面, sessionStorage 对象也是不同的。cookies会发送到服务器端,其余两个不会。 Microsoft 指出 Internet Explorer 8 增加 cookie 限制为每个域名 50 个,但 IE7 似乎也允许每个域名 50 个 cookie 。 Firefox 每个域名 cookie 限制为 50 个。 Opera 每个域名 cookie 限制为 30 个。 Firefox 和 Safari 允许 cookie 多达 4097 个字节,包括名( name )、值( value )和等号。 Opera 许 cookie 多达 4096 个字节,包括:名( name )、值( value )和等号。 Internet Explorer 允许 cookie 多达 4095 个字节,包括:名( name )、值( value )和等号。 区别: - Cookie 每个域名存储量比较小(各浏览器不同,大致 4K ) 所有域名的存储量有限制(各浏览器不同,大致 4K ) 有个数限制(各浏览器不同) 会随请求发送到服务器 - LocalStorage 永久存储 单个域名存储量比较大(推荐 5MB ,各浏览器不同) 总体数量无限制 - SessionStorage 只在 Session 内有效 存储量更大(推荐没有限制,但是实际上各浏览器也不同) sessionStorage和localStorage用法 setItem( key, value) getItem( key ) removeItem(key) clear() 用.和[]获取键值 storage事件: 当键值改变或者clear的时候,就可以触发 2.纯css实现三角形border属性四边交集的地方其实是一个梯形状,当div的width、height都为0时,四边相交会发展成三角形。具体看http://www.cnblogs.com/jack-chan/p/5024129.html 3.在IE下实现一个高为1px的divIE6及以下中,div默认高度不低于它字体的行高,一般最低高度达到18px,所以要设div高度小于18px有两种方法:1:div{ height: 1px; overflow: hidden; } 推荐,这个高度最准确2: div{ height: 1px; font-size: 0; }, 这个还是会有误差 4.用过哪些css的伪元素,用在什么地方css中伪类有 常用伪类 :link,:visited,:hover,:active 结构性伪类 :first-child(li:first-child所有元素中的第一个li元素),:first-of-type(在父容器内其所有种类元素的第一个元素), :last-child, :last-of-type, :not, :nth-child(n), :nth-last-child(n), :nth-of-type(n), :nth-last-of-type(n), :only-child(只有一个孩子的父元素), :only-of-type(指定一个元素没有特殊类型的兄弟元素), :target(如article具有target的ID,当浏览器中的URL以#target结束时,其将会被指定) 验证性伪类 :checked, :default, :disabled, :empty, :enabled, :in-range, :out-of-range, :indeterminate(输入元素没有被选择的元素,如单选按钮或复选框,未选中或页面加载后未选中的元素), :valid, :invalid, :required, :optional(表单中没有被required的输入区域), :read-only, :read-write, :scope, :dir(ltr/rtl),:lang(l)(匹配一个元素的语言与HTML属性中的lang=”l”), :root(文档中最高级父元素), :fullscreen(指定元素在全屏模式下显示) css中伪元素有(css3规定用双冒号表示伪元素,以与伪类进行区分,除IE8及以下不支持外,全部浏览器都支持) :before, :after, ::backdrop(经常和:fullscreen伪类结合使用改变最大化屏幕的背景颜色,必须使用双冒号), :first-letter, :first-line, ::selection(用于文档中样式被突出显示的部分,基于Gecko的浏览器需要添加版本前缀: ::-moz-selection, 仅仅在一个规则中使用前缀或者不使用前缀是不起作用的。我们需要声明两个单独的规则), ::placeholder(这个伪元素还不是标准的一部分,它的实现可能还会有改变,所以使用时需要注意)参考:http://www.w3cplus.com/css/an-ultimate-guide-to-css-pseudo-classes-and-pseudo-elements.html 5.实现两个div各占50%的宽度flex, grid布局]]></content>
<categories>
<category>面试</category>
</categories>
<tags>
<tag>面试</tag>
</tags>
</entry>
<entry>
<title><![CDATA[flex布局基本语法]]></title>
<url>%2F2017%2F03%2F15%2Fflex%E5%B8%83%E5%B1%80%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95%2F</url>
<content type="text"><![CDATA[浏览器支持:chrome21+,Opera12.1+,Firefox22+,Safari6.1+,IE10+任何一个容器,包括行内元素都可以使用flex布局(display:flex/inline-flex)。Webkit内核的浏览器(ios8以下)必须加上-webkit前缀(display:-webkit-flex)。flex布局中,子元素的float,clear,vertical-align属性会失效。 flex布局基本概念flex布局的元素称为flex容器(flex-container),它所有的子元素自动成为容器成员(flex-item),容器存在两根轴:水平的主轴和垂直的交叉轴,都以边框为起点。flex-item默认沿主轴排列,单个item的主轴空间(默认为宽)称作main size,交叉轴空间(默认为高)称作cross size flex容器的属性共 flex-direction/flex-wrap/flex-flow/justify-content/align-items/align-content 6个属性 1.flex-direction定义主轴方向(item排列方向)flex-direction:row | row-reverse | column | column-reverserow:水平方向,默认起点为左边;column:垂直方向,默认起点为上边 2.flex-wrap默认所有item在一行显示,这个属性决定是否换行显示flex-wrap:nowrap | wrap | wrap-reversenowrap不换行;wrap换行,第一行在上边;wrap-reverse换行,第一行在下边 3.flex-flow是flex-direction和flex-wrap属性的简写形式,默认值是row nowrap 4.justify-content定义item在主轴上的对齐方式justify-content:flex-start | flex-end | center | space-between | space-aroundflex-start主轴起点对齐;flex-end主轴终点对齐;center居中;space-between两端对齐,item之间有间隔;space-around每个item两侧的间隔相等,item之间的间隔比与边框的间隔大一倍 5.align-items定义item在交叉轴上的对齐方式align-items:flex-start | flex-end | center | baseline | stretchflex-start交叉轴起点对齐;flex-end交叉轴终点对齐;center居中;baseline与item的第一行文字的基线对齐;stretch(默认值)若item未设置高度或高度设置为auto,将占满整个容器的高度 6.align-content定义多根轴线(多行)的对齐方式,如果items只有一条轴线,该属性不起作用align-content:flex-start | flex-end | center | space-between | space-around | stretchflex-start与交叉轴起点对齐;flex-end与交叉轴终点对齐;center与交叉轴中点对齐;space-between交叉轴两端对齐,轴线之间间隔平均分布;space-around每根轴线两侧的间隔都相等;stretch(默认)占满整个交叉轴 item的属性共 order| flex-grow | flex-shrink | flex-basis | flex | align-self 6个属性 1.order定义item的排列顺序,数值越小,排列越前,默认是0order:整数; 2.flex-grow定义如果存在剩余空间,item的放大比例。默认为0:存在剩余空间,也不放大flex-grow:数字; 3.flex-shrink定义了item的缩小比例,默认为1:如果空间不足,项目将会缩小flex-shrink:数字;如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。 4.flex-basis定义了在分配多余空间之前,item占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。flex-basis:数值 | auto; 5.flexflex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。flex:none | auto | [flex-grow flex-shrink?|| flex-basis]auto(1 1 auto),none(0 0 auto)建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。 6.align-self允许单个item与其他item有不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。align-self:auto | flex-start | flex-end | center | baseline | stretch; 参考:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
<tag>css3</tag>
</tags>
</entry>
<entry>
<title><![CDATA[css元素居中总结]]></title>
<url>%2F2017%2F03%2F12%2Fcss%E5%85%83%E7%B4%A0%E5%B1%85%E4%B8%AD%E6%80%BB%E7%BB%93%2F</url>
<content type="text"><![CDATA[水平居中1.inline或inline-*的元素设块级父元素text-align为center,对inline,inline-block,inline-table,inline-flex等元素都起作用。 2.一个block元素(1)设定元素宽度,margin-left和margin-right为auto即可。(2)设定父元素position:relative,子元素absolute 1234567.center { position: absolute; top: 0; left: 50%; margin-left: center的width; //或transform: translate(-50%, 0);} 没有float:center,我们可以用伪元素实现一个图片居中,两边段落环绕的效果,具体看https://www.zybuluo.com/mdeditor#691644 3.多个block元素(1) 多个元素在一行显示,且居中,设要居中元素为display:inline-block(inline-block元素之间会有默认空隙,去除方法:)或设其父元素为flex布局 1234.parent { display: flex; justify-centent: center;} (2) 多个元素各占一行显示的方法参考上面2 垂直居中1.inline或inline-*的元素(1) 一行显示:父元素内padding-top和padding-bottom相等 或者是 设置父元素line-height和height相等(2) 多行显示:1.父元素的父元素display:table,父元素display:table-cell,vertical-align:center2.父元素设为flex布局,且有定高(px,%等) 123456.center_parent { display: flex; flex-direction: column; justify-content: center; height: 400px;} 3.利用伪元素 1234567891011121314.parent { position: relative;}.parent:before { content: ""; display: inline-block; height: 100%; width: 1%; vertical-align: middle;}.parent p { display: inline-block; vertical-align: middle;} 2.block元素(1) 知道元素的高度:元素相对父元素top:50%,margin-top:-width/2(2) 不知道元素的高度:1⃣️ 元素相对父元素top:50%,transform:translateY(-50%)2⃣️ flex布局:父元素flex-direction:column;justify-content:center; 水平和垂直居中(1) 知道元素高度和宽度 123456789101112.parent { position: relative;}.child { width: 300px; height: 100px; padding: 20px; position: absolute; top: 50%; left: 50%; margin: -70px 0 0 -170px;} (2) 不知道元素高度和宽度 123456.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);} (3) 用flex布局 12345.parent { display: flex; justify-content: center; align-items: center;} 参考:https://css-tricks.com/centering-css-complete-guide/]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
</tags>
</entry>
<entry>
<title><![CDATA[伪元素实现图片居中,文字环绕效果]]></title>
<url>%2F2017%2F03%2F10%2F%E4%BC%AA%E5%85%83%E7%B4%A0%E5%AE%9E%E7%8E%B0%E5%9B%BE%E7%89%87%E5%B1%85%E4%B8%AD%EF%BC%8C%E6%96%87%E5%AD%97%E7%8E%AF%E7%BB%95%E6%95%88%E6%9E%9C%2F</url>
<content type="text"><![CDATA[利用伪元素的浮动实现html结构如下: 123456789101112131415<html> <body> <div class="wrap"> <img id="logo" src="#"> <div id="left"> <p>content</p> <p>content</p> </div> <div id="right"> <p>content</p> <p>content</p> </div> </div> </body></html> 基本样式如下,假设图片大小为250px*250px: 123456789101112131415161718192021222324.wrap { position: relative; width: 80%; margin: 20px auto; //居中}#logo { position: absolute; top: 0; left: 50%; margin-left: -125px; //不知道宽度的情况,transform: translate(-50%, 0); }#left: before, #right: before { content: ""; width: 125px; height: 250px;}#left:before { float: right;}#right:before { float: left;} 参考:https://css-tricks.com/float-center/]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
</tags>
</entry>
<entry>
<title><![CDATA[关于margin collapse]]></title>
<url>%2F2017%2F02%2F15%2Ffloat%26margin%20collapse%2F</url>
<content type="text"><![CDATA[使用下面的例子来说明: ```css <div class="sibling">sibling</div> <div class="container clearfix"> <div class="div1">div1</div> <div class="div2">div2</div> </div> .container { background: #000; margin-bottom: 20px; } .sibling { margin-bottom: 20px; width: 100%; height: 30px; background: #00f; } .div1 { width: 50px; height: 80px; float: left; background: #0f0; } .div2 { margin-top: 80px; width: 200px; height: 50px; background: #ff0; } .clearfix:after { content: ""; display: table; clear: both; } .clearfix {zoom:1;} ```css 1.因为不是很清楚margin collapse的情况,就看了MDN上关于它的说明 Margin collapsing occurs in three basic cases: Adjacent siblings: The margins of adjacent siblings are collapsed (except when the later sibling needs to be cleared past floats). 第一种情况是指相邻两个元素上下margin会合并,这种情况要排除第二个元素使用了清除浮动的情况(例子等弄明白后再补充) 2. Parent and first/last child: If there is no border, padding, inline content, or clearance to separate the margin-top of a block from the margin-top of its first child block, or no border, padding, inline content, height, min-height, or max-height to separate the margin-bottom of a block from the margin-bottom of its last child, then those margins collapse. The collapsed margin ends up outside the parent. 第二种情况是指块级元素与其第一个非浮动的块级子元素的margin-top,及与其最后一个非浮动的块级子元素的margin-bottom可能发生合并。浮动的元素不会与其他元素发生margin collapse 这种情况要求元素与子元素之间没有如border、padding、inline子元素这样的间隔。合并的margin最终可能跑到父元素外边去,下面是图例: 这里div2与父元素container的margin-top合并了,并跑到外边去了,且与sibling的margin-bottom合并了 注:clearfix不能加::before{display:table;}哦,加了后display:table会产生一个新的BFC,从而隔离了父元素和div2的margin,我就是没注意这个,测试了好久都没有效果。 所以,将div2的margin-top改为100px,再加上::before{ display:table;}后,div2的margin也在container里边了 3. Empty blocks:If there is no border, padding, inline content, height, or min-height to separate a block’s margin-top from its margin-bottom, then its top and bottom margins collapse. 这里是说空元素的margin-top和margin-bottom会互相重叠 4. 这些情况适用范围和负边距的情况 These rules apply even to margins that are zero, so the margin of a first/last child ends up outside its parent (according to the rules above) whether or not the parent’s margin is zero. 父元素的margin为0也适用 When negative margins are involved, the size of the collapsed margin is the sum of the largest positive margin and the smallest (most negative) negative margin. 当存在负的边距时,合并边距计算方法为:最大正边距与最小负边距(-10<-5)之和 参考资料 MDN: margin collapse 知乎上关于这个问题的回答]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css</tag>
</tags>
</entry>
</search>