-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
700 lines (535 loc) · 183 KB
/
atom.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
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Z World</title>
<link href="/atom.xml" rel="self"/>
<link href="http://zeligzhou.github.io/"/>
<updated>2017-07-22T09:41:32.000Z</updated>
<id>http://zeligzhou.github.io/</id>
<author>
<name>Zelig Zhou</name>
<email>zeligzhou@gmail.com</email>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>SVG服务器渲染</title>
<link href="http://zeligzhou.github.io/2017/07/22/svg-ssr/"/>
<id>http://zeligzhou.github.io/2017/07/22/svg-ssr/</id>
<published>2017-07-22T09:35:21.000Z</published>
<updated>2017-07-22T09:41:32.000Z</updated>
<content type="html"><![CDATA[<p>这个月几乎全部精力都在完成公司图表库的<em>Server-side Rendering</em>,摆脱echarts投入d3的怀抱,旨在毫秒级的性能改善和预备以后反爬虫的可能性,不过性能表现的提升还得跟踪一段时间才能得到毕竟准确的结果。</p>
<h3 id="Canvas和SVG的选择"><a href="#Canvas和SVG的选择" class="headerlink" title="Canvas和SVG的选择"></a>Canvas和SVG的选择</h3><p>Canvas似乎是现在的主流选择,Flipboard甚至不惜用Canvas代替DOM来改善交互,表现大家自有定论。但在服务器端渲染,Canvas不具备交互的条件,所以SVG是唯一的选择。</p>
<h3 id="虚拟DOM的那些事儿"><a href="#虚拟DOM的那些事儿" class="headerlink" title="虚拟DOM的那些事儿"></a>虚拟DOM的那些事儿</h3><p>其实在服务器端渲染需要解决的一个最大的问题,便是<em>虚拟DOM</em>的操作了。虚拟DOM这个概念最近肯定是耳熟能详,为什么浏览器里需要一个虚拟DOM——还不是嫌DOM操作慢。而服务器端也面临同样的问题,有PhantomJS和JSDOM这样的完全模拟出浏览器环境进行DOM操作,但性能完全不能如意啊。<br>个人在做这个SVG服务器渲染的时候一开始是使用JSDOM(D3官方推荐),但渲染一个折线图(X轴50个点以内)大约需要80ms以上。这样的速度我们来进行SSR就是得不偿失了。所以我尝试了好几种方案:</p>
<ul>
<li>cheerio:性能非常好,但仅仅提供简单的DOM树形结构,但不包含任何DOM方法,无法对节点进行操作。</li>
<li>minidom:提供了DOM2大部分方法,但仅限于HTML文档,缺少D3需要的createElementNS。</li>
<li>xmldom:提供了DOM2大部分方法,性能能够满足要求。但缺少D3需要的Selectors API。<br>于是我给xmldom打了一个补丁,叫<a href="https://www.npmjs.com/package/xmldom-qsa" title="xmldom-qsa" target="_blank" rel="external">xmldom-qsa</a>,让其DOM节点包含querySelector等方法。这样就可以在服务器端完美地调用各种D3的API进行SVG绘图。粗略测试它的性能大概是JSDOM的4倍左右。<a id="more"></a>
</li>
</ul>
<h3 id="JS-config和CSS-theme"><a href="#JS-config和CSS-theme" class="headerlink" title="JS config和CSS theme"></a>JS config和CSS theme</h3><p>在一个库里配置项总是最让我头疼的部分,配置项应该有什么,应该像什么。颜色主题是应该放CSS里还是放配置项里。在做package的时候反复验证了,最终样式还是交给CSS了,改起来容易啊。😊</p>
<h4 id="Node端配置项"><a href="#Node端配置项" class="headerlink" title="Node端配置项"></a>Node端配置项</h4><p>配置项还是参考了echarts的基本结构。但因为主题配色几乎由CSS包办了,所以省去了体积庞大的<code>font-size</code>和<code>color</code>这类样式配置。可以专注于数据啦!<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line">{ </div><div class="line"> <span class="attr">xAxis</span>:</div><div class="line"> { <span class="attr">type</span>: <span class="string">'time'</span>,</div><div class="line"> <span class="attr">data</span>:</div><div class="line"> [ <span class="number">20170524</span>,</div><div class="line"> <span class="number">20170525</span>,</div><div class="line"> ...]</div><div class="line"> },</div><div class="line"> <span class="attr">yAxis</span>:</div><div class="line"> { <span class="attr">type</span>: <span class="string">'points'</span>,</div><div class="line"> <span class="attr">data</span>: [ <span class="number">123</span>, <span class="number">345</span>, ... ]},</div><div class="line"> <span class="attr">tooltip</span>: { <span class="attr">pointIndex</span>: <span class="number">14</span> },</div><div class="line"> <span class="attr">series</span>:[</div><div class="line"> {</div><div class="line"> <span class="attr">name</span>: <span class="string">'票房'</span>,<span class="comment">//not required, if you need legend you should give it to me </span></div><div class="line"> color: <span class="string">'#010101'</span>, <span class="comment">//not required </span></div><div class="line"> data:[</div><div class="line"> { <span class="attr">yValue</span>: <span class="number">3160</span>,</div><div class="line"> <span class="attr">tooltip</span>: <span class="string">'2017-06-22 3160'</span>,</div><div class="line"> <span class="attr">xValue</span>: <span class="number">20170524</span> },</div><div class="line"> { <span class="attr">yValue</span>: <span class="number">7556</span>,</div><div class="line"> <span class="attr">tooltip</span>: <span class="string">'2017-06-23 7556'</span>,</div><div class="line"> <span class="attr">xValue</span>: <span class="number">20170525</span> }</div><div class="line"> ]},</div><div class="line"> {<span class="attr">data</span>:[</div><div class="line"> { <span class="attr">yValue</span>: <span class="number">60000</span>,</div><div class="line"> <span class="attr">tooltip</span>: <span class="string">'2017-06-22 6'</span>,</div><div class="line"> <span class="attr">xValue</span>: <span class="number">20170524</span> },</div><div class="line"> { <span class="attr">yValue</span>: <span class="number">80000</span>,</div><div class="line"> <span class="attr">tooltip</span>: <span class="string">'2017-06-23 8'</span>,</div><div class="line"> <span class="attr">xValue</span>: <span class="number">20170525</span> }</div><div class="line"> ]}</div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>这样是不是很好,服务器就应该尽量只关心数据对吧。</p>
<h4 id="浏览器内的交互"><a href="#浏览器内的交互" class="headerlink" title="浏览器内的交互"></a>浏览器内的交互</h4><p>当然,事件绑定还是需要浏览器来完成,所以也给出了比较简单的浏览器配置项。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//after import client/js/chart.js </span></div><div class="line"><span class="keyword">var</span> setting = {</div><div class="line"> <span class="attr">type</span> : <span class="string">'line'</span>, <span class="comment">//type, required </span></div><div class="line"> tooltip : <span class="literal">true</span>, <span class="comment">//has tooltip </span></div><div class="line"> tooltipTrigger: <span class="literal">false</span>,<span class="comment">//show the tooltip when has it </span></div><div class="line"> callback: <span class="literal">undefined</span>,<span class="comment">//the callback function of click on item </span></div><div class="line"> moveTrigger: <span class="literal">true</span>,<span class="comment">//trigger callback when move in axis </span></div><div class="line"> defaultEvent: <span class="literal">true</span><span class="comment">//whether use defaute events on item </span></div><div class="line">}</div><div class="line">myChart(<span class="built_in">document</span>.getElementById(<span class="string">'lineChart'</span>), setting);</div></pre></td></tr></table></figure></p>
<p>配置项还是倾向于简洁明了,当然以后会继续改善,如果感兴趣,还是去看看<a href="https://www.npmjs.com/package/svg-ssr" title="svg-ssr" target="_blank" rel="external">文档</a>吧,欢迎指导。</p>
<h3 id="未尽之响应和动画"><a href="#未尽之响应和动画" class="headerlink" title="未尽之响应和动画"></a>未尽之响应和动画</h3><p>响应式应该是现有Web UI库里的标配了,在服务器端不是很好做的原因是,无法即时得到客户端视窗的大小,而在客户端进行二次渲染的话耗费的资源又有点得不偿失,所以响应式做的不尽完善。<br>而动画也因为时间关系没有深究,实际上SVG动画是有比较大的潜力的,有大牛给过相应的例子——<a href="https://75team.com/post/svg-animation-in-action.html" target="_blank" rel="external">SVG动画实践</a>。<br>当然,SVG服务器渲染这套东西还没完全完成,后续肯定会改善响应性和大屏上的体验。</p>
]]></content>
<summary type="html">
<p>这个月几乎全部精力都在完成公司图表库的<em>Server-side Rendering</em>,摆脱echarts投入d3的怀抱,旨在毫秒级的性能改善和预备以后反爬虫的可能性,不过性能表现的提升还得跟踪一段时间才能得到毕竟准确的结果。</p>
<h3 id="Canvas和SVG的选择"><a href="#Canvas和SVG的选择" class="headerlink" title="Canvas和SVG的选择"></a>Canvas和SVG的选择</h3><p>Canvas似乎是现在的主流选择,Flipboard甚至不惜用Canvas代替DOM来改善交互,表现大家自有定论。但在服务器端渲染,Canvas不具备交互的条件,所以SVG是唯一的选择。</p>
<h3 id="虚拟DOM的那些事儿"><a href="#虚拟DOM的那些事儿" class="headerlink" title="虚拟DOM的那些事儿"></a>虚拟DOM的那些事儿</h3><p>其实在服务器端渲染需要解决的一个最大的问题,便是<em>虚拟DOM</em>的操作了。虚拟DOM这个概念最近肯定是耳熟能详,为什么浏览器里需要一个虚拟DOM——还不是嫌DOM操作慢。而服务器端也面临同样的问题,有PhantomJS和JSDOM这样的完全模拟出浏览器环境进行DOM操作,但性能完全不能如意啊。<br>个人在做这个SVG服务器渲染的时候一开始是使用JSDOM(D3官方推荐),但渲染一个折线图(X轴50个点以内)大约需要80ms以上。这样的速度我们来进行SSR就是得不偿失了。所以我尝试了好几种方案:</p>
<ul>
<li>cheerio:性能非常好,但仅仅提供简单的DOM树形结构,但不包含任何DOM方法,无法对节点进行操作。</li>
<li>minidom:提供了DOM2大部分方法,但仅限于HTML文档,缺少D3需要的createElementNS。</li>
<li>xmldom:提供了DOM2大部分方法,性能能够满足要求。但缺少D3需要的Selectors API。<br>于是我给xmldom打了一个补丁,叫<a href="https://www.npmjs.com/package/xmldom-qsa" title="xmldom-qsa" target="_blank" rel="external">xmldom-qsa</a>,让其DOM节点包含querySelector等方法。这样就可以在服务器端完美地调用各种D3的API进行SVG绘图。粗略测试它的性能大概是JSDOM的4倍左右。
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="SVG" scheme="http://zeligzhou.github.io/tags/SVG/"/>
<category term="server-side" scheme="http://zeligzhou.github.io/tags/server-side/"/>
<category term="render" scheme="http://zeligzhou.github.io/tags/render/"/>
</entry>
<entry>
<title>事件循环</title>
<link href="http://zeligzhou.github.io/2017/04/16/event-loop/"/>
<id>http://zeligzhou.github.io/2017/04/16/event-loop/</id>
<published>2017-04-16T12:00:21.000Z</published>
<updated>2017-04-19T14:54:50.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>我们知道JavaScript的一大特点就是单线程,而这个线程中拥有唯一的一个事件循环。JavaScript代码的执行过程中,除了依靠函数调用栈来搞定函数的执行顺序外,还依靠任务队列(task queue)来搞定另外一些代码的执行。</p>
</blockquote>
<h3 id="事件循环是什么"><a href="#事件循环是什么" class="headerlink" title="事件循环是什么"></a>事件循环是什么</h3><p>“任务队列”是一个事件的队列(也可以理解成消息的队列),IO设备完成一项任务,就在”任务队列”中添加一个事件,表示相关的异步任务可以进入”执行栈”了。主线程读取”任务队列”,就是读取里面有哪些事件。</p>
<blockquote>
<p>“任务队列”中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入”任务队列”,等待主线程读取。</p>
</blockquote>
<p>主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。<br>事件循环的过程就是等待一个消息:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">while</span>(queue.waitForMessage()){</div><div class="line"> queue.processNextMessage();</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>在浏览器里,当一个事件出现且有一个事件监听器被绑定时,消息会被随时添加。如果没有事件监听器,事件会丢失。所以点击一个附带点击事件处理函数的元素会添加一个消息。</p>
<a id="more"></a>
<h3 id="事件循环的顺序"><a href="#事件循环的顺序" class="headerlink" title="事件循环的顺序"></a>事件循环的顺序</h3><p>调用<code>setTimeout</code>函数会在一个时间段过去后在队列中添加一个消息。比如说一个定时器中,将<code>setTimeout</code>的第二个参数设为0,就表示当前代码执行完(执行栈清空)以后,立即执行(0毫秒间隔)指定的回调函数。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{<span class="built_in">console</span>.log(<span class="number">1</span>);}, <span class="number">0</span>);</div><div class="line"><span class="built_in">console</span>.log(<span class="number">2</span>);</div></pre></td></tr></table></figure></p>
<p>上面代码的执行结果总是2,1,因为只有在执行完第二行以后,系统才会去执行”任务队列”中的回调函数。<br>Node.js还提供了另外两个与”任务队列”有关的方法:process.nextTick和setImmediate。它们可以帮助我们加深对”任务队列”的理解。<br>process.nextTick方法可以在当前”执行栈”的尾部—-下一次Event Loop(主线程读取”任务队列”)之前—-触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前。setImmediate方法则是在当前”任务队列”的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行,这与setTimeout(fn, 0)很像。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">process.nextTick(<span class="function"><span class="keyword">function</span> <span class="title">A</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="number">1</span>);</div><div class="line"> process.nextTick(<span class="function"><span class="keyword">function</span> <span class="title">B</span>(<span class="params"></span>)</span>{<span class="built_in">console</span>.log(<span class="number">2</span>);});</div><div class="line">});</div><div class="line">setTimeout(<span class="function"><span class="keyword">function</span> <span class="title">timeout</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'TIMEOUT FIRED'</span>);</div><div class="line">}, <span class="number">0</span>)</div><div class="line"><span class="comment">// 1</span></div><div class="line"><span class="comment">// 2</span></div><div class="line"><span class="comment">// TIMEOUT FIRED</span></div></pre></td></tr></table></figure></p>
<p>而当时间循环中有Promise时会怎样呢?<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="number">1</span>)</div><div class="line">}, <span class="number">0</span>);</div><div class="line"><span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span> <span class="title">executor</span>(<span class="params">resolve</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="number">2</span>);</div><div class="line"> <span class="keyword">for</span>( <span class="keyword">var</span> i=<span class="number">0</span> ; i<<span class="number">10000</span> ; i++ ) {</div><div class="line"> i == <span class="number">9999</span> && resolve();</div><div class="line"> }</div><div class="line"> <span class="built_in">console</span>.log(<span class="number">3</span>);</div><div class="line">}).then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="number">4</span>);</div><div class="line">});</div><div class="line"><span class="built_in">console</span>.log(<span class="number">5</span>);</div></pre></td></tr></table></figure></p>
<p>答案:2 3 5 4 1。</p>
<p>想知道为什么吗,还是有<a href="http://www.jianshu.com/p/12b9f73c5a4f#" target="_blank" rel="external">大牛解读</a>的。</p>
]]></content>
<summary type="html">
<blockquote>
<p>我们知道JavaScript的一大特点就是单线程,而这个线程中拥有唯一的一个事件循环。JavaScript代码的执行过程中,除了依靠函数调用栈来搞定函数的执行顺序外,还依靠任务队列(task queue)来搞定另外一些代码的执行。</p>
</blockquote>
<h3 id="事件循环是什么"><a href="#事件循环是什么" class="headerlink" title="事件循环是什么"></a>事件循环是什么</h3><p>“任务队列”是一个事件的队列(也可以理解成消息的队列),IO设备完成一项任务,就在”任务队列”中添加一个事件,表示相关的异步任务可以进入”执行栈”了。主线程读取”任务队列”,就是读取里面有哪些事件。</p>
<blockquote>
<p>“任务队列”中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入”任务队列”,等待主线程读取。</p>
</blockquote>
<p>主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。<br>事件循环的过程就是等待一个消息:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">while</span>(queue.waitForMessage())&#123;</div><div class="line"> queue.processNextMessage();</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>在浏览器里,当一个事件出现且有一个事件监听器被绑定时,消息会被随时添加。如果没有事件监听器,事件会丢失。所以点击一个附带点击事件处理函数的元素会添加一个消息。</p>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="eventloop" scheme="http://zeligzhou.github.io/tags/eventloop/"/>
</entry>
<entry>
<title>Javascript中的设计模式</title>
<link href="http://zeligzhou.github.io/2017/01/06/design-pattern-of-js/"/>
<id>http://zeligzhou.github.io/2017/01/06/design-pattern-of-js/</id>
<published>2017-01-06T10:28:21.000Z</published>
<updated>2017-04-19T09:38:00.000Z</updated>
<content type="html"><![CDATA[<p>设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。我们写代码总是会无意识的接触到别人的设计模式,例如每种语言都有自己的监听机制,这么看来其实设计模式从我们学编程起就一直伴随左右了。其实说到设计模式就离不开经验,当我们不断在一门语言里实践的过程中,总会用自己的理解组织代码。例如我每次重新写一个功能,都会总结哪里可以抽出来复用,哪里改动之后可以作为插件供其他人使用,这样就无意识的使用了一种设计模式。<br>使用设计模式都是为了让代码好维护,可读性更高,调用更合理。尤其是面向对象程序设计里,要遵循一些原则才具有良好的设计。</p>
<h3 id="设计原则"><a href="#设计原则" class="headerlink" title="设计原则"></a>设计原则</h3><p>面向对象程序设计有几个原则:单一职责原则 (Single Responsiblity Principle SRP)、里氏代换原则(Liskov Substitution Principle,LSP)、依赖倒转原则(Dependency Inversion Principle,DIP)、接口隔离原则(Interface Segregation Principle,ISP)、最小知识原则(Principle of Least Knowledge,PLK,也叫迪米特法则)、开闭原则(Open Closed Principle,OCP)。开闭原则具有理想主义的色彩,它是面向对象设计的终极目标。其他几条,则可以看做是开闭原则的实现方法。<br>我先简单介绍以下这几个原则的意思:</p>
<ul>
<li>单一职责原则:一个类只负责一项职责。在JS里即一个对象只做一件事情。</li>
<li>里氏代换原则:类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。</li>
<li>依赖倒转原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。</li>
<li>接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 </li>
<li>最小知识原则:一个对象应该对其他对象保持最少的了解。也就是对象之间耦合度要小。</li>
<li>开闭原则:一个软件实体如类、模块和函数应该可以扩展,但不可以修改。</li>
</ul>
<a id="more"></a>
<p>接下来看看我们常用的设计模式是怎么实现这些原则的。</p>
<h3 id="观察者模式"><a href="#观察者模式" class="headerlink" title="观察者模式"></a>观察者模式</h3><p>这个在实践中真的是随处可见。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">dom.addEventListener(<span class="string">"click"</span>,<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{ ...code... },<span class="literal">false</span>); <span class="comment">//订阅</span></div><div class="line">dom.click(); <span class="comment">//发布</span></div></pre></td></tr></table></figure></p>
<p>用的不能再多了吧,这个设计有什么好处呢?<br>假若,我们点击不同的DOM节点要触发一些事件,而事件和节点之间本身无关联,我们需要灵活的进行订阅和取消。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">callback1</span>(<span class="params"></span>)</span>{}</div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">callback2</span>(<span class="params"></span>)</span>{}</div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">callback3</span>(<span class="params"></span>)</span>{}</div><div class="line">dom1.addEventListener(<span class="string">"click"</span>,callback1,<span class="literal">false</span>);</div><div class="line">dom1.addEventListener(<span class="string">"click"</span>,callback3,<span class="literal">false</span>);</div><div class="line">dom2.addEventListener(<span class="string">"click"</span>,callback2,<span class="literal">false</span>);</div><div class="line">dom2.addEventListener(<span class="string">"click"</span>,callback3,<span class="literal">false</span>);</div><div class="line">dom1.click();</div><div class="line">dom2.click();</div></pre></td></tr></table></figure></p>
<p><code>dom1</code>并不需要关心<code>dom2</code>订阅过什么,<code>dom1</code>也不需要关心<code>dom1</code>之前订阅过什么,这样的模式在开发中优势就很明显了。</p>
<h3 id="策略模式"><a href="#策略模式" class="headerlink" title="策略模式"></a>策略模式</h3><p>表单验证写过不少吧。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">registerForm.onsubmit = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">if</span> ( registerForm.userName.value === <span class="string">''</span> ){</div><div class="line"> alert ( <span class="string">'用户名不能为空'</span> );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> ( registerForm.password.value.length < <span class="number">6</span> ){</div><div class="line"> alert ( <span class="string">'密码长度不能少于6 位'</span> );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> ( !<span class="regexp">/(^1[3|5|8][0-9]{9}$)/</span>.test( registerForm.phoneNumber.value ) ){</div><div class="line"> alert ( <span class="string">'手机号码格式不正确'</span> );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>怎么样,现在还能看,但是当表单有100个input要一一验证怎么破?这样的话我们其实会调用一些组件库,像我正在用的组件库里其实有很多这样的判断字典:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> strategies = {</div><div class="line"> <span class="attr">isNonEmpty</span>: <span class="function"><span class="keyword">function</span>(<span class="params"> value, errorMsg </span>)</span>{ <span class="comment">// 不为空</span></div><div class="line"> <span class="keyword">if</span> ( value === <span class="string">''</span> ){</div><div class="line"> <span class="keyword">return</span> errorMsg ;</div><div class="line"> }</div><div class="line"> },</div><div class="line"> <span class="attr">minLength</span>: <span class="function"><span class="keyword">function</span>(<span class="params"> value, length, errorMsg </span>)</span>{ <span class="comment">// 限制最小长度</span></div><div class="line"> <span class="keyword">if</span> ( value.length < length ){</div><div class="line"> <span class="keyword">return</span> errorMsg;</div><div class="line"> }</div><div class="line"> },</div><div class="line"> <span class="attr">isMobile</span>: <span class="function"><span class="keyword">function</span>(<span class="params"> value, errorMsg </span>)</span>{ <span class="comment">// 手机号码格式</span></div><div class="line"> <span class="keyword">if</span> ( !<span class="regexp">/(^1[3|5|8][0-9]{9}$)/</span>.test( value ) ){</div><div class="line"> <span class="keyword">return</span> errorMsg;</div><div class="line"> }</div><div class="line"> }</div><div class="line">};</div></pre></td></tr></table></figure></p>
<p>然后在webapp中我们只需要向一个验证方法添加所需要的策略:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> validataFunc = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"><span class="keyword">var</span> validator = <span class="keyword">new</span> Validator(); <span class="comment">// 创建一个validator 对象,代码略</span></div><div class="line"><span class="comment">/***************添加一些校验规则****************/</span></div><div class="line">validator.add( registerForm.userName, <span class="string">'isNonEmpty'</span>, <span class="string">'用户名不能为空'</span> );</div><div class="line">validator.add( registerForm.password, <span class="string">'minLength:6'</span>, <span class="string">'密码长度不能少于6 位'</span> );</div><div class="line">validator.add( registerForm.phoneNumber, <span class="string">'isMobile'</span>, <span class="string">'手机号码格式不正确'</span> );</div><div class="line"><span class="keyword">var</span> errorMsg = validator.start(); <span class="comment">// 获得校验结果</span></div><div class="line"> <span class="keyword">return</span> errorMsg; <span class="comment">// 返回校验结果</span></div><div class="line">}</div><div class="line"><span class="keyword">var</span> registerForm = <span class="built_in">document</span>.getElementById( <span class="string">'registerForm'</span> );</div><div class="line">registerForm.onsubmit = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">var</span> errorMsg = validataFunc(); <span class="comment">// 如果errorMsg 有确切的返回值,说明未通过校验</span></div><div class="line"> <span class="keyword">if</span> ( errorMsg ){</div><div class="line"> alert ( errorMsg );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">// 阻止表单提交</span></div><div class="line"> }</div><div class="line">};</div></pre></td></tr></table></figure></p>
<h3 id="装饰者模式"><a href="#装饰者模式" class="headerlink" title="装饰者模式"></a>装饰者模式</h3><p>还是表单验证,这是我们提交表单时的代码,怎么样,又有表单验证,又有ajax请求,符合单一职责原则吗?<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">registerForm.onsubmit = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">if</span> ( registerForm.userName.value === <span class="string">''</span> ){</div><div class="line"> alert ( <span class="string">'用户名不能为空'</span> );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> ( registerForm.password.value.length < <span class="number">6</span> ){</div><div class="line"> alert ( <span class="string">'密码长度不能少于6 位'</span> );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> ( !<span class="regexp">/(^1[3|5|8][0-9]{9}$)/</span>.test( registerForm.phoneNumber.value ) ){</div><div class="line"> alert ( <span class="string">'手机号码格式不正确'</span> );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> ajax(url,param);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>当然,我们可以用钩子来优化代码,但随着功能的扩展,也可能出现<code>if/else</code>交替增加,又变成了噩梦。<br>那么我们可以用装饰者模式解决。</p>
<blockquote>
<p>装饰者模式能够在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责。跟继承相比,装饰者是一种更轻便灵活的做法,这是一种“即用即付”的方式,比如天冷了就多穿一件外套,需要飞行时就在头上插一支竹蜻蜓,遇到一堆食尸鬼时就点开AOE(范围攻击)技能。</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">Function</span>.prototype.before = <span class="function"><span class="keyword">function</span>(<span class="params"> beforefn </span>)</span>{</div><div class="line"> <span class="keyword">var</span> __self = <span class="keyword">this</span>;</div><div class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">if</span> ( beforefn.apply( <span class="keyword">this</span>, <span class="built_in">arguments</span> ) === <span class="literal">false</span> ){</div><div class="line"> <span class="comment">// beforefn 返回false 的情况直接return,不再执行后面的原函数</span></div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> __self.apply( <span class="keyword">this</span>, <span class="built_in">arguments</span> );</div><div class="line"> }</div><div class="line">}</div><div class="line"><span class="keyword">var</span> validata = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">if</span> ( username.value === <span class="string">''</span> ){</div><div class="line"> alert ( <span class="string">'用户名不能为空'</span> );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span> ( password.value === <span class="string">''</span> ){</div><div class="line"> alert ( <span class="string">'密码不能为空'</span> );</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line">}</div><div class="line"><span class="keyword">var</span> formSubmit = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">var</span> param = {</div><div class="line"> <span class="attr">username</span>: username.value,</div><div class="line"> <span class="attr">password</span>: password.value</div><div class="line"> }</div><div class="line"> ajax( <span class="string">'http:// xxx.com/login'</span>, param );</div><div class="line">}</div><div class="line">formSubmit = formSubmit.before( validata );</div><div class="line">submitBtn.onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> formSubmit();</div><div class="line">}</div></pre></td></tr></table></figure>
<p>其实ES6新增的Promise就算是一个装饰者,不过它是后置装饰,形成了一个异步的包装链。<br>设计模式还有很多说不完的东西,边实践边总结吧。</p>
]]></content>
<summary type="html">
<p>设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。我们写代码总是会无意识的接触到别人的设计模式,例如每种语言都有自己的监听机制,这么看来其实设计模式从我们学编程起就一直伴随左右了。其实说到设计模式就离不开经验,当我们不断在一门语言里实践的过程中,总会用自己的理解组织代码。例如我每次重新写一个功能,都会总结哪里可以抽出来复用,哪里改动之后可以作为插件供其他人使用,这样就无意识的使用了一种设计模式。<br>使用设计模式都是为了让代码好维护,可读性更高,调用更合理。尤其是面向对象程序设计里,要遵循一些原则才具有良好的设计。</p>
<h3 id="设计原则"><a href="#设计原则" class="headerlink" title="设计原则"></a>设计原则</h3><p>面向对象程序设计有几个原则:单一职责原则 (Single Responsiblity Principle SRP)、里氏代换原则(Liskov Substitution Principle,LSP)、依赖倒转原则(Dependency Inversion Principle,DIP)、接口隔离原则(Interface Segregation Principle,ISP)、最小知识原则(Principle of Least Knowledge,PLK,也叫迪米特法则)、开闭原则(Open Closed Principle,OCP)。开闭原则具有理想主义的色彩,它是面向对象设计的终极目标。其他几条,则可以看做是开闭原则的实现方法。<br>我先简单介绍以下这几个原则的意思:</p>
<ul>
<li>单一职责原则:一个类只负责一项职责。在JS里即一个对象只做一件事情。</li>
<li>里氏代换原则:类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。</li>
<li>依赖倒转原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。</li>
<li>接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 </li>
<li>最小知识原则:一个对象应该对其他对象保持最少的了解。也就是对象之间耦合度要小。</li>
<li>开闭原则:一个软件实体如类、模块和函数应该可以扩展,但不可以修改。</li>
</ul>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="设计模式" scheme="http://zeligzhou.github.io/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
</entry>
<entry>
<title>Webpack模块化</title>
<link href="http://zeligzhou.github.io/2016/11/26/webpack-in-use/"/>
<id>http://zeligzhou.github.io/2016/11/26/webpack-in-use/</id>
<published>2016-11-26T07:46:21.000Z</published>
<updated>2017-04-18T15:23:14.000Z</updated>
<content type="html"><![CDATA[<h2 id="Webpack模块化的实践"><a href="#Webpack模块化的实践" class="headerlink" title="Webpack模块化的实践"></a>Webpack模块化的实践</h2><p>Webpack 是德国开发者 Tobias Koppers 开发的模块加载器,在 Webpack 当中, 所有的资源都被当作是模块, js, css, 图片等等,对应各种不同文件类型的资源, Webpack 有对应的模块 loader,Webpack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。</p>
<h3 id="一步一步来配置"><a href="#一步一步来配置" class="headerlink" title="一步一步来配置"></a>一步一步来配置</h3><p>它的配置文件是 webpack.config.js.<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// webpack.config.js</span></div><div class="line"><span class="built_in">module</span>.exports = {</div><div class="line"> <span class="attr">entry</span>: {</div><div class="line"> <span class="attr">bundle1</span>: <span class="string">'./main1.js'</span>,</div><div class="line"> <span class="attr">bundle2</span>: <span class="string">'./main2.js'</span></div><div class="line"> },</div><div class="line"> <span class="attr">output</span>: {</div><div class="line"> <span class="attr">filename</span>: <span class="string">'[name].js'</span></div><div class="line"> }</div><div class="line">};</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<p>Webpack 允许你在js文件中require CSS , 通过 CSS-loader来预处理css文件.<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">module</span>.exports = {</div><div class="line"> <span class="attr">entry</span>: <span class="string">'./main.js'</span>,</div><div class="line"> <span class="attr">output</span>: {</div><div class="line"> <span class="attr">filename</span>: <span class="string">'bundle.js'</span></div><div class="line"> },</div><div class="line"> <span class="attr">module</span>: {</div><div class="line"> <span class="attr">loaders</span>:[</div><div class="line"> { <span class="attr">test</span>: <span class="regexp">/\.css$/</span>, <span class="attr">loader</span>: <span class="string">'style-loader!css-loader'</span> },</div><div class="line"> ]</div><div class="line"> }</div><div class="line">};</div></pre></td></tr></table></figure></p>
<p>你需要使用loaders来转换CSS 文件. 第一个是 CSS-loader 来读取CSS文件, 另外一个是Style-loader 是将style样式插入到html中,用!连接。<br>同样,Webpack 允许你在js文件中require图片 , 通过 url-loader和file-loader来预处理图片文件.</p>
<p>Webpack 可以使用UglifyJs Plugin 处理js。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> webpack = <span class="built_in">require</span>(<span class="string">'webpack'</span>);</div><div class="line"><span class="keyword">var</span> uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;</div><div class="line"><span class="built_in">module</span>.exports = {</div><div class="line"> <span class="attr">entry</span>: <span class="string">'./main.js'</span>,</div><div class="line"> <span class="attr">output</span>: {</div><div class="line"> <span class="attr">filename</span>: <span class="string">'bundle.js'</span></div><div class="line"> },</div><div class="line"> <span class="attr">plugins</span>: [</div><div class="line"> <span class="keyword">new</span> uglifyJsPlugin({</div><div class="line"> <span class="attr">compress</span>: {</div><div class="line"> <span class="attr">warnings</span>: <span class="literal">false</span></div><div class="line"> }</div><div class="line"> })</div><div class="line"> ]</div><div class="line">};</div></pre></td></tr></table></figure></p>
<p>还可以使用html-webpack-plugin 创建 index.html ,open-browser-webpack-plugin 打开浏览器。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> HtmlwebpackPlugin = <span class="built_in">require</span>(<span class="string">'html-webpack-plugin'</span>);</div><div class="line"><span class="keyword">var</span> OpenBrowserPlugin = <span class="built_in">require</span>(<span class="string">'open-browser-webpack-plugin'</span>);</div><div class="line"></div><div class="line"><span class="built_in">module</span>.exports = {</div><div class="line"> <span class="attr">entry</span>: <span class="string">'./main.js'</span>,</div><div class="line"> <span class="attr">output</span>: {</div><div class="line"> <span class="attr">filename</span>: <span class="string">'bundle.js'</span></div><div class="line"> },</div><div class="line"> <span class="attr">plugins</span>: [</div><div class="line"> <span class="keyword">new</span> HtmlwebpackPlugin({</div><div class="line"> <span class="attr">title</span>: <span class="string">'Webpack-demos'</span>,</div><div class="line"> <span class="attr">filename</span>: <span class="string">'index.html'</span></div><div class="line"> }),</div><div class="line"> <span class="keyword">new</span> OpenBrowserPlugin({</div><div class="line"> <span class="attr">url</span>: <span class="string">'http://localhost:8080'</span></div><div class="line"> })</div><div class="line"> ]</div><div class="line">};</div></pre></td></tr></table></figure></p>
<p>还有热更新之类的各种插件等你玩哦~~如果喜欢用JS管理一切资源,那webpack真是必备神器了!</p>
<p>当然还要记得webpack的命令行:</p>
<ul>
<li>webpack – 构建文件</li>
<li>webpack -p – 发布</li>
<li>webpack –watch – 监听项目</li>
<li>webpack -d – 包含 source maps方便调试</li>
<li>webpack –colors – 让打包界面更好看</li>
</ul>
<p>构建项目的时候, 你可以把启动项写进package.json。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// package.json</span></div><div class="line">{</div><div class="line"> <span class="comment">// ...</span></div><div class="line"> <span class="string">"scripts"</span>: {</div><div class="line"> <span class="string">"dev"</span>: <span class="string">"webpack-dev-server --devtool eval --progress --colors"</span>,</div><div class="line"> <span class="string">"deploy"</span>: <span class="string">"NODE_ENV=production webpack -p"</span></div><div class="line"> },</div><div class="line"> <span class="comment">// ...</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>然后跑起来吧~<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">npm run dev</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<h2 id="Webpack模块化的实践"><a href="#Webpack模块化的实践" class="headerlink" title="Webpack模块化的实践"></a>Webpack模块化的实践</h2><p>Webpack 是德国开发者 Tobias Koppers 开发的模块加载器,在 Webpack 当中, 所有的资源都被当作是模块, js, css, 图片等等,对应各种不同文件类型的资源, Webpack 有对应的模块 loader,Webpack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。</p>
<h3 id="一步一步来配置"><a href="#一步一步来配置" class="headerlink" title="一步一步来配置"></a>一步一步来配置</h3><p>它的配置文件是 webpack.config.js.<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// webpack.config.js</span></div><div class="line"><span class="built_in">module</span>.exports = &#123;</div><div class="line"> <span class="attr">entry</span>: &#123;</div><div class="line"> <span class="attr">bundle1</span>: <span class="string">'./main1.js'</span>,</div><div class="line"> <span class="attr">bundle2</span>: <span class="string">'./main2.js'</span></div><div class="line"> &#125;,</div><div class="line"> <span class="attr">output</span>: &#123;</div><div class="line"> <span class="attr">filename</span>: <span class="string">'[name].js'</span></div><div class="line"> &#125;</div><div class="line">&#125;;</div></pre></td></tr></table></figure></p>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="webpack" scheme="http://zeligzhou.github.io/tags/webpack/"/>
</entry>
<entry>
<title>Vue实践</title>
<link href="http://zeligzhou.github.io/2016/08/13/vue-and-practice/"/>
<id>http://zeligzhou.github.io/2016/08/13/vue-and-practice/</id>
<published>2016-08-13T12:26:21.000Z</published>
<updated>2017-04-18T16:31:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="Vue和一些7788"><a href="#Vue和一些7788" class="headerlink" title="Vue和一些7788"></a>Vue和一些7788</h2><p>最近公司的朋友都很疑惑,前端这阵子真的是日新月异,我们还用着jquery,underscore和knockout这些“小玩具”好像步入了中年一样。没办法啊,现在的前端大兴土木搞组件,搞模块化,我们也得跟,不过老项目总有钉子户,不能一口啃下来,所以就出了一个兼容并包的demo。</p>
<h3 id="简单的模板"><a href="#简单的模板" class="headerlink" title="简单的模板"></a>简单的模板</h3><p>初始化这些到处可以搜到的东西就不重复写了。<br>直接上手写组件。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">Vue.component(<span class="string">'section1'</span>,{</div><div class="line"> <span class="attr">template</span>:<span class="string">'<section><h2>{{title}}</h2><div>{{message}}</div></section>'</span>,</div><div class="line"> <span class="attr">data</span>:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> {</div><div class="line"> <span class="attr">title</span>:<span class="string">'示例1:独立组件'</span>,</div><div class="line"> <span class="attr">message</span>:<span class="string">'data必须是function'</span></div><div class="line"> }</div><div class="line"> }</div><div class="line">});</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<h3 id="循环模板"><a href="#循环模板" class="headerlink" title="循环模板"></a>循环模板</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">ul</span> <span class="attr">class</span>=<span class="string">"card_frame"</span>></span></div><div class="line"> <span class="tag"><<span class="name">li</span></span></div><div class="line"> <span class="attr">is</span>=<span class="string">"card-item"</span></div><div class="line"> <span class="attr">v-for</span>=<span class="string">"(card, index) in cards"</span></div><div class="line"> <span class="attr">v-bind:title</span>=<span class="string">"card.text"</span></div><div class="line"> ></div><div class="line"> <span class="tag"></<span class="name">li</span>></span></div><div class="line"><span class="tag"></<span class="name">ul</span>></span></div></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line">Vue.component(<span class="string">'card-item'</span>,{</div><div class="line"> <span class="attr">template</span>:<span class="string">'<li>{{title}}</li>'</span>,</div><div class="line"> <span class="attr">props</span>:[<span class="string">'title'</span>]</div><div class="line">});</div><div class="line"><span class="comment">//初始化data</span></div><div class="line"><span class="keyword">var</span> app = <span class="keyword">new</span> Vue({</div><div class="line"> <span class="attr">el</span>: <span class="string">'#app'</span>,</div><div class="line"> <span class="attr">data</span>: {</div><div class="line"> <span class="attr">title</span>:<span class="string">"Vue Demo"</span>,</div><div class="line"> <span class="attr">message</span>:<span class="string">"Vue常用功能示例"</span>,</div><div class="line"> <span class="attr">cards</span>:[</div><div class="line"> {<span class="attr">text</span>:<span class="string">'card1'</span>},</div><div class="line"> {<span class="attr">text</span>:<span class="string">'card2'</span>},</div><div class="line"> {<span class="attr">text</span>:<span class="string">'card3'</span>}</div><div class="line"> ],</div><div class="line">...</div></pre></td></tr></table></figure>
<h3 id="事件绑定模板"><a href="#事件绑定模板" class="headerlink" title="事件绑定模板"></a>事件绑定模板</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">ul</span> <span class="attr">class</span>=<span class="string">"card_frame"</span>></span></div><div class="line"> <span class="tag"><<span class="name">li</span></span></div><div class="line"> <span class="attr">is</span>=<span class="string">"card-item2"</span></div><div class="line"> <span class="attr">v-for</span>=<span class="string">"(card, index) in cards"</span></div><div class="line"> <span class="attr">v-bind:title</span>=<span class="string">"card.text"</span></div><div class="line"> </div><div class="line"> ><span class="tag"></<span class="name">li</span>></span></div><div class="line"><span class="tag"></<span class="name">ul</span>></span></div></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">Vue.component(<span class="string">'card-item2'</span>,{</div><div class="line"> <span class="attr">template</span>:<span class="string">'<li v-on:click="hideText($event)">{{title}}</li>'</span>,</div><div class="line"> <span class="attr">props</span>:[<span class="string">'title'</span>],</div><div class="line"> <span class="attr">methods</span>:{</div><div class="line"> <span class="attr">hideText</span>:<span class="function"><span class="keyword">function</span>(<span class="params">e</span>)</span>{</div><div class="line"> e.target.style.display = <span class="string">"none"</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line">});</div></pre></td></tr></table></figure>
<h3 id="引用外部插件"><a href="#引用外部插件" class="headerlink" title="引用外部插件"></a>引用外部插件</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"js/jquery.dragsort-0.5.1.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">mounted:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"组件挂载后,目标li的数量为:"</span>+$(<span class="string">"#list1 li"</span>).length);</div><div class="line"> $(<span class="string">"#list1, #list2"</span>).dragsort({ <span class="attr">dragSelector</span>: <span class="string">"li"</span>, <span class="attr">dragBetween</span>: <span class="literal">true</span>, <span class="attr">dragEnd</span>: saveOrder });</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">saveOrder</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"调用拖动事件后,目标li的数量为:"</span>+$(<span class="string">"#list1 li"</span>).length);</div><div class="line"> };</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="Ajax请求"><a href="#Ajax请求" class="headerlink" title="Ajax请求"></a>Ajax请求</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">section5</span> <span class="attr">v-bind:weather</span>=<span class="string">"ajaxData"</span>></span><span class="tag"></<span class="name">section5</span>></span></div></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line">Vue.component(<span class="string">'section5'</span>,{</div><div class="line"> <span class="attr">template</span>:<span class="string">'<section><h2>{{title}}</h2><div>{{message}}</div><div>当前天气:{{weather}}</div></section>'</span>,</div><div class="line"> <span class="attr">data</span>:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> {</div><div class="line"> <span class="attr">title</span>:<span class="string">'示例5:AJAX获取数据'</span>,</div><div class="line"> <span class="attr">message</span>:<span class="string">'异步数据的展示'</span></div><div class="line"> }</div><div class="line"> },</div><div class="line"> <span class="attr">props</span>:[<span class="string">'weather'</span>]</div><div class="line">});</div><div class="line"><span class="comment">//app实例化方法中</span></div><div class="line">...</div><div class="line">created:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"实例创建后,ajaxData为:"</span>+<span class="keyword">this</span>.ajaxData);</div><div class="line"> <span class="keyword">var</span> self = <span class="keyword">this</span>;</div><div class="line"> $.ajax({</div><div class="line"> <span class="attr">url</span>: <span class="string">"http://api.k780.com:88/?app=weather.today&weaid=1&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json&jsoncallback=?"</span>,</div><div class="line"> <span class="attr">dataType</span>: <span class="string">"jsonp"</span>,</div><div class="line"> <span class="attr">type</span>:<span class="string">"Post"</span>,</div><div class="line"> <span class="attr">jsonpCallback</span>: <span class="string">"jsonpCallback"</span>,</div><div class="line"> <span class="attr">success</span>: <span class="function"><span class="keyword">function</span> (<span class="params">data</span>) </span>{</div><div class="line"> self.ajaxData = data.result.temperature;</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"请求完成后,ajaxData为:"</span>+self.ajaxData);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"实例创建后,目标li的数量为:"</span>+$(<span class="string">"#list1 li"</span>).length);</div><div class="line"> },</div><div class="line">...</div></pre></td></tr></table></figure>
<h2 id="后话"><a href="#后话" class="headerlink" title="后话"></a>后话</h2><p>想当初,我刚做前端的时候,全世界都在说内容表现行为要分离。现在的webapp,大框架,模块化,恨不得JS搞定一切,想来也是唏嘘,不过每个时代总有局限性,只要能适应以后的发展就跟着走吧。</p>
<p>完整demo见<a href="https://github.com/zeligzhou/boom" target="_blank" rel="external">boom</a>。</p>
]]></content>
<summary type="html">
<h2 id="Vue和一些7788"><a href="#Vue和一些7788" class="headerlink" title="Vue和一些7788"></a>Vue和一些7788</h2><p>最近公司的朋友都很疑惑,前端这阵子真的是日新月异,我们还用着jquery,underscore和knockout这些“小玩具”好像步入了中年一样。没办法啊,现在的前端大兴土木搞组件,搞模块化,我们也得跟,不过老项目总有钉子户,不能一口啃下来,所以就出了一个兼容并包的demo。</p>
<h3 id="简单的模板"><a href="#简单的模板" class="headerlink" title="简单的模板"></a>简单的模板</h3><p>初始化这些到处可以搜到的东西就不重复写了。<br>直接上手写组件。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">Vue.component(<span class="string">'section1'</span>,&#123;</div><div class="line"> <span class="attr">template</span>:<span class="string">'&lt;section&gt;&lt;h2&gt;&#123;&#123;title&#125;&#125;&lt;/h2&gt;&lt;div&gt;&#123;&#123;message&#125;&#125;&lt;/div&gt;&lt;/section&gt;'</span>,</div><div class="line"> <span class="attr">data</span>:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line"> <span class="keyword">return</span> &#123;</div><div class="line"> <span class="attr">title</span>:<span class="string">'示例1:独立组件'</span>,</div><div class="line"> <span class="attr">message</span>:<span class="string">'data必须是function'</span></div><div class="line"> &#125;</div><div class="line"> &#125;</div><div class="line">&#125;);</div></pre></td></tr></table></figure></p>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="Vue.js" scheme="http://zeligzhou.github.io/tags/Vue-js/"/>
</entry>
<entry>
<title>原型Prototype</title>
<link href="http://zeligzhou.github.io/2016/06/09/prototype-and-sth/"/>
<id>http://zeligzhou.github.io/2016/06/09/prototype-and-sth/</id>
<published>2016-06-09T06:18:21.000Z</published>
<updated>2017-04-19T05:10:40.000Z</updated>
<content type="html"><![CDATA[<p><code>prototype</code>应该是Javascript里最核心的内容了。原型链继承的概念神马的估计都背熟了,但其实在应用中又该怎么玩呢?</p>
<h3 id="原型链是什么"><a href="#原型链是什么" class="headerlink" title="原型链是什么"></a>原型链是什么</h3><p>如果<code>myObject</code>上不存在<code>a</code>属性时,我们就将注意力转向对象的<code>[[Prototype]]</code>链:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> anotherObject = {</div><div class="line"> <span class="attr">a</span>: <span class="number">2</span></div><div class="line">};</div><div class="line"><span class="comment">// 创建一个链接到`anotherObject`的对象</span></div><div class="line"><span class="keyword">var</span> myObject = <span class="built_in">Object</span>.create( anotherObject );</div><div class="line">myObject.a; <span class="comment">// 2</span></div></pre></td></tr></table></figure></p>
<p>这个处理持续进行,直到找到名称匹配的属性,或者<code>[[Prototype]]</code>链终结。如果在链条的末尾都没有找到匹配的属性,那么<code>[[Get]]</code>操作的返回结果为<code>undefined</code>。<br><a id="more"></a></p>
<h3 id="原型链的屏蔽"><a href="#原型链的屏蔽" class="headerlink" title="原型链的屏蔽"></a>原型链的屏蔽</h3><p>而以下这个案例又说明了什么?<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> anotherObject = {</div><div class="line"> <span class="attr">a</span>: <span class="number">2</span></div><div class="line">};</div><div class="line"><span class="comment">// 创建一个链接到`anotherObject`的对象</span></div><div class="line"><span class="keyword">var</span> myObject = <span class="built_in">Object</span>.create( anotherObject );</div><div class="line">myObject.a; <span class="comment">// 2</span></div><div class="line">anotherObject.a = <span class="number">3</span>;</div><div class="line"><span class="built_in">console</span>.log(myObject.a);<span class="comment">//3 仍然通过[[Prototype]]查找到a</span></div><div class="line">myObject.a = <span class="number">4</span>;<span class="comment">//直接拥有了属性a,屏蔽[[Prototype]]</span></div><div class="line"><span class="built_in">console</span>.log(anotherObject.a);<span class="comment">//3 </span></div><div class="line">anotherObject.a = <span class="number">5</span>;</div><div class="line"><span class="built_in">console</span>.log(myObject.a);<span class="comment">//4 [[Prototype]]被屏蔽,直接读取自身属性a</span></div></pre></td></tr></table></figure></p>
<p><code>[[Prototype]]</code>链怎么访问呢,现在浏览器提供了一个<code>.__proto__</code>属性来查找原型链。可以这么实现:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">Object</span>.defineProperty( <span class="built_in">Object</span>.prototype, <span class="string">"__proto__"</span>, {</div><div class="line"> <span class="attr">get</span>: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.getPrototypeOf( <span class="keyword">this</span> );</div><div class="line"> },</div><div class="line"> <span class="attr">set</span>: <span class="function"><span class="keyword">function</span>(<span class="params">o</span>) </span>{</div><div class="line"> <span class="comment">// setPrototypeOf(..) as of ES6</span></div><div class="line"> <span class="built_in">Object</span>.setPrototypeOf( <span class="keyword">this</span>, o );</div><div class="line"> <span class="keyword">return</span> o;</div><div class="line"> }</div><div class="line">} );</div></pre></td></tr></table></figure></p>
<p>其实,我们并不需要一堆<code>new</code>和<code>.prototype</code>就能很好的利用原型的特性来完成代码,直接使用对象的字面形式将拥有更简洁的语法和更好的可读性。</p>
<h3 id="Object-create-和替补"><a href="#Object-create-和替补" class="headerlink" title="Object.create(..)和替补"></a><code>Object.create(..)</code>和替补</h3><p><code>Object.create(..)</code>在ES5中被加入。你可能需要支持ES5之前的环境:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (!<span class="built_in">Object</span>.create) {</div><div class="line"> <span class="built_in">Object</span>.create = <span class="function"><span class="keyword">function</span>(<span class="params">o</span>) </span>{</div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">F</span>(<span class="params"></span>)</span>{}</div><div class="line"> F.prototype = o;</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> F();</div><div class="line"> };</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p><code>Object.create(..)</code>的这种用法是目前最常见的用法,因为他的这一部分是可以填补的。ES5标准的内建<code>Object.create(..)</code>还提供了一个附加的功能,它是 不能 被ES5之前的版本填补的。如此,这个功能的使用远没有那么常见。为了完整性,让我么看看这个附加功能:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> anotherObject = {</div><div class="line"> <span class="attr">a</span>: <span class="number">2</span></div><div class="line">};</div><div class="line"><span class="keyword">var</span> myObject = <span class="built_in">Object</span>.create( anotherObject, {</div><div class="line"> <span class="attr">b</span>: {</div><div class="line"> <span class="attr">enumerable</span>: <span class="literal">false</span>,</div><div class="line"> <span class="attr">writable</span>: <span class="literal">true</span>,</div><div class="line"> <span class="attr">configurable</span>: <span class="literal">false</span>,</div><div class="line"> <span class="attr">value</span>: <span class="number">3</span></div><div class="line"> },</div><div class="line"> <span class="attr">c</span>: {</div><div class="line"> <span class="attr">enumerable</span>: <span class="literal">true</span>,</div><div class="line"> <span class="attr">writable</span>: <span class="literal">false</span>,</div><div class="line"> <span class="attr">configurable</span>: <span class="literal">false</span>,</div><div class="line"> <span class="attr">value</span>: <span class="number">4</span></div><div class="line"> }</div><div class="line">} );</div><div class="line">myObject.hasOwnProperty( <span class="string">"a"</span> ); <span class="comment">// false</span></div><div class="line">myObject.hasOwnProperty( <span class="string">"b"</span> ); <span class="comment">// true</span></div><div class="line">myObject.hasOwnProperty( <span class="string">"c"</span> ); <span class="comment">// true</span></div><div class="line">myObject.a; <span class="comment">// 2</span></div><div class="line">myObject.b; <span class="comment">// 3</span></div><div class="line">myObject.c; <span class="comment">// 4</span></div></pre></td></tr></table></figure></p>
<p>当然我们经常使用一些polyfill代码来实现并没有被广泛支持的新增功能,其中的可维护性和兼容性之间的取舍就看你自己啦。</p>
]]></content>
<summary type="html">
<p><code>prototype</code>应该是Javascript里最核心的内容了。原型链继承的概念神马的估计都背熟了,但其实在应用中又该怎么玩呢?</p>
<h3 id="原型链是什么"><a href="#原型链是什么" class="headerlink" title="原型链是什么"></a>原型链是什么</h3><p>如果<code>myObject</code>上不存在<code>a</code>属性时,我们就将注意力转向对象的<code>[[Prototype]]</code>链:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> anotherObject = &#123;</div><div class="line"> <span class="attr">a</span>: <span class="number">2</span></div><div class="line">&#125;;</div><div class="line"><span class="comment">// 创建一个链接到`anotherObject`的对象</span></div><div class="line"><span class="keyword">var</span> myObject = <span class="built_in">Object</span>.create( anotherObject );</div><div class="line">myObject.a; <span class="comment">// 2</span></div></pre></td></tr></table></figure></p>
<p>这个处理持续进行,直到找到名称匹配的属性,或者<code>[[Prototype]]</code>链终结。如果在链条的末尾都没有找到匹配的属性,那么<code>[[Get]]</code>操作的返回结果为<code>undefined</code>。<br>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="prototype" scheme="http://zeligzhou.github.io/tags/prototype/"/>
</entry>
<entry>
<title>XHR2那些事儿</title>
<link href="http://zeligzhou.github.io/2016/04/18/xhr2-in-use/"/>
<id>http://zeligzhou.github.io/2016/04/18/xhr2-in-use/</id>
<published>2016-04-18T14:51:21.000Z</published>
<updated>2017-04-18T16:50:54.000Z</updated>
<content type="html"><![CDATA[<h2 id="XMLHttpRequest-Level-2"><a href="#XMLHttpRequest-Level-2" class="headerlink" title="XMLHttpRequest Level 2"></a>XMLHttpRequest Level 2</h2><p>使用AJAX好多年了吧,相信创建一个请求监听什么状态都驾轻就熟了,还有什么好说的呢。问题来源于最近公司在优化图片上传的接口。所以来总结以下XMLHttpRequest Level 2的一些东西。</p>
<h3 id="Formdata"><a href="#Formdata" class="headerlink" title="Formdata"></a>Formdata</h3><p>AJAX 操作往往用来传递表单数据。为了方便表单处理,HTML 5新增了一个 FormData 对象,可以用于模拟表单。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> formData = <span class="keyword">new</span> FormData(form)</div></pre></td></tr></table></figure></p>
<p>新版 XMLHttpRequest 对象,不仅可以发送文本信息,还可以上传文件。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> input = <span class="built_in">document</span>.getElementById(<span class="string">"input"</span>),</div><div class="line"> formData = <span class="keyword">new</span> FormData();</div><div class="line">formData.append(<span class="string">"file"</span>,input.files[<span class="number">0</span>]); <span class="comment">// file名称与后台接收的名称一致</span></div><div class="line">xhr.open(<span class="string">'POST'</span>, form.action);</div><div class="line">xhr.send(formData);</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<h3 id="Progress"><a href="#Progress" class="headerlink" title="Progress"></a>Progress</h3><p>XHR 对象提供了一系列 API,用于监听进度事件,progress表示请求的传输中状态:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</div><div class="line">xhr.open(<span class="string">'GET'</span>,<span class="string">'/resource'</span>);</div><div class="line">xhr.timeout = <span class="number">5000</span>; <span class="comment">// 设置超时时间</span></div><div class="line"></div><div class="line">xhr.addEventListener(<span class="string">'load'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ ... }); <span class="comment">// 传输成功监听</span></div><div class="line">xhr.addEventListener(<span class="string">'error'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ ... }); <span class="comment">// 传输错误监听</span></div><div class="line"></div><div class="line"><span class="keyword">var</span> onProgressHandler = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>) </span>{</div><div class="line"> <span class="keyword">if</span>(event.lengthComputable) {</div><div class="line"> <span class="keyword">var</span> progress = (event.loaded / event.total) * <span class="number">100</span>; <span class="comment">// 传输中监听回掉函数</span></div><div class="line"> ...</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">xhr.upload.addEventListener(<span class="string">'progress'</span>, onProgressHandler); <span class="comment">// 上传传输中监听</span></div><div class="line">xhr.addEventListener(<span class="string">'progress'</span>, onProgressHandler); <span class="comment">// 下载传输中监听</span></div><div class="line">xhr.send();</div></pre></td></tr></table></figure>
<p>知道progress可以干啥了吧。只要event.lengthComputable为true,就能拿到传输数据的进度啦。</p>
<p>当然XHR2还有以下特征:</p>
<ul>
<li>可以设置HTTP请求的超时时间。</li>
<li>可以使用FormData对象管理表单数据。</li>
<li>可以上传文件。</li>
<li>可以请求不同域名下的数据(跨域请求)。</li>
<li>可以获取服务器端的二进制数据。</li>
<li>可以获得数据传输的进度信息。</li>
</ul>
<p>好好玩吧~</p>
]]></content>
<summary type="html">
<h2 id="XMLHttpRequest-Level-2"><a href="#XMLHttpRequest-Level-2" class="headerlink" title="XMLHttpRequest Level 2"></a>XMLHttpRequest Level 2</h2><p>使用AJAX好多年了吧,相信创建一个请求监听什么状态都驾轻就熟了,还有什么好说的呢。问题来源于最近公司在优化图片上传的接口。所以来总结以下XMLHttpRequest Level 2的一些东西。</p>
<h3 id="Formdata"><a href="#Formdata" class="headerlink" title="Formdata"></a>Formdata</h3><p>AJAX 操作往往用来传递表单数据。为了方便表单处理,HTML 5新增了一个 FormData 对象,可以用于模拟表单。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> formData = <span class="keyword">new</span> FormData(form)</div></pre></td></tr></table></figure></p>
<p>新版 XMLHttpRequest 对象,不仅可以发送文本信息,还可以上传文件。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> input = <span class="built_in">document</span>.getElementById(<span class="string">"input"</span>),</div><div class="line"> formData = <span class="keyword">new</span> FormData();</div><div class="line">formData.append(<span class="string">"file"</span>,input.files[<span class="number">0</span>]); <span class="comment">// file名称与后台接收的名称一致</span></div><div class="line">xhr.open(<span class="string">'POST'</span>, form.action);</div><div class="line">xhr.send(formData);</div></pre></td></tr></table></figure></p>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="xhr" scheme="http://zeligzhou.github.io/tags/xhr/"/>
<category term="ajax" scheme="http://zeligzhou.github.io/tags/ajax/"/>
</entry>
<entry>
<title>关于this</title>
<link href="http://zeligzhou.github.io/2016/01/20/this-and-more/"/>
<id>http://zeligzhou.github.io/2016/01/20/this-and-more/</id>
<published>2016-01-20T04:31:21.000Z</published>
<updated>2017-04-19T04:54:08.000Z</updated>
<content type="html"><![CDATA[<p><code>this</code>应该是Javascript里永恒的面试题。这次只说说硬绑定里的陷阱题。</p>
<h3 id="硬绑定"><a href="#硬绑定" class="headerlink" title="硬绑定"></a>硬绑定</h3><p>求下面这个题目的输出:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">cb</span>) </span>{</div><div class="line"> cb();</div><div class="line">}</div><div class="line"><span class="keyword">var</span> a = {</div><div class="line"> <span class="attr">a</span>: <span class="string">"a in a"</span>,</div><div class="line"> <span class="attr">getA</span>:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.a);</div><div class="line">}</div><div class="line">};</div><div class="line"><span class="keyword">var</span> b = {</div><div class="line"> <span class="attr">a</span>: <span class="string">"a in b"</span></div><div class="line">};</div><div class="line"><span class="keyword">var</span> getA = a.getA;</div><div class="line"><span class="keyword">var</span> getA2 = getA.bind(a);</div><div class="line">a.getA();<span class="comment">//"a in a"</span></div><div class="line">getA();<span class="comment">//a</span></div><div class="line">foo(a.getA);<span class="comment">//a</span></div><div class="line">getA2.call(b);<span class="comment">//"a in a"</span></div></pre></td></tr></table></figure></p>
<a id="more"></a>
<p>第一个很好理解吧,不用多说。<br>第二个<code>getA</code>只是<code>a.getA</code>的一个引用,指向的是函数本身,此时的<code>getA</code>其实是一个不带任何修饰的函数调用,所以会采用默认绑定(绑定到全局对象或undefined上)。<br>第三个其实和第二个是一个原理。<br>第四个就是个障眼法,<code>getA2</code>已经将<code>getA</code>方法硬绑定到全局<code>a</code>变量了,可以理解为<code>bind</code>返回了一个硬编码的新函数,之后你无论怎么调用<code>getA2</code>,这个新函数的<code>this</code>永远指向<code>a</code>。</p>
<h3 id="比硬绑定还强的指定"><a href="#比硬绑定还强的指定" class="headerlink" title="比硬绑定还强的指定"></a>比硬绑定还强的指定</h3><p>我们还可以看看什么可以改变硬绑定的指向:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">something</span>) </span>{</div><div class="line"> <span class="keyword">this</span>.a = something;</div><div class="line">}</div><div class="line"><span class="keyword">var</span> obj1 = {};</div><div class="line"><span class="keyword">var</span> bar = foo.bind( obj1 );</div><div class="line">bar( <span class="number">2</span> );</div><div class="line"><span class="built_in">console</span>.log( obj1.a ); <span class="comment">// 2</span></div><div class="line"><span class="keyword">var</span> baz = <span class="keyword">new</span> bar( <span class="number">3</span> );</div><div class="line"><span class="built_in">console</span>.log( obj1.a ); <span class="comment">// 2</span></div><div class="line"><span class="built_in">console</span>.log( baz.a ); <span class="comment">// 3</span></div></pre></td></tr></table></figure></p>
<p>有趣了吧,真是一山更比一山高。如果要追踪其原理,推荐一本书<a href="https://github.com/getify/You-Dont-Know-JS" target="_blank" rel="external">You Don’t Know JS</a>。</p>
]]></content>
<summary type="html">
<p><code>this</code>应该是Javascript里永恒的面试题。这次只说说硬绑定里的陷阱题。</p>
<h3 id="硬绑定"><a href="#硬绑定" class="headerlink" title="硬绑定"></a>硬绑定</h3><p>求下面这个题目的输出:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">cb</span>) </span>&#123;</div><div class="line"> cb();</div><div class="line">&#125;</div><div class="line"><span class="keyword">var</span> a = &#123;</div><div class="line"> <span class="attr">a</span>: <span class="string">"a in a"</span>,</div><div class="line"> <span class="attr">getA</span>:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.a);</div><div class="line">&#125;</div><div class="line">&#125;;</div><div class="line"><span class="keyword">var</span> b = &#123;</div><div class="line"> <span class="attr">a</span>: <span class="string">"a in b"</span></div><div class="line">&#125;;</div><div class="line"><span class="keyword">var</span> getA = a.getA;</div><div class="line"><span class="keyword">var</span> getA2 = getA.bind(a);</div><div class="line">a.getA();<span class="comment">//"a in a"</span></div><div class="line">getA();<span class="comment">//a</span></div><div class="line">foo(a.getA);<span class="comment">//a</span></div><div class="line">getA2.call(b);<span class="comment">//"a in a"</span></div></pre></td></tr></table></figure></p>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="this" scheme="http://zeligzhou.github.io/tags/this/"/>
</entry>
<entry>
<title>ES6一二三</title>
<link href="http://zeligzhou.github.io/2015/12/12/es6-and-more/"/>
<id>http://zeligzhou.github.io/2015/12/12/es6-and-more/</id>
<published>2015-12-12T09:10:25.000Z</published>
<updated>2017-04-18T14:56:58.000Z</updated>
<content type="html"><![CDATA[<h2 id="ES6一些总结"><a href="#ES6一些总结" class="headerlink" title="ES6一些总结"></a>ES6一些总结</h2><p>ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的新标准,它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。ES6新增了一些值得思考的内容,下面来拜一拜最受瞩目的三个吧。</p>
<h3 id="Module"><a href="#Module" class="headerlink" title="Module"></a>Module</h3><p>ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// ES6模块</span></div><div class="line"><span class="keyword">import</span> { stat, exists, readFile } <span class="keyword">from</span> <span class="string">'fs'</span>;</div></pre></td></tr></table></figure></p>
<p>上面代码的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。<br><a id="more"></a><br>模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// profile.js</span></div><div class="line"><span class="keyword">var</span> firstName = <span class="string">'Michael'</span>;</div><div class="line"><span class="keyword">var</span> lastName = <span class="string">'Jackson'</span>;</div><div class="line"><span class="keyword">var</span> year = <span class="number">1958</span>;</div><div class="line"></div><div class="line"><span class="keyword">export</span> {firstName, lastName, year};</div></pre></td></tr></table></figure></p>
<p>使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// main.js</span></div><div class="line"><span class="keyword">import</span> {firstName, lastName, year} <span class="keyword">from</span> <span class="string">'./profile'</span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">setName</span>(<span class="params">element</span>) </span>{</div><div class="line"> element.textContent = firstName + <span class="string">' '</span> + lastName;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h3 id="let和const命令"><a href="#let和const命令" class="headerlink" title="let和const命令"></a>let和const命令</h3><p>ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> a = [];</div><div class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < <span class="number">10</span>; i++) {</div><div class="line"> a[i] = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(i);</div><div class="line"> };</div><div class="line">}</div><div class="line">a[<span class="number">6</span>](); <span class="comment">// 6</span></div></pre></td></tr></table></figure></p>
<p>想起了闭包的例子没,这就是块作用域的闭包特性。<br>const声明一个只读的常量。一旦声明,常量的值就不能改变。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> PI = <span class="number">3.1415</span>;</div><div class="line">PI <span class="comment">// 3.1415</span></div><div class="line"></div><div class="line">PI = <span class="number">3</span>;</div><div class="line"><span class="comment">// TypeError: Assignment to constant variable.</span></div></pre></td></tr></table></figure></p>
<h3 id="Promise-对象"><a href="#Promise-对象" class="headerlink" title="Promise 对象"></a>Promise 对象</h3><p>所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。<br>Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript引擎提供,不用自己部署。</p>
<p>resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。</p>
<p>Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。</p>
<p>then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Reject时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> promise = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve, reject</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'Promise'</span>);</div><div class="line"> resolve();</div><div class="line">});</div><div class="line"></div><div class="line">promise.then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'Resolved.'</span>);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(<span class="string">'Hi!'</span>);</div><div class="line"></div><div class="line"><span class="comment">// Promise</span></div><div class="line"><span class="comment">// Hi!</span></div><div class="line"><span class="comment">// Resolved</span></div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="ES6一些总结"><a href="#ES6一些总结" class="headerlink" title="ES6一些总结"></a>ES6一些总结</h2><p>ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的新标准,它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。ES6新增了一些值得思考的内容,下面来拜一拜最受瞩目的三个吧。</p>
<h3 id="Module"><a href="#Module" class="headerlink" title="Module"></a>Module</h3><p>ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// ES6模块</span></div><div class="line"><span class="keyword">import</span> &#123; stat, exists, readFile &#125; <span class="keyword">from</span> <span class="string">'fs'</span>;</div></pre></td></tr></table></figure></p>
<p>上面代码的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。<br>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="ES6" scheme="http://zeligzhou.github.io/tags/ES6/"/>
<category term="ECMAScript" scheme="http://zeligzhou.github.io/tags/ECMAScript/"/>
</entry>
<entry>
<title>Node.js实践</title>
<link href="http://zeligzhou.github.io/2015/09/09/nodejs-spider/"/>
<id>http://zeligzhou.github.io/2015/09/09/nodejs-spider/</id>
<published>2015-09-09T05:10:25.000Z</published>
<updated>2017-04-18T13:19:58.000Z</updated>
<content type="html"><![CDATA[<h2 id="Node-js做一个爬虫"><a href="#Node-js做一个爬虫" class="headerlink" title="Node.js做一个爬虫"></a>Node.js做一个爬虫</h2><p>一个临时的支线小任务,用node做一个爬虫,爬点贴吧的数据。</p>
<h3 id="Express"><a href="#Express" class="headerlink" title="Express"></a>Express</h3><p>express 是 Node.js 应用最广泛的 web 框架),可以用来建立一个强大的服务器端应用,包括中间件,模板引擎,路由等强大功能。<br>启动一个express最简单的服务代码如下:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 这句的意思就是引入 `express` 模块,并将它赋予 `express` 这个变量等待使用。</span></div><div class="line"><span class="keyword">var</span> express = <span class="built_in">require</span>(<span class="string">'express'</span>);</div><div class="line"><span class="comment">// 调用 express 实例,它是一个函数,不带参数调用时,会返回一个 express 实例,将这个变量赋予 app 变量。</span></div><div class="line"><span class="keyword">var</span> app = express();</div><div class="line"></div><div class="line"><span class="comment">// app 本身有很多方法,其中包括最常用的 get、post、put/patch、delete,在这里我们调用其中的 get 方法,为我们的 `/` 路径指定一个 handler 函数。</span></div><div class="line"><span class="comment">// 这个 handler 函数会接收 req 和 res 两个对象,他们分别是请求的 request 和 response。</span></div><div class="line"><span class="comment">// request 中包含了浏览器传来的各种信息,比如 query 啊,body 啊,headers 啊之类的,都可以通过 req 对象访问到。</span></div><div class="line"><span class="comment">// res 对象,我们一般不从里面取信息,而是通过它来定制我们向浏览器输出的信息,比如 header 信息,比如想要向浏览器输出的内容。这里我们调用了它的 #send 方法,向浏览器输出一个字符串。</span></div><div class="line">app.get(<span class="string">'/'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">req, res</span>) </span>{</div><div class="line"> res.send(<span class="string">'Hello World'</span>);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="comment">// 定义好我们 app 的行为之后,让它监听本地的 3000 端口。这里的第二个函数是个回调函数,会在 listen 动作成功后执行,我们这里执行了一个命令行输出操作,告诉我们监听动作已完成。</span></div><div class="line">app.listen(<span class="number">3000</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'app is listening at port 3000'</span>);</div><div class="line">});</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<h3 id="CasperJS"><a href="#CasperJS" class="headerlink" title="CasperJS"></a>CasperJS</h3><p>CasperJS是一个开源的导航脚本处理和测试工具,基于PhantomJS(前端自动化测试工具)编写。CasperJS简化了完整的导航场景的过程定义,提供了用于完成常见任务的实用的高级函数、方法和语法。<br>启动一个casper服务代码如下:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> casper = <span class="built_in">require</span>(<span class="string">'casper'</span>).create({ </div><div class="line"> <span class="attr">verbose</span>: <span class="literal">true</span>, </div><div class="line"> <span class="attr">logLevel</span>: <span class="string">'debug'</span> </div><div class="line">}); </div><div class="line"></div><div class="line"><span class="comment">// start中可以什么都不写 </span></div><div class="line">casper.start(); </div><div class="line"> </div><div class="line"> </div><div class="line"><span class="comment">// 这句很重要,如果没有设置userAgent,则很多website会拒绝访问 </span></div><div class="line"><span class="keyword">var</span> userAgentString = <span class="string">'Mozilla/5.0 (Macintosh; Intel Mac OS X)'</span>; </div><div class="line">casper.userAgent(userAgentString);</div></pre></td></tr></table></figure></p>
<p>CasperJS打开一个页面后,会建立一个沙箱,沙箱就相当于浏览器啦,可以使用浏览器文档对象的一些方法拿到想要的信息。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 遍历列表 </span></div><div class="line"> <span class="keyword">this</span>.thenOpen(opts.url,<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{ </div><div class="line"> <span class="keyword">var</span> res = <span class="keyword">this</span>.evaluate(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{ </div><div class="line"> <span class="comment">// 沙箱里面不能用_,只能用for,因为_不能传入沙箱 </span></div><div class="line"> <span class="keyword">var</span> aString = <span class="string">"a.j_th_tit"</span>; </div><div class="line"> <span class="keyword">var</span> rst = []; </div><div class="line"> <span class="keyword">var</span> nodeList = <span class="built_in">document</span>.querySelectorAll(aString); </div><div class="line"> <span class="keyword">var</span> nxtString = <span class="string">".pagination-item.next"</span>;</div><div class="line"> <span class="keyword">var</span> nxt = <span class="built_in">document</span>.querySelector(nxtString).getAttribute(<span class="string">"href"</span>); </div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < nodeList.length; i++) { </div><div class="line"> <span class="keyword">var</span> node = nodeList[i]; </div><div class="line"> <span class="keyword">var</span> title = node.innerHTML; </div><div class="line"> <span class="keyword">var</span> url = node.getAttribute(<span class="string">"href"</span>); </div><div class="line"> <span class="keyword">if</span>(url.indexOf(<span class="string">"http://"</span>)==<span class="number">-1</span>){ </div><div class="line"> url = location.origin+url; </div><div class="line"> } </div><div class="line"> rst.push({<span class="attr">title</span>:title,<span class="attr">url</span>:url}); </div><div class="line"> }; </div><div class="line"> <span class="keyword">return</span> {<span class="attr">rst</span>:rst,<span class="attr">nxt</span>:nxt}; </div><div class="line"> }); </div><div class="line"> list = res.rst;</div><div class="line"> nextP = res.nxt;</div><div class="line"> });</div></pre></td></tr></table></figure></p>
<p>完整demo见<a href="https://github.com/zeligzhou/spider" target="_blank" rel="external">我的spider</a>。</p>
]]></content>
<summary type="html">
<h2 id="Node-js做一个爬虫"><a href="#Node-js做一个爬虫" class="headerlink" title="Node.js做一个爬虫"></a>Node.js做一个爬虫</h2><p>一个临时的支线小任务,用node做一个爬虫,爬点贴吧的数据。</p>
<h3 id="Express"><a href="#Express" class="headerlink" title="Express"></a>Express</h3><p>express 是 Node.js 应用最广泛的 web 框架),可以用来建立一个强大的服务器端应用,包括中间件,模板引擎,路由等强大功能。<br>启动一个express最简单的服务代码如下:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 这句的意思就是引入 `express` 模块,并将它赋予 `express` 这个变量等待使用。</span></div><div class="line"><span class="keyword">var</span> express = <span class="built_in">require</span>(<span class="string">'express'</span>);</div><div class="line"><span class="comment">// 调用 express 实例,它是一个函数,不带参数调用时,会返回一个 express 实例,将这个变量赋予 app 变量。</span></div><div class="line"><span class="keyword">var</span> app = express();</div><div class="line"></div><div class="line"><span class="comment">// app 本身有很多方法,其中包括最常用的 get、post、put/patch、delete,在这里我们调用其中的 get 方法,为我们的 `/` 路径指定一个 handler 函数。</span></div><div class="line"><span class="comment">// 这个 handler 函数会接收 req 和 res 两个对象,他们分别是请求的 request 和 response。</span></div><div class="line"><span class="comment">// request 中包含了浏览器传来的各种信息,比如 query 啊,body 啊,headers 啊之类的,都可以通过 req 对象访问到。</span></div><div class="line"><span class="comment">// res 对象,我们一般不从里面取信息,而是通过它来定制我们向浏览器输出的信息,比如 header 信息,比如想要向浏览器输出的内容。这里我们调用了它的 #send 方法,向浏览器输出一个字符串。</span></div><div class="line">app.get(<span class="string">'/'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">req, res</span>) </span>&#123;</div><div class="line"> res.send(<span class="string">'Hello World'</span>);</div><div class="line">&#125;);</div><div class="line"></div><div class="line"><span class="comment">// 定义好我们 app 的行为之后,让它监听本地的 3000 端口。这里的第二个函数是个回调函数,会在 listen 动作成功后执行,我们这里执行了一个命令行输出操作,告诉我们监听动作已完成。</span></div><div class="line">app.listen(<span class="number">3000</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'app is listening at port 3000'</span>);</div><div class="line">&#125;);</div></pre></td></tr></table></figure></p>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="NodeJS" scheme="http://zeligzhou.github.io/tags/NodeJS/"/>
<category term="Express" scheme="http://zeligzhou.github.io/tags/Express/"/>
<category term="CasperJs" scheme="http://zeligzhou.github.io/tags/CasperJs/"/>
</entry>
<entry>
<title>关于FastClick</title>
<link href="http://zeligzhou.github.io/2015/07/22/about-fastclick/"/>
<id>http://zeligzhou.github.io/2015/07/22/about-fastclick/</id>
<published>2015-07-22T11:42:25.000Z</published>
<updated>2017-04-18T12:32:46.000Z</updated>
<content type="html"><![CDATA[<p>由于移动端click事件的300ms延迟,很多人都选择了使用FastClick。但我在使用过程中遇到了一些问题。</p>
<h3 id="覆盖了自己封装的tap事件"><a href="#覆盖了自己封装的tap事件" class="headerlink" title="覆盖了自己封装的tap事件"></a>覆盖了自己封装的tap事件</h3><p>解决方法是给该元素添加class——“needsclick”,官方给出了Bootstrap下的解决方案:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">a</span> <span class="attr">class</span>=<span class="string">"dropdown-toggle needsclick"</span> <span class="attr">data-toggle</span>=<span class="string">"dropdown"</span>></span>Dropdown<span class="tag"></<span class="name">a</span>></span></div></pre></td></tr></table></figure></p>
<h3 id="AMD环境下引入失败"><a href="#AMD环境下引入失败" class="headerlink" title="AMD环境下引入失败"></a>AMD环境下引入失败</h3><p>比较严重的是在amd环境下,requirejs引入时候的bug。<br><a id="more"></a><br>源码是:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// AMD. Register as an anonymous module.</span></div><div class="line">define(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">return</span> FastClick;</div><div class="line">});</div></pre></td></tr></table></figure></p>
<p>显然不合规范,导致引入后作用域内未定义。<br>但修改为:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// AMD. Register as an anonymous module.</span></div><div class="line">define(FastClick);</div></pre></td></tr></table></figure></p>
<p>又会在检测浏览器时报错:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)</span></div><div class="line"><span class="keyword">if</span> (layer.style.msTouchAction === <span class="string">'none'</span> || layer.style.touchAction === <span class="string">'manipulation'</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>最后无奈,只好把amd环境下的定义去掉了。</p>
<p>Game over~</p>
]]></content>
<summary type="html">
<p>由于移动端click事件的300ms延迟,很多人都选择了使用FastClick。但我在使用过程中遇到了一些问题。</p>
<h3 id="覆盖了自己封装的tap事件"><a href="#覆盖了自己封装的tap事件" class="headerlink" title="覆盖了自己封装的tap事件"></a>覆盖了自己封装的tap事件</h3><p>解决方法是给该元素添加class——“needsclick”,官方给出了Bootstrap下的解决方案:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">"dropdown-toggle needsclick"</span> <span class="attr">data-toggle</span>=<span class="string">"dropdown"</span>&gt;</span>Dropdown<span class="tag">&lt;/<span class="name">a</span>&gt;</span></div></pre></td></tr></table></figure></p>
<h3 id="AMD环境下引入失败"><a href="#AMD环境下引入失败" class="headerlink" title="AMD环境下引入失败"></a>AMD环境下引入失败</h3><p>比较严重的是在amd环境下,requirejs引入时候的bug。<br>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="FastClick" scheme="http://zeligzhou.github.io/tags/FastClick/"/>
<category term="amd" scheme="http://zeligzhou.github.io/tags/amd/"/>
<category term="requirejs" scheme="http://zeligzhou.github.io/tags/requirejs/"/>
</entry>
<entry>
<title>Amazing CSS</title>
<link href="http://zeligzhou.github.io/2015/03/26/amazing-CSS3/"/>
<id>http://zeligzhou.github.io/2015/03/26/amazing-CSS3/</id>
<published>2015-03-26T02:23:45.000Z</published>
<updated>2017-04-18T13:00:44.000Z</updated>
<content type="html"><![CDATA[<p>一些牛逼哄哄的CSS的玩法。</p>
<h3 id="设置选中文字的背景色。现在选中后为马卡龙绿色。"><a href="#设置选中文字的背景色。现在选中后为马卡龙绿色。" class="headerlink" title="设置选中文字的背景色。现在选中后为马卡龙绿色。"></a>设置选中文字的背景色。现在选中后为马卡龙绿色。</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="selector-pseudo">::selection</span> {</div><div class="line"> <span class="attribute">background</span>: <span class="number">#DB4F33</span>;</div><div class="line"> <span class="attribute">color</span>: white;</div><div class="line"> <span class="attribute">text-shadow</span>: none;</div><div class="line">}</div></pre></td></tr></table></figure>
<a id="more"></a>
<h3 id="webkit-perspective可以用来设置透视的度数,呈现3D立体感。"><a href="#webkit-perspective可以用来设置透视的度数,呈现3D立体感。" class="headerlink" title="-webkit-perspective可以用来设置透视的度数,呈现3D立体感。"></a>-webkit-perspective可以用来设置透视的度数,呈现3D立体感。</h3><p>origin为透视原点(底部位置)。<br><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.cls</span>{</div><div class="line"> <span class="attribute">-webkit-perspective</span>: <span class="number">800</span>;</div><div class="line"> <span class="attribute">-webkit-perspective-origin</span>: <span class="number">50%</span> <span class="number">200px</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>perspective的最佳大小为显示器宽像素*(人眼距显示器距离/显示器宽度)。<br>当translateZ极限接近perspective值的时候,元素会占满整个屏幕。<br>在3D的世界里,rotate是沿着中轴线旋转的(此时另两个坐标的轴线一起转移),translate是沿着轴方向位移。<br>当元素是一个边长为200px的正方体。每个面都在旋转后z位移100px(因为是沿重点转),就能组成一个立方体。<br>这是我的<a href="http://keyof.me/" target="_blank" rel="external">demo</a>。<br>此外,perspective应用在“舞台”和“元素”二者身上的表现是不同的。见<a href="http://www.zhangxinxu.com/study/201209/transform-perspective-same-rotate.html" target="_blank" rel="external">大牛的demo</a>。</p>
<h3 id="box-shadow是个很神奇的东西,同border和background这类一起应用好直接能画图。"><a href="#box-shadow是个很神奇的东西,同border和background这类一起应用好直接能画图。" class="headerlink" title="box-shadow是个很神奇的东西,同border和background这类一起应用好直接能画图。"></a>box-shadow是个很神奇的东西,同border和background这类一起应用好直接能画图。</h3><p>见<a href="http://lynnandtonic.github.io/a-single-div/" target="_blank" rel="external">大牛的一个把box-shadow发挥到极致的网站</a>。<br>你可以试试这么写border出来分别是什么东东。<br><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.triangle</span> {</div><div class="line"> <span class="attribute">height</span>: <span class="number">0px</span>;</div><div class="line"> <span class="attribute">width</span>: <span class="number">0px</span>;</div><div class="line"> <span class="attribute">border</span>:<span class="number">100px</span> solid;</div><div class="line"> <span class="comment">/* Add color now */</span></div><div class="line"> <span class="attribute">border-color</span>: pink green yellow purple;</div><div class="line">}</div><div class="line"><span class="selector-class">.triangle2</span> {</div><div class="line"> <span class="attribute">height</span>: <span class="number">0px</span>;</div><div class="line"> <span class="attribute">width</span>: <span class="number">0px</span>;</div><div class="line"> <span class="attribute">border</span>:<span class="number">100px</span> solid;</div><div class="line"> <span class="attribute">border-color</span>: transparent transparent <span class="number">#DB4F33</span> transparent;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h3 id="自定义字体:"><a href="#自定义字体:" class="headerlink" title="自定义字体:"></a>自定义字体:</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">@<span class="keyword">font-face</span> {</div><div class="line"> <span class="attribute">font-family</span>: <span class="string">'MyWebFont'</span>;</div><div class="line"> <span class="attribute">src</span>: <span class="built_in">url</span>(<span class="string">'webfont.eot'</span>); <span class="comment">/* IE9 Compat Modes */</span></div><div class="line"> <span class="attribute">src</span>: <span class="built_in">url</span>(<span class="string">'webfont.eot?#iefix'</span>) <span class="built_in">format</span>(<span class="string">'embedded-opentype'</span>), <span class="comment">/* IE6-IE8 */</span></div><div class="line"> <span class="built_in">url</span>(<span class="string">'webfont.woff'</span>) <span class="built_in">format</span>(<span class="string">'woff'</span>), <span class="comment">/* Modern Browsers */</span></div><div class="line"> <span class="built_in">url</span>(<span class="string">'webfont.ttf'</span>) <span class="built_in">format</span>(<span class="string">'truetype'</span>), <span class="comment">/* Safari, Android, iOS */</span></div><div class="line"> <span class="built_in">url</span>(<span class="string">'webfont.svg#svgFontName'</span>) <span class="built_in">format</span>(<span class="string">'svg'</span>); <span class="comment">/* Legacy iOS */</span></div><div class="line">}</div><div class="line"><span class="comment">/* 这么调用 */</span></div><div class="line"><span class="selector-tag">body</span> {</div><div class="line"> <span class="attribute">font-family</span>: <span class="string">'MyWebFont'</span>, Fallback, sans-serif;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="剪裁路径clip-path"><a href="#剪裁路径clip-path" class="headerlink" title="剪裁路径clip-path"></a>剪裁路径clip-path</h3><p>来看看<a href="http://runjs.cn/code/ijpkosqw" target="_blank" rel="external">这个</a>。<br><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">a</span>{</div><div class="line"> <span class="attribute">display</span>:block;</div><div class="line"> <span class="attribute">position</span>: absolute;</div><div class="line"> <span class="attribute">left</span>: <span class="number">0</span>;</div><div class="line"> <span class="attribute">top</span>: <span class="number">0</span>;</div><div class="line"> <span class="attribute">width</span>: <span class="number">100vw</span>;</div><div class="line"> <span class="attribute">height</span>: <span class="number">115.625vw</span>;</div><div class="line"> <span class="attribute">-webkit-clip-path</span>: <span class="built_in">polygon</span>(0 0, 100% 50%, 0 100%);</div><div class="line"> <span class="attribute">clip-path</span>: <span class="built_in">polygon</span>(0 0, 100% 50%, 0 100%);</div><div class="line"> <span class="attribute">background</span>:<span class="number">#f00</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>有时候美术就是会有一些棒棒的设计,比如说三角形的选块,这在传统意义上的盒模型里是不好实现的,好在有CSS和SVG这种神一般的存在。<br>clip-path除了作为clip的替身,还是SVG clip-path属性的延伸。想要了解更多见<a href="http://www.zhangxinxu.com/wordpress/2014/12/css3-svg-clip-path/" target="_blank" rel="external">大牛的demo中的解析</a>。</p>
]]></content>
<summary type="html">
<p>一些牛逼哄哄的CSS的玩法。</p>
<h3 id="设置选中文字的背景色。现在选中后为马卡龙绿色。"><a href="#设置选中文字的背景色。现在选中后为马卡龙绿色。" class="headerlink" title="设置选中文字的背景色。现在选中后为马卡龙绿色。"></a>设置选中文字的背景色。现在选中后为马卡龙绿色。</h3><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="selector-pseudo">::selection</span> &#123;</div><div class="line"> <span class="attribute">background</span>: <span class="number">#DB4F33</span>;</div><div class="line"> <span class="attribute">color</span>: white;</div><div class="line"> <span class="attribute">text-shadow</span>: none;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</summary>
<category term="CSS" scheme="http://zeligzhou.github.io/categories/CSS/"/>
<category term="CSS3" scheme="http://zeligzhou.github.io/tags/CSS3/"/>
<category term="HTML5" scheme="http://zeligzhou.github.io/tags/HTML5/"/>
</entry>
<entry>
<title>F.I.S是个好工具</title>
<link href="http://zeligzhou.github.io/2015/01/17/FIS-a-good-tool/"/>
<id>http://zeligzhou.github.io/2015/01/17/FIS-a-good-tool/</id>
<published>2015-01-17T11:45:36.000Z</published>
<updated>2015-01-19T09:53:14.000Z</updated>
<content type="html"><![CDATA[<h2 id="FIS工具介绍"><a href="#FIS工具介绍" class="headerlink" title="FIS工具介绍"></a>FIS工具介绍</h2><p>最近为新项目做前端技术选型时顺便了解了一下百度推出的前端自动化开发框架——FIS。FIS在项目中为性能优化、模块化框架、开发规范、代码部署、开发流程等问题整套解决方案,为前端开发提供不少便利。</p>
<h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>如果你的系统中已经安装npm则只需要:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ npm install -g fis</div></pre></td></tr></table></figure></p>
<p>如果遇上过慢可以使用淘宝的<a href="http://npm.taobao.org/" target="_blank" rel="external">cnpm</a>镜像服务完成安装。<br><a id="more"></a></p>
<h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><p>FIS的使用可谓相当简单。几乎下面三条命令就可以走遍天下。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ fis install firstblood-demo</div><div class="line">$ fis release --md5 --dest ./output</div><div class="line">$ fis server start</div></pre></td></tr></table></figure></p>
<p>更详细的手册<a href="http://fis.baidu.com/docs/api/cli.html" target="_blank" rel="external">戳这里</a>。</p>
<h3 id="后端解决方案"><a href="#后端解决方案" class="headerlink" title="后端解决方案"></a>后端解决方案</h3><p>当然FIS并没有止步于纯前端工具链,而是可以模拟后台提供数据来模拟前端开发的所有要求。<br>其中<a href="http://oak.baidu.com/docs/fis-plus" target="_blank" rel="external">fis-plus</a>就是php语言的前端集成解决方案。这也是使FIS更实用的工程化案例之一。</p>
<h2 id="Jello"><a href="#Jello" class="headerlink" title="Jello"></a>Jello</h2><p><a href="http://oak.baidu.com/docs/jello" target="_blank" rel="external">Jello</a>是针对服务端为 JAVA + Velocity 的前端集成解决方案。<br>在 jello 中开发项目需要遵循一定的目录规范。</p>
<p>一个完整的项目包括两部分:</p>
<ul>
<li>前端部分:包含图片、样式、脚本、模板等一列前端资源。</li>
<li>后端部分:各类 java 资源 jar 配置项文件等。</li>
</ul>
<p>jello 的开发模式是让前端同学主要负责前端部分,编写 velocity 模板文件、js、css等,脱离后端环境直接在 jello 的环境里面运行。<br>后端同学主要负责后端数据的获取和页面渲染逻辑,合并前端编译产出,完成整个项目的开发。</p>
<p>这样的好处是只要制定好数据格式便可以并行开发。</p>
<h3 id="前端目录"><a href="#前端目录" class="headerlink" title="前端目录"></a>前端目录</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line">├── fis-conf.js</div><div class="line">├── page</div><div class="line">│ ├── doc</div><div class="line">│ ├── examples</div><div class="line">│ ├── index.vm</div><div class="line">│ └── layout</div><div class="line">├── server.conf</div><div class="line">├── static</div><div class="line">│ ├── favicon.ico</div><div class="line">│ ├── js</div><div class="line">│ ├── libs</div><div class="line">│ └── scss</div><div class="line">├── test</div><div class="line">│ ├── page</div><div class="line">│ ├── page.json</div><div class="line">│ └── page.jsp</div><div class="line">└── widget</div><div class="line"> ├── footer</div><div class="line"> ├── header</div><div class="line"> └── sidebarmenus</div></pre></td></tr></table></figure>
<h3 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h3><ul>
<li><code>fis-conf.js</code> 用来设置 fis 编译配置。</li>
<li><code>page</code> 用来存放各类页面级模板文件(.vm), 可以直接在jello 环境下预览。<ul>
<li><code>layout</code> 骨架 vm</li>
</ul>
</li>
<li><code>static</code> 用来存放各类静态资源,如:JS、CSS、image、swf…</li>
<li><code>test</code> 用来存放各类测试数据,其与page文件夹下的vm文件数据配置对应。还可配置ajax请求数据。</li>
<li><code>widget</code> 用来存放页面小片段,方便其他页面引用。</li>
<li><code>server.conf</code> 可用rewrite指定路由跳转地址。</li>
</ul>
<h3 id="产出目录"><a href="#产出目录" class="headerlink" title="产出目录"></a>产出目录</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">├── WEB-INF</div><div class="line">│ ├── config</div><div class="line">│ │ └── map.json</div><div class="line">│ ├── views</div><div class="line">│ │ ├── page</div><div class="line">│ │ └── widget</div><div class="line">├── static</div><div class="line">└── test</div></pre></td></tr></table></figure>
<p>将 jello 前端模块编译产出目录如上。</p>
<ul>
<li><code>WEB-INF/config/map.json</code> 静态资源表,便于后端定位静态资源。</li>
<li><code>WEB-INF/views</code> velocity 模板文件。</li>
<li><code>static</code> 静态资源,如果静态资源部署到了cdn 服务器上,后端环境则不需要此文件夹。</li>
<li><code>test</code> 用于本地环境调试,后端程序无需关注。</li>
</ul>
<p>Jello的命令行语法和FIS是一致的,开发中的API也可参考FIS。</p>
]]></content>
<summary type="html">
<h2 id="FIS工具介绍"><a href="#FIS工具介绍" class="headerlink" title="FIS工具介绍"></a>FIS工具介绍</h2><p>最近为新项目做前端技术选型时顺便了解了一下百度推出的前端自动化开发框架——FIS。FIS在项目中为性能优化、模块化框架、开发规范、代码部署、开发流程等问题整套解决方案,为前端开发提供不少便利。</p>
<h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>如果你的系统中已经安装npm则只需要:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ npm install -g fis</div></pre></td></tr></table></figure></p>
<p>如果遇上过慢可以使用淘宝的<a href="http://npm.taobao.org/" target="_blank" rel="external">cnpm</a>镜像服务完成安装。<br>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="NodeJS" scheme="http://zeligzhou.github.io/tags/NodeJS/"/>
<category term="FIS" scheme="http://zeligzhou.github.io/tags/FIS/"/>
</entry>
<entry>
<title>Grunt和前端工程化实践</title>
<link href="http://zeligzhou.github.io/2015/01/14/grunt-in-FE/"/>
<id>http://zeligzhou.github.io/2015/01/14/grunt-in-FE/</id>
<published>2015-01-14T05:03:39.000Z</published>
<updated>2017-04-18T12:31:08.000Z</updated>
<content type="html"><![CDATA[<h2 id="Grunt工具介绍"><a href="#Grunt工具介绍" class="headerlink" title="Grunt工具介绍"></a>Grunt工具介绍</h2><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>运行项目我们需要grunt-cli和yeoman和yo的一个webapp生成器,如果你的系统中已经安装npm则只需要:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">npm install -g grunt-cli</div><div class="line">npm install -g yo</div><div class="line">/* npm install -g generator-webapp */</div></pre></td></tr></table></figure></p>
<p>然后开始你的grunt之旅吧~<br><a id="more"></a></p>
<h3 id="Grunt配置"><a href="#Grunt配置" class="headerlink" title="Grunt配置"></a>Grunt配置</h3><p>Grunt的配置项在根目录的gruntfile.js下。<br>以sass为例<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// Compiles Sass to CSS and generates necessary files if requested</span></div><div class="line">sass: {</div><div class="line"> <span class="attr">options</span>: {</div><div class="line"> <span class="attr">loadPath</span>: <span class="string">'bower_components'</span></div><div class="line"> },</div><div class="line"> <span class="attr">dist</span>: {</div><div class="line"> <span class="attr">files</span>: [{</div><div class="line"> <span class="attr">expand</span>: <span class="literal">true</span>,</div><div class="line"> <span class="attr">cwd</span>: <span class="string">'<%= config.app %>/styles'</span>,</div><div class="line"> <span class="attr">src</span>: [<span class="string">'*.{scss,sass}'</span>],</div><div class="line"> <span class="attr">dest</span>: <span class="string">'dist/styles'</span>,</div><div class="line"> <span class="attr">ext</span>: <span class="string">'.css'</span></div><div class="line"> }]</div><div class="line"> },</div><div class="line"> <span class="attr">server</span>: {</div><div class="line"> <span class="attr">files</span>: [{</div><div class="line"> <span class="attr">expand</span>: <span class="literal">true</span>,</div><div class="line"> <span class="attr">cwd</span>: <span class="string">'<%= config.app %>/styles'</span>,</div><div class="line"> <span class="attr">src</span>: [<span class="string">'*.{scss,sass}'</span>],</div><div class="line"> <span class="attr">dest</span>: <span class="string">'.tmp/styles'</span>,</div><div class="line"> <span class="attr">ext</span>: <span class="string">'.css'</span></div><div class="line"> }]</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>里面配置了import源文件地址loadPath,文件源文件地址cwd和目的地址dest等等。<br>可以通过运行一下代码进行编译。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">grunt sass</div></pre></td></tr></table></figure></p>
<h3 id="Grunt压缩合并小案例"><a href="#Grunt压缩合并小案例" class="headerlink" title="Grunt压缩合并小案例"></a>Grunt压缩合并小案例</h3><p>压缩合并一些js应该算是最被需要的功能之一了,用Grunt来实现也尤为简单<br>首先需要安装grunt-contrib-concat和grunt-contrib-uglify插件。<br>然后按以下代码配置:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> (<span class="params">grunt</span>) </span>{</div><div class="line"> <span class="comment">// 项目配置</span></div><div class="line"> grunt.initConfig({</div><div class="line"> <span class="attr">pkg</span>: grunt.file.readJSON(<span class="string">'package.json'</span>),</div><div class="line"> <span class="attr">concat</span>: {</div><div class="line"> <span class="attr">options</span>: {</div><div class="line"> <span class="attr">separator</span>: <span class="string">';'</span></div><div class="line"> },</div><div class="line"> <span class="attr">dist</span>: {</div><div class="line"> <span class="attr">src</span>: [<span class="string">'src/zepto.js'</span>, <span class="string">'src/underscore.js'</span>, <span class="string">'src/backbone.js'</span>],</div><div class="line"> <span class="attr">dest</span>: <span class="string">'dest/libs.js'</span></div><div class="line"> }</div><div class="line"> },</div><div class="line"> <span class="attr">uglify</span>: {</div><div class="line"> <span class="attr">build</span>: {</div><div class="line"> <span class="attr">src</span>: <span class="string">'dest/libs.js'</span>,</div><div class="line"> <span class="attr">dest</span>: <span class="string">'dest/libs.min.js'</span></div><div class="line"> }</div><div class="line"> }</div><div class="line"> });</div><div class="line"> grunt.loadNpmTasks(<span class="string">'grunt-contrib-uglify'</span>);</div><div class="line"> grunt.loadNpmTasks(<span class="string">'grunt-contrib-concat'</span>);</div><div class="line"> <span class="comment">// 默认任务</span></div><div class="line"> grunt.registerTask(<span class="string">'default'</span>, [<span class="string">'concat'</span>, <span class="string">'uglify'</span>]);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>Zepto/underscore/backbone就打包成了观众们喜闻乐见的libs.js和压缩版libs.min.js啦。</p>
<p>当然咯,Grunt还有很多插件可以实现更多更强大的功能(比如单元测试),这些就在实践中出真知吧。</p>
]]></content>
<summary type="html">
<h2 id="Grunt工具介绍"><a href="#Grunt工具介绍" class="headerlink" title="Grunt工具介绍"></a>Grunt工具介绍</h2><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>运行项目我们需要grunt-cli和yeoman和yo的一个webapp生成器,如果你的系统中已经安装npm则只需要:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">npm install -g grunt-cli</div><div class="line">npm install -g yo</div><div class="line">/* npm install -g generator-webapp */</div></pre></td></tr></table></figure></p>
<p>然后开始你的grunt之旅吧~<br>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="NodeJS" scheme="http://zeligzhou.github.io/tags/NodeJS/"/>
<category term="grunt" scheme="http://zeligzhou.github.io/tags/grunt/"/>
</entry>
<entry>
<title>Knockout.js应用</title>
<link href="http://zeligzhou.github.io/2014/10/09/knockout-practice/"/>
<id>http://zeligzhou.github.io/2014/10/09/knockout-practice/</id>
<published>2014-10-09T08:19:25.000Z</published>
<updated>2017-04-18T12:00:50.000Z</updated>
<content type="html"><![CDATA[<p>Knockout是一个轻量级的UI类库,通过应用MVVM模式使JavaScript前端UI简单化。</p>
<h3 id="下载和安装"><a href="#下载和安装" class="headerlink" title="下载和安装"></a>下载和安装</h3><p><a href="https://github.com/knockout/knockout" target="_blank" rel="external">Github官网</a></p>
<h3 id="MVVM-和-View-Model"><a href="#MVVM-和-View-Model" class="headerlink" title="MVVM 和 View Model"></a>MVVM 和 View Model</h3><p>Model-View-View Model (MVVM) 是一种创建用户界面的设计模式。 描述的是如何将复杂的UI用户界面分成3个部分:</p>
<ul>
<li>model: 你程序里存储的数据。这个数据包括对象和业务操作(例如:银子账户可以完成转账功能), 并且独立于任何UI。使用KO的时候,通常说是向服务器调用Ajax读写这个存储的模型数据。</li>
<li><p>view model: 在UI上,纯code描述的数据以及操作。例如,如果你实现列表编辑,你的view model应该是一个包含列表项items的对象和暴露的add/remove列表项(item)的操作方法。</p>
<blockquote>
<p>注意这不是UI本身:它不包含任何按钮的概念或者显示风格。它也不是持续数据模型 – 包含用户正在使用的未保存数据。使用KO的时候,你的view models是不包含任何HTML知识的纯JavaScript 对象。保持view model抽象可以保持简单,以便你能管理更复杂的行为。</p>
</blockquote>
</li>
<li><p>view: 一个可见的,交互式的,表示view model状态的UI。 从view model显示数据,发送命令到view model(例如:当用户click按钮的时候) ,任何view model状态改变的时候更新。</p>
</li>
</ul>
<a id="more"></a>
<h3 id="简单的介绍一下"><a href="#简单的介绍一下" class="headerlink" title="简单的介绍一下"></a>简单的介绍一下</h3><p>其实简而言之一句话,MVVM就是用来实现数据的双向绑定,让你在开发的时候只更改数据而不用耗费精力处理显示的内容。<br>例如我们现在要在页面上做一个菜单的下拉列表,数据内容如下:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> availableMeals = [</div><div class="line"> { <span class="attr">mealName</span>: <span class="string">'Standard'</span>, <span class="attr">description</span>: <span class="string">'Dry crusts of bread'</span>, <span class="attr">extraCost</span>: <span class="number">0</span> },</div><div class="line"> { <span class="attr">mealName</span>: <span class="string">'Premium'</span>, <span class="attr">description</span>: <span class="string">'Fresh bread with cheese'</span>, <span class="attr">extraCost</span>: <span class="number">9.95</span> },</div><div class="line"> { <span class="attr">mealName</span>: <span class="string">'Deluxe'</span>, <span class="attr">description</span>: <span class="string">'Caviar and vintage Dr Pepper'</span>, <span class="attr">extraCost</span>: <span class="number">18.50</span> }</div><div class="line"> ];</div></pre></td></tr></table></figure></p>
<p>如果想让这3个选项显示到页面上,我们可以绑定一个下拉菜单(例如:select元素)到这个数据上。例如:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">h3</span>></span>Meal upgrades<span class="tag"></<span class="name">h3</span>></span></div><div class="line"><span class="tag"><<span class="name">p</span>></span>Make your flight more bearable by selecting a meal to match your social and economic status.<span class="tag"></<span class="name">p</span>></span></div><div class="line">Chosen meal: <span class="tag"><<span class="name">select</span> <span class="attr">data-bind</span>=<span class="string">"options: availableMeals,optionsText: 'mealName'"</span>></span><span class="tag"></<span class="name">select</span>></span></div></pre></td></tr></table></figure></p>
<p>启用Knockout并使你的绑定生效,在availableMeals变量声明之后添加如下代码:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> viewModel = {</div><div class="line"> <span class="comment">/* we'll populate this in a moment */</span></div><div class="line">};</div><div class="line"></div><div class="line">ko.applyBindings(viewModel); <span class="comment">// Makes Knockout get to work</span></div><div class="line"><span class="comment">// 注意:ko. applyBindings需要在上述HTML之后应用才有效</span></div></pre></td></tr></table></figure></p>
<p>下一步,声明一个简单的data model来描述旅客已经选择的套餐,添加一个属性到当前的view model上:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> viewModel = {</div><div class="line"> <span class="attr">chosenMeal</span>: ko.observable(availableMeals[<span class="number">0</span>])</div><div class="line">};</div></pre></td></tr></table></figure></p>
<p>ko.observable是什么?它是KO里的一个基础概念。UI可以监控(observe)它的值并且回应它的变化。这里我们设置chosenMeal是UI可以监控已经选择的套餐,并初始化它,使用availableMeal里的第一个值作为它的默认值(例如:Standard)。</p>
<p>让我们将chosenMeal 关联到下拉菜单上,仅仅是更新select的data-bind属性,告诉它让select元素的值读取/写入chosenMeal这个模型属性:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">Chosen meal: <span class="tag"><<span class="name">select</span> <span class="attr">data-bind</span>=<span class="string">"options: availableMeals,</span></span></div><div class="line"> optionsText: 'mealName',</div><div class="line"> value: chosenMeal"><span class="tag"></<span class="name">select</span>></span></div></pre></td></tr></table></figure></p>
<p>理论上说,我们现在可以读/写chosenMeal 属性了,但是我们不知道它的作用。让我们来显示已选择套餐的描述和价格:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">p</span>></span></div><div class="line"> You've chosen:</div><div class="line"> <span class="tag"><<span class="name">b</span> <span class="attr">data-bind</span>=<span class="string">"text: chosenMeal().description"</span>></span><span class="tag"></<span class="name">b</span>></span></div><div class="line"> (price: <span class="tag"><<span class="name">span</span> <span class="attr">data-bind</span>=<span class="string">'text: chosenMeal().extraCost'</span>></span><span class="tag"></<span class="name">span</span>></span>)</div><div class="line"><span class="tag"></<span class="name">p</span>></span></div></pre></td></tr></table></figure></p>
<p>好啦,一个最简单的数据双向绑定完成啦。</p>
]]></content>
<summary type="html">
<p>Knockout是一个轻量级的UI类库,通过应用MVVM模式使JavaScript前端UI简单化。</p>
<h3 id="下载和安装"><a href="#下载和安装" class="headerlink" title="下载和安装"></a>下载和安装</h3><p><a href="https://github.com/knockout/knockout" target="_blank" rel="external">Github官网</a></p>
<h3 id="MVVM-和-View-Model"><a href="#MVVM-和-View-Model" class="headerlink" title="MVVM 和 View Model"></a>MVVM 和 View Model</h3><p>Model-View-View Model (MVVM) 是一种创建用户界面的设计模式。 描述的是如何将复杂的UI用户界面分成3个部分:</p>
<ul>
<li>model: 你程序里存储的数据。这个数据包括对象和业务操作(例如:银子账户可以完成转账功能), 并且独立于任何UI。使用KO的时候,通常说是向服务器调用Ajax读写这个存储的模型数据。</li>
<li><p>view model: 在UI上,纯code描述的数据以及操作。例如,如果你实现列表编辑,你的view model应该是一个包含列表项items的对象和暴露的add/remove列表项(item)的操作方法。</p>
<blockquote>
<p>注意这不是UI本身:它不包含任何按钮的概念或者显示风格。它也不是持续数据模型 – 包含用户正在使用的未保存数据。使用KO的时候,你的view models是不包含任何HTML知识的纯JavaScript 对象。保持view model抽象可以保持简单,以便你能管理更复杂的行为。</p>
</blockquote>
</li>
<li><p>view: 一个可见的,交互式的,表示view model状态的UI。 从view model显示数据,发送命令到view model(例如:当用户click按钮的时候) ,任何view model状态改变的时候更新。</p>
</li>
</ul>
</summary>
<category term="Javascript" scheme="http://zeligzhou.github.io/categories/Javascript/"/>
<category term="Knockout" scheme="http://zeligzhou.github.io/tags/Knockout/"/>
<category term="MVVM" scheme="http://zeligzhou.github.io/tags/MVVM/"/>
<category term="ViewModel" scheme="http://zeligzhou.github.io/tags/ViewModel/"/>
</entry>
<entry>
<title>Debut</title>
<link href="http://zeligzhou.github.io/2014/06/25/debut/"/>
<id>http://zeligzhou.github.io/2014/06/25/debut/</id>
<published>2014-06-25T09:06:59.000Z</published>
<updated>2016-08-20T16:50:38.000Z</updated>
<content type="html"><![CDATA[<h2 id="基本的Git指令"><a href="#基本的Git指令" class="headerlink" title="基本的Git指令"></a>基本的Git指令</h2><h4 id="从github下载内容"><a href="#从github下载内容" class="headerlink" title="从github下载内容"></a>从github下载内容</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="built_in">clone</span> https://github.com:xxxx/xxxx.git</div></pre></td></tr></table></figure>
<h4 id="添加github仓库并获取数据"><a href="#添加github仓库并获取数据" class="headerlink" title="添加github仓库并获取数据"></a>添加github仓库并获取数据</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git remote add origin https://github.com:xxxx/xxxx.git</div><div class="line">git pull <远程主机名> <远程分支名><span class="comment"># 抓取远程仓库所有分支更新并合并到本地</span></div></pre></td></tr></table></figure>
<p>pull相当于:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">git fetch origin master</div><div class="line">git <span class="built_in">log</span> -p master..origin/master</div><div class="line">git merge origin/master</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<h4 id="提交本地内容到远程分支"><a href="#提交本地内容到远程分支" class="headerlink" title="提交本地内容到远程分支"></a>提交本地内容到远程分支</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">git add .</div><div class="line">git commit -m <span class="string">"更新提示"</span></div><div class="line">git push origin gh-pages <span class="comment">#提交到gh-pages分支</span></div></pre></td></tr></table></figure>
<h4 id="切换分支(没有即创建)"><a href="#切换分支(没有即创建)" class="headerlink" title="切换分支(没有即创建)"></a>切换分支(没有即创建)</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git checkout -b ph-pages</div></pre></td></tr></table></figure>
<h4 id="建立SSH-Key需要关联github"><a href="#建立SSH-Key需要关联github" class="headerlink" title="建立SSH Key需要关联github"></a>建立SSH Key需要关联github</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ ssh -T git@github.com</div></pre></td></tr></table></figure>
<p>原文输入后,按提示再输入‘yes’即可。<br>更多指南在<a href="http://www.ruanyifeng.com/blog/2014/06/git_remote.html" target="_blank" rel="external">(1)</a>和<a href="http://www.jianshu.com/p/05289a4bc8b2" target="_blank" rel="external">(2)</a>。</p>
<h2 id="熟悉一下Markdown"><a href="#熟悉一下Markdown" class="headerlink" title="熟悉一下Markdown"></a>熟悉一下Markdown</h2><h3 id="标题分级"><a href="#标题分级" class="headerlink" title="标题分级"></a>标题分级</h3><h4 id="无序列表"><a href="#无序列表" class="headerlink" title="无序列表"></a>无序列表</h4><ul>
<li>这个是<a href="http://keyof.me" target="_blank" rel="external">超链接</a></li>
<li><em>强调</em></li>
</ul>
<h4 id="有序列表"><a href="#有序列表" class="headerlink" title="有序列表"></a>有序列表</h4><p>代办事项:</p>
<ol>
<li>样式需要调整</li>
<li>上传一些图片</li>
</ol>
<h3 id="还有引用层级"><a href="#还有引用层级" class="headerlink" title="还有引用层级"></a>还有引用层级</h3><blockquote>
<p>一级引用</p>
<blockquote>
<p>二级引用</p>
</blockquote>
<p>回到一级</p>
</blockquote>
<hr>
<p>上面是分割线</p>
<h2 id="HEXO指令"><a href="#HEXO指令" class="headerlink" title="HEXO指令"></a>HEXO指令</h2><p>当hexo项目上传到github CSS失效<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ hexo clean</div></pre></td></tr></table></figure></p>
<p>其他hexo指令<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">hexo g == hexo generate</div><div class="line">hexo d == hexo deploy</div><div class="line">hexo s == hexo server</div><div class="line">hexo n == hexo new</div><div class="line">hexo d -g == hexo generate && hexo deploy</div><div class="line">hexo s -g == hexo generate && hexo server</div></pre></td></tr></table></figure></p>
<hr>
<p>HTML也适用吗?</p>
<p></p><h4>第四级标题</h4><br>不会在文档结构里。<br><br><p></p>
<p>今天就到此为止吧,^o^</p>]]></content>
<summary type="html">
<h2 id="基本的Git指令"><a href="#基本的Git指令" class="headerlink" title="基本的Git指令"></a>基本的Git指令</h2><h4 id="从github下载内容"><a href="#从github下载内容" class="headerlink" title="从github下载内容"></a>从github下载内容</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="built_in">clone</span> https://github.com:xxxx/xxxx.git</div></pre></td></tr></table></figure>
<h4 id="添加github仓库并获取数据"><a href="#添加github仓库并获取数据" class="headerlink" title="添加github仓库并获取数据"></a>添加github仓库并获取数据</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git remote add origin https://github.com:xxxx/xxxx.git</div><div class="line">git pull &lt;远程主机名&gt; &lt;远程分支名&gt;<span class="comment"># 抓取远程仓库所有分支更新并合并到本地</span></div></pre></td></tr></table></figure>
<p>pull相当于:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">git fetch origin master</div><div class="line">git <span class="built_in">log</span> -p master..origin/master</div><div class="line">git merge origin/master</div></pre></td></tr></table></figure></p>
</summary>
<category term="Learn" scheme="http://zeligzhou.github.io/categories/Learn/"/>
<category term="git" scheme="http://zeligzhou.github.io/tags/git/"/>
<category term="github" scheme="http://zeligzhou.github.io/tags/github/"/>
<category term="markdown" scheme="http://zeligzhou.github.io/tags/markdown/"/>
<category term="hexo" scheme="http://zeligzhou.github.io/tags/hexo/"/>
</entry>
</feed>