-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
896 lines (673 loc) · 104 KB
/
Copy pathindex.html
File metadata and controls
896 lines (673 loc) · 104 KB
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
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>
NULL
</title>
<meta property="og:type" content="website">
<meta property="og:title" content="NULL">
<meta property="og:url" content="https://cuijing1031.github.io/index.html">
<meta property="og:site_name" content="NULL">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="NULL">
<link rel="alternative" href="/atom.xml" title="NULL" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<link rel="stylesheet" href="/perfect-scrollbar/css/perfect-scrollbar.min.css">
<link rel="stylesheet" href="/styles/main.css">
</head>
<body
class="monochrome"
>
<div class="mobile-header">
<button class="sidebar-toggle" type="button">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="title" href="/">NULL</a>
</div>
<div class="main-container">
<div class="sidebar">
<div class="header">
<h1 class="title"><a href="/">NULL</a></h1>
<div class="info">
<div class="content">
<div class="author">Candy.J</div>
</div>
<div class="avatar">
<a href="/about"><img src="/images/avatar.gif"></a>
</div>
</div>
</div>
<div class="body">
<ul class="nav">
<li class="category-list-container">
<a href="javascript:;">分类</a>
<ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/CSS/">CSS</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/web/">web</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/工程化/">工程化</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/语言/">语言</a><span class="category-list-count">1</span></li></ul>
</li>
<li class="tag-list-container">
<a href="javascript:;">标签</a>
<ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/CSS/">CSS</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/flow/">flow</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/javascript/">javascript</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/javascript-canvas/">javascript canvas</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/webpack/">webpack</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/基础知识/">基础知识</a><span class="tag-list-count">1</span></li></ul>
</li>
<li class="archive-list-container">
<a href="javascript:;">归档</a>
<ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/">2017</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/">2016</a><span class="archive-list-count">6</span></li></ul>
</li>
</ul>
<ul class="nav">
<li>
<a href="/" title="Homepage">Homepage</a>
</li>
<li>
<a href="/archives" title="By Year">By Year</a>
</li>
</ul>
<ul class="nav">
<li>
<a href="https://github.com/cuijing1031" title="Github" target="_blank" rel="external">Github</a>
</li>
</ul>
</div>
</div>
<div class="main-content">
<div style="max-width: 1000px">
<div class="post-list">
<div class="post-list-item article">
<h3 class="article-header">
<a href="/2017/03/20/基于canvas的图像预加载/" >
基于canvas的图像预加载
</a>
</h3>
<div class="article-info">
<a href="/2017/03/20/基于canvas的图像预加载/"><span class="article-date">
2017-03-20
</span>
</a>
<span class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/javascript-canvas/">javascript canvas</a></li></ul>
</span>
</div>
<div class="article-entry">
<p>在图片多的页面中,为了提高用户体验,我们会对图片进行压缩,采用更小的图片格式让图片尽可能快的展现给用户。在浏览medium.freecodecamp.com中一些文章时,偶然发现在网速不好的时候,会先看到一张模糊的图片,然后再展示出清晰的图。于是打开控制台抓了一下资源,发现展现出的第一张模糊的图片大小只有30*30。通过预加载一张小的图片,可以快速的展示给用户一些东西,减少中间的空白时间。看一看源码,发现是基于cancas来实现的。下面来看看它是怎么做的吧</p>
<p>首先我们有两张图<br>一张是原始图像:<br><img src="/images/canvas-blur-demo.png" style="width:400px;margin:0 auto;display:block;" alt="demo"><br>另一张是 30*30 的小图:<br><img src="/images/canvas-blur-demo-20.png" style="width:30px;margin:0 auto;display:block;" alt="demo20"></p>
<p>图片展示的 html 结构如下,原始图像我们先通过 visibility:hidden 隐藏起来。</p>
<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">div</span> <span class="attr">class</span>=<span class="string">"img-container is-canvasLoaded"</span> <span class="attr">img-src</span>=<span class="string">"./demo.png"</span>></span></div><div class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"./demo_min.png"</span> <span class="attr">id</span>=<span class="string">"imgdemo"</span> <span class="attr">alt</span>=<span class="string">""</span> <span class="attr">style</span>=<span class="string">"opacity:0;position: absolute;z-index: -1;"</span>></span></div><div class="line"> <span class="tag"><<span class="name">canvas</span> <span class="attr">id</span>=<span class="string">"canvas-container"</span>></span><span class="tag"></<span class="name">canvas</span>></span></div><div class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"./demo2.png"</span> <span class="attr">alt</span>=<span class="string">""</span> <span class="attr">id</span>=<span class="string">"origin-img"</span> <span class="attr">style</span>=<span class="string">"opacity:0"</span>></span></div><div class="line"><span class="tag"></<span class="name">div</span>></span></div></pre></td></tr></table></figure>
<p>初始时设置 canvas 的大小略大于我们的 demo_min.png 图片,如 75 * 75,然后:</p>
<ul>
<li>获取 demo_min.png 大小 60 * 30</li>
<li>根据 demo_min.png 的比例,设置一下 canvas 的比例 75 * 37.5</li>
</ul>
<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="keyword">var</span> imgDemoSize = {</div><div class="line"> <span class="attr">width</span>: imgDemo.offsetWidth,</div><div class="line"> <span class="attr">height</span>: imgDemo.offsetHeight</div><div class="line">}</div><div class="line"><span class="keyword">var</span> scale = imgDemoSize.width / imgDemoSize.height > canvasSize.width / canvasSize.height ? canvasSize.width / imgDemoSize.width : canvasSize.height / imgDemoSize.height</div><div class="line"><span class="keyword">var</span> scaleSize = {</div><div class="line"> <span class="attr">width</span>: imgDemoSize.width * scale,</div><div class="line"> <span class="attr">height</span>: imgDemoSize.height * scale,</div><div class="line">}</div><div class="line">canvasDom.width = scaleSize.width</div><div class="line">canvasDom.height = scaleSize.height</div></pre></td></tr></table></figure>
<p>现在html结构如下:</p>
<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">div</span> <span class="attr">class</span>=<span class="string">"img-container is-canvasLoaded"</span> <span class="attr">img-src</span>=<span class="string">"./demo.png"</span>></span></div><div class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">src</span>=<span class="string">"./demo_min.png"</span> <span class="attr">id</span>=<span class="string">"imgdemo"</span> <span class="attr">alt</span>=<span class="string">""</span> <span class="attr">style</span>=<span class="string">"opacity:0;position: absolute;z-index: -1;"</span>></span></div><div class="line"> <span class="tag"><<span class="name">canvas</span> <span class="attr">id</span>=<span class="string">"canvas-container"</span> <span class="attr">width</span>=<span class="string">"75"</span> <span class="attr">height</span>=<span class="string">"37></canvas></span></span></div><div class="line"> <img src="<span class="attr">.</span>/<span class="attr">demo2.png</span>" <span class="attr">alt</span>=<span class="string">""</span> <span class="attr">id</span>=<span class="string">"origin-img"</span> <span class="attr">style</span>=<span class="string">"opacity:0"</span>></div><div class="line"><span class="tag"></<span class="name">div</span>></span></div></pre></td></tr></table></figure>
<p>将图像画在 canvas 上:</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></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> context = canvasDom.getContext(<span class="string">'2d'</span>)</div><div class="line"><span class="comment">// drawImage可以是HTMLImageElement</span></div><div class="line">context.drawImage(imgDemo, <span class="number">0</span>,<span class="number">0</span>,<span class="number">60</span>,<span class="number">30</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">75</span>,<span class="number">37</span>)</div></pre></td></tr></table></figure>
<p>canvas 的 drawImage 方法的第一个参数,允许是 HTMLImageElement 。所以这里直接用 img 元素比较方便。图像画在 canvas 上之后,我们就可以通过 canvas 的 getImageData 方法来获取图像的像素,然后对图像进行高斯模糊处理。模糊处理这里直接使用了 <a href="https://github.com/flozz/StackBlur" target="_blank" rel="external">stackblur.js</a> 。想了解高斯模糊原理的可以参考<a href="http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html" target="_blank" rel="external">高斯模糊的算法</a></p>
<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="keyword">var</span> imgData = context.getImageData(<span class="number">0</span>,<span class="number">0</span>,<span class="number">75</span>,<span class="number">37</span>)</div><div class="line"><span class="keyword">var</span> blurImgData = StackBlur.imageDataRGBA(imgData, <span class="number">0</span>,<span class="number">0</span>, <span class="number">75</span>, <span class="number">37</span>, <span class="number">5</span>);</div></pre></td></tr></table></figure>
<p>模糊处理完之后,putImageData 放在 canvas 中</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">context.putImageData(blurImgData, <span class="number">0</span>, <span class="number">0</span>);</div></pre></td></tr></table></figure>
<p>然后展示 canvas , 到此页面上会展示一张模糊的图。</p>
<p><img src="/images/canvas-blur-result.png" style="width:60%;margin:0 auto;display:block;" alt="blur-result"></p>
<p>模糊图片出来了,原始图像什么时候展示呢?<br>使用 Img 的 load 事件,原始的图像加载完成后触发 load 事件,将 canvas 隐藏,展示原始图像。</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></pre></td><td class="code"><pre><div class="line">imgOrigin.addEventListener(<span class="string">'load'</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> imgOrigin.style.opacity = <span class="number">1</span></div><div class="line"> canvasDom.style.opacity = <span class="number">0</span></div><div class="line">})</div></pre></td></tr></table></figure>
<p>在网速略慢时,我们就会看到页面上会先出现一张模糊的图,然后再呈现出清晰的图。此外可以用 css 的 transition 属性,增加模糊图和原始图 opacity 过度时间,让图片之间的切换看起来更为自然顺畅。</p>
</div>
</div>
<a class="read-all-link" href="/2017/03/20/基于canvas的图像预加载/">阅读全部</a>
</div>
<div class="post-list">
<div class="post-list-item article">
<h3 class="article-header">
<a href="/2016/12/28/webpack-DefinePlugin介绍/" >
webpack.DefinePlugin介绍
</a>
</h3>
<div class="article-info">
<a href="/2016/12/28/webpack-DefinePlugin介绍/"><span class="article-date">
2016-12-28
</span>
</a>
<span class="article-category tagcloud">
<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/工程化/">工程化</a></li></ul>
</span>
<span class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/webpack/">webpack</a></li></ul>
</span>
</div>
<div class="article-entry">
<h5 id="基本用法"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法</h5><p>这个插件用来定义全局变量,在webpack打包的时候会对这些变量做替换。<br>先看个例子</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><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></pre></td><td class="code"><pre><div class="line"><span class="comment">//webpack.config.js</span></div><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> path = <span class="built_in">require</span>(<span class="string">'path'</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>: {</div><div class="line"> <span class="attr">index</span>: <span class="string">"./js/index.js"</span></div><div class="line"> },</div><div class="line"> <span class="attr">output</span>: {</div><div class="line"> <span class="attr">path</span>: <span class="string">"./dist/"</span>,</div><div class="line"> <span class="attr">filename</span>: <span class="string">"js/[name].js"</span>,</div><div class="line"> <span class="attr">chunkFilename</span>: <span class="string">"js/[name].js"</span></div><div class="line"> },</div><div class="line"> <span class="attr">plugins</span>: [</div><div class="line"> <span class="keyword">new</span> webpack.DefinePlugin({</div><div class="line"> <span class="attr">SOMETHINE</span>: <span class="string">'This is something we needed.'</span></div><div class="line"> })</div><div class="line"> ]</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">//index.js</span></div><div class="line"><span class="built_in">console</span>.log(SOMETHINE);</div></pre></td></tr></table></figure>
<p>编译完的结果如下:</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></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span>(<span class="params">module, exports, __webpack_require__</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log((This Is The Test Text.));</div><div class="line">}</div></pre></td></tr></table></figure>
<p>可以看到代码中 SOMETHINE 被直接替换为 This is something we needed. 但是我们的本意中 SOMETHINE 是一个字符串,而直接替换后却不是一个字符串。怎么办呢?</p>
<p>方法一:可以将 SOMETHINE 的值写成 </p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">SOMETHINE: <span class="string">'"This is something we needed."'</span></div></pre></td></tr></table></figure>
<p>方法二: 借助 JSON.tringify ,转为字符串</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">SOMETHINE: <span class="built_in">JSON</span>.stringify(<span class="string">'This is something we needed.'</span>)</div></pre></td></tr></table></figure>
<p>推荐使用方法二,它不仅可以处理字符串,还可以处理Object中的字符串和Array。如下:</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><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//webpack.config.js</span></div><div class="line"></div><div class="line"> plugins: [</div><div class="line"> <span class="keyword">new</span> webpack.DefinePlugin({</div><div class="line"> <span class="attr">OBJ</span>: <span class="built_in">JSON</span>.stringify({<span class="string">"key1"</span>: <span class="string">"this is value"</span>}),</div><div class="line"> <span class="attr">OBJ2</span>: {<span class="string">"key1"</span>: <span class="string">"this is value"</span>},</div><div class="line"> <span class="attr">OBJ3</span>: {<span class="string">"key1"</span>: <span class="string">"'this is value'"</span>},</div><div class="line"> <span class="attr">ARRAY</span>: <span class="built_in">JSON</span>.stringify([<span class="string">"value1"</span>, <span class="string">"value2"</span>]),</div><div class="line"> <span class="attr">ARRAY2</span>: [<span class="string">"value1"</span>, <span class="string">"value2"</span>],</div><div class="line"> <span class="attr">ARRAY3</span>: [<span class="string">"'value1'"</span>, <span class="string">"'value2'"</span>]</div><div class="line"> })</div><div class="line">]</div><div class="line"></div><div class="line"><span class="comment">//index.js</span></div><div class="line"><span class="built_in">console</span>.log(OBJ);</div><div class="line"><span class="built_in">console</span>.log(OBJ2);</div><div class="line"><span class="built_in">console</span>.log(OBJ3);</div><div class="line"><span class="built_in">console</span>.log(ARRAY);</div><div class="line"><span class="built_in">console</span>.log(ARRAY2);</div><div class="line"><span class="built_in">console</span>.log(ARRAY3);</div></pre></td></tr></table></figure>
<p>编译结果</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></pre></td><td class="code"><pre><div class="line"><span class="built_in">console</span>.log(({<span class="string">"key1"</span>:<span class="string">"this is value"</span>})); <span class="comment">// OBJ 正确</span></div><div class="line"><span class="built_in">console</span>.log(({<span class="string">"key1"</span>:<span class="keyword">this</span> is value})); <span class="comment">// OBJ2 this is value 被直接替换了,而非字符串</span></div><div class="line"><span class="built_in">console</span>.log(({<span class="string">"key1"</span>:<span class="string">'this is value'</span>})); <span class="comment">// OBJ3 正确</span></div><div class="line"><span class="built_in">console</span>.log(([<span class="string">"value1"</span>,<span class="string">"value2"</span>])); <span class="comment">// ARRAY 正确</span></div><div class="line"><span class="built_in">console</span>.log(({<span class="string">"0"</span>:value1,<span class="string">"1"</span>:value2})); <span class="comment">// ARRAY2 直接写[]的形式,会被替换为object的类型,value1 和 value2 不是字符串</span></div><div class="line"><span class="built_in">console</span>.log(({<span class="string">"0"</span>:<span class="string">'value1'</span>,<span class="string">"1"</span>:<span class="string">'value2'</span>})); <span class="comment">// ARRAY3 正确</span></div></pre></td></tr></table></figure>
<p>还剩下 Number 和 Boolean 两种变量类型,对于这两种类型,就不像上面介绍的这么麻烦了,直接写就行</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></pre></td><td class="code"><pre><div class="line"><span class="comment">//webpack.config.js</span></div><div class="line"></div><div class="line"> plugins: [</div><div class="line"> <span class="keyword">new</span> webpack.DefinePlugin({</div><div class="line"> <span class="attr">NUMBER</span>: <span class="number">12</span>,</div><div class="line"> <span class="attr">BOOL</span>: <span class="literal">true</span></div><div class="line"> })</div><div class="line">]</div><div class="line"></div><div class="line"><span class="comment">//index.js</span></div><div class="line"><span class="built_in">console</span>.log(NUMBER);</div><div class="line"><span class="built_in">console</span>.log(BOOL);</div></pre></td></tr></table></figure>
<p>编译结果</p>
<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="built_in">console</span>.log((<span class="number">12</span>));</div><div class="line"><span class="built_in">console</span>.log((<span class="literal">true</span>));</div></pre></td></tr></table></figure>
<h5 id="实际运用"><a href="#实际运用" class="headerlink" title="实际运用"></a>实际运用</h5><p>介绍了这么多,在实际使用中, DefinePlugin 最为常用的用途就是用来处理我们开发环境和生产环境的不同。比如一些 debug 的功能在生产环境中需要关闭、开发环境中和生产环境中 api 地址的不同。以 vue-cli 生成的打包文件为例子,来看看在实际中的使用。</p>
<p>vue-cli 生成的目录中编译、打包相关的有两个文件夹 build 和 config 。</p>
<p>build 文件夹中找到 wbepack.dev.conf.js 和 webpack.prod.conf.js ,这两个文件中都通过 DefinePlugin 插件定义了 process.env 这个变量</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="comment">// webpack.dev.conf.js</span></div><div class="line"><span class="keyword">var</span> config = <span class="built_in">require</span>(<span class="string">'../config'</span>)</div><div class="line">...</div><div class="line">new webpack.DefinePlugin({</div><div class="line"> <span class="string">'process.env'</span>: config.dev.env</div><div class="line">})</div><div class="line"></div><div class="line"><span class="comment">// webpack.prod.conf.js</span></div><div class="line"><span class="keyword">var</span> config = <span class="built_in">require</span>(<span class="string">'../config'</span>)</div><div class="line"><span class="keyword">var</span> env = config.build.env</div><div class="line">...</div><div class="line">new webpack.DefinePlugin({</div><div class="line"> <span class="string">'process.env'</span>: env</div><div class="line">})</div></pre></td></tr></table></figure>
<p>config 中对 env 的定义分别放在 config/dev.env.js 和 config/prod.env.js 中</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><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">//config/index.js</span></div><div class="line"><span class="built_in">module</span>.exports = {</div><div class="line"> <span class="attr">build</span>: {</div><div class="line"> <span class="attr">env</span>: <span class="built_in">require</span>(<span class="string">'./prod.env'</span>),</div><div class="line"> ...</div><div class="line"> },</div><div class="line"> <span class="attr">dev</span>: {</div><div class="line"> <span class="attr">env</span>: <span class="built_in">require</span>(<span class="string">'./dev.env'</span>),</div><div class="line"> ...</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//config/prod.env.js</span></div><div class="line"><span class="built_in">module</span>.exports = {</div><div class="line"> <span class="attr">NODE_ENV</span>: <span class="string">'"production"'</span></div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//config/dev.env.js</span></div><div class="line"><span class="keyword">var</span> merge = <span class="built_in">require</span>(<span class="string">'webpack-merge'</span>)</div><div class="line"><span class="keyword">var</span> prodEnv = <span class="built_in">require</span>(<span class="string">'./prod.env'</span>)</div><div class="line"></div><div class="line"><span class="built_in">module</span>.exports = merge(prodEnv, {</div><div class="line"> <span class="attr">NODE_ENV</span>: <span class="string">'"development"'</span></div><div class="line">})</div></pre></td></tr></table></figure>
<p>到此可以看到,在 wbepack.dev.conf.js 中最终为 </p>
<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="string">'process.env'</span>: {<span class="attr">NODE_ENV</span>: <span class="string">'"development"'</span>}</div></pre></td></tr></table></figure>
<p>在 webpack.prod.conf.js 中最终为 </p>
<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="string">'process.env'</span>: {<span class="attr">NODE_ENV</span>: <span class="string">'"production"'</span>}</div></pre></td></tr></table></figure>
<p>在我们的代码中,如果部分只是在开发环境下才执行的逻辑,那么可以通过下面的方式</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></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (<span class="string">'development'</span> === process.env.NODE_ENV) {</div><div class="line"> <span class="comment">// 开发环境下的逻辑</span></div><div class="line">} <span class="keyword">else</span> {</div><div class="line"> <span class="comment">// 生产环境下</span></div><div class="line">}</div></pre></td></tr></table></figure>
</div>
</div>
<a class="read-all-link" href="/2016/12/28/webpack-DefinePlugin介绍/">阅读全部</a>
</div>
<div class="post-list">
<div class="post-list-item article">
<h3 class="article-header">
<a href="/2016/12/18/flow的使用/" >
flow的使用
</a>
</h3>
<div class="article-info">
<a href="/2016/12/18/flow的使用/"><span class="article-date">
2016-12-18
</span>
</a>
<span class="article-category tagcloud">
<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/工程化/">工程化</a></li></ul>
</span>
<span class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/flow/">flow</a></li></ul>
</span>
</div>
<div class="article-entry">
<p>facebook 推出的 js 静态类型检查工具。</p>
<blockquote>
<p>flow可以在代码运行前对类型错误进行检查,包括:</p>
<ul>
<li>类型错误</li>
<li>对null的引用</li>
<li>以及可怕的 “undefined is not a function”<br>flow 允许我们给变量添加类型</li>
</ul>
</blockquote>
<h4 id="flow-的安装和使用"><a href="#flow-的安装和使用" class="headerlink" title="flow 的安装和使用"></a>flow 的安装和使用</h4><p>安装:<br>由于 flow 是用 OCaml 语言写的,npm 上只有对应的二进制包。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">npm install --save-dev flow-bin</div></pre></td></tr></table></figure>
<p>1.基本使用</p>
<p>安装完成后我们在要执行静态检查的文件跟目录下执行一下 <strong>flow init</strong> ,之后会发现多处一个<strong>.flowconfig</strong>文件,<strong>这个文件告诉 Flow 在这个目录下开始检测</strong>。此外 .flowconfig 文件可以进行一下更为高级的配置,比如仅包含一些目录、忽略一下目录等等(更深入的了解,<a href="https://flowtype.org/docs/advanced-configuration.html#_" target="_blank" rel="external">请戳官网</a>)。 </p>
<p>对于需要使用 flow 进行类型检查的 js 文件,在开头加入 @flow 的注释</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></pre></td><td class="code"><pre><div class="line"><span class="comment">/* @flow */</span> 只要带有这个注释,都会进行类型检测</div><div class="line"></div><div class="line">或者</div><div class="line"></div><div class="line"><span class="comment">/* @flow weak */</span> 只对有加类型注解的变量进行类型检测</div></pre></td></tr></table></figure>
<p>例如:</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></pre></td><td class="code"><pre><div class="line"><span class="comment">/* @flow */</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">multiple10</span> (<span class="params">num</span>) </span>{</div><div class="line"> <span class="keyword">return</span> num * <span class="number">10</span></div><div class="line">}</div><div class="line"></div><div class="line">multiple10(<span class="string">'20'</span>)</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">getLength</span> (<span class="params">str</span>) </span>{</div><div class="line"> <span class="keyword">return</span> str.length</div><div class="line">}</div><div class="line">getLength(<span class="string">'3'</span>)</div><div class="line">getLength([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>])</div></pre></td></tr></table></figure>
<p>接下来执行 flow check 看一下结果</p>
<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></pre></td><td class="code"><pre><div class="line">3: <span class="built_in">return</span> num * 10</div><div class="line"> ^^^ string. The operand of an arithmetic operation must be a number.</div><div class="line"></div><div class="line">Found 1 error</div></pre></td></tr></table></figure>
<p>multiple10 函数中的类型转换被 flow 标记出。</p>
<p>2.类型注解</p>
<p>注意上面例子中 flow 的报错,只有 multiple10 中静态类型错误被检测中。对于 getLength 函数中参数 str 的类型是什么呢? 从函数本身来分析,只要包含 length 属性就都是合法的。 对于这种情况则可以为其添加“<a href="https://zhenyong.github.io/flowtype/docs/type-annotations.html#_" target="_blank" rel="external">类型注解</a>”,来明确的告诉 flow 这个值的类型。</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></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">getLength</span> (<span class="params">str: string</span>) </span>{</div><div class="line"> <span class="keyword">return</span> str.length</div><div class="line">}</div><div class="line">getLength(<span class="string">'3'</span>)</div><div class="line">getLength([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>])</div></pre></td></tr></table></figure>
<p>再来运行一下 flow check , 这时结果会提示我们[1,2,3]这个参数类型不对。</p>
<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></pre></td><td class="code"><pre><div class="line">12: getLength([1,2,3])</div><div class="line"> ^^^^^^^ array literal. This type is incompatible with the expected param type of</div><div class="line"> 8: function getLength (str: string) {</div><div class="line"> ^^^^^^ string</div></pre></td></tr></table></figure>
<p>3.自定义类型</p>
<p>很多时候,除了 number 、 string 这些基础类型外,我们还会有一些自定义的类型,比如:</p>
<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></pre></td><td class="code"><pre><div class="line">var someData = {</div><div class="line"> id: 1,</div><div class="line"> text: '选项1'</div><div class="line">}</div></pre></td></tr></table></figure>
<p>这时候可以在一个单独的文件中将 someData 申明了一个自定义类型。方式如下:</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></pre></td><td class="code"><pre><div class="line"><span class="comment">/* /decls/data.js.flow */</span></div><div class="line">declare type SomeData = {</div><div class="line"> <span class="attr">id</span>: number;</div><div class="line"> text: strin;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>然后在 .flowconfig 文件中引入该申明文件</p>
<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">[libs]</div><div class="line">decls/</div></pre></td></tr></table></figure>
<h4 id="flow-server"><a href="#flow-server" class="headerlink" title="flow server"></a>flow server</h4><p>在大型项目中,如果每修改完代码,就执行以下 flow check ,然后等待看结果,显然会被逼疯的。flow 为我们提供了一个 flow server ,支持在后台运行,并且只监测有修改的文件。方法很简单,只有一个命令</p>
<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">$> flow <span class="comment"># 开启一个后台服务,输出首次检测结果</span></div><div class="line">$> flow <span class="comment"># 第二次使用flow,连接正在运行的后台服务,输出检测结果</span></div><div class="line">$> flow stop <span class="comment"># 关闭flow server</span></div></pre></td></tr></table></figure>
<h4 id="babel-flow"><a href="#babel-flow" class="headerlink" title="babel+flow"></a>babel+flow</h4><p>由于 flow 中类型注解的语法不属于 javascript 规范中的内容。所以在最终的代码中,我们需要移除flow的内容。flow 提供了 flow-remove-types 和 babel 插件两种方式,推荐使用 babel 插件来完成这项工作。</p>
<ul>
<li><p>flow-remove-types<br>这种方法比较简单粗暴: 安装 flow-remove-types,然后执行命令。</p>
<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">$> npm install -g flow-remove-types</div><div class="line">$> flow-remove-types src/ --out-dir build/</div></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>babel插件<br>安装 babel 插件</p>
<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 babel-plugin-transform-flow-strip-types</div></pre></td></tr></table></figure>
</li>
</ul>
<p> babel 的 plugin 中加入该插件</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></pre></td><td class="code"><pre><div class="line"> {</div><div class="line"> <span class="string">"presets"</span>: [<span class="string">"es2015"</span>, <span class="string">"stage-2"</span>],</div><div class="line"> <span class="string">"plugins"</span>: [<span class="string">"transform-runtime"</span>, <span class="string">"transform-flow-strip-types"</span>],</div><div class="line"> <span class="string">"comments"</span>: <span class="literal">false</span></div><div class="line">}</div></pre></td></tr></table></figure>
<blockquote>
<p>注意:在 babel6 的 babel-preset-react 的插件中已经内置了 transform-flow-strip-types(<a href="https://flowtype.org/docs/syntax.html" target="_blank" rel="external">https://flowtype.org/docs/syntax.html</a>),如果使用了 babel-preset-react 那么无需再引入transform-flow-strip-types</p>
</blockquote>
<h4 id="eslint"><a href="#eslint" class="headerlink" title="eslint"></a>eslint</h4><p>eslint-plugin-flowtype 插件,可以让我们在 eslint 代码检查中加入 flow 的书写规范化检查。使用方式也很简单:</p>
<ol>
<li><p>安装</p>
<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 eslint-plugin-flowtype</div></pre></td></tr></table></figure>
</li>
<li><p>在 .eslintrc.js 中设置 parser 为 <strong>babel-eslint</strong></p>
</li>
<li>plugin 中加入 <strong>flowtype</strong></li>
<li>eslint-plugin-flowtype 插件中默认提供了一份基于优秀实践总结出的 flow type 书写<a href="https://github.com/gajus/eslint-plugin-flowtype/blob/master/src/configs/recommended.json" target="_blank" rel="external">规范配置</a>,在 .eslintrc 文件的 extend 中加入 “plugin:flowtype/recommended” 即可直接使用。</li>
</ol>
<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">{</div><div class="line"> <span class="string">"extends"</span>: [</div><div class="line"> <span class="string">"standard"</span>,</div><div class="line"> <span class="string">"plugin:flowtype/recommended"</span></div><div class="line"> ],</div><div class="line"> <span class="string">"plugins"</span>: [</div><div class="line"> <span class="string">"flowtype"</span></div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure>
<p>完成后我们来看看效果。下面的代码</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></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">getLength</span> (<span class="params">str:string</span>) </span>{</div><div class="line"> <span class="keyword">return</span> str.length</div><div class="line">}</div><div class="line">getLength(<span class="string">'3'</span>)</div></pre></td></tr></table></figure>
<p>eslint 检查结果会抛出一个错误:类型注解的冒号后面丢失了空格。</p>
<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"></div><div class="line"> ✘ https://google.com/<span class="comment">#q=flowtype%2Fspace-after-type-colon There must be a space after "str" parameter type annotation colon</span></div><div class="line"> /Users/didi/xiaoju/src/static-h5-src/750/driver/feedback/src/main.js:2:21</div><div class="line"> <span class="keyword">function</span> getLength (str:string) {</div><div class="line"> ^</div><div class="line">✘ 1 problem (1 error, 0 warnings)</div></pre></td></tr></table></figure>
<p>因为推荐的规范中:类型注解冒号后需要一个空格</p>
<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">"rules": {</div><div class="line"> ...</div><div class="line">"flowtype/space-after-type-colon": [</div><div class="line"> 2,</div><div class="line"> "always"</div><div class="line">],</div><div class="line">...</div><div class="line">}</div></pre></td></tr></table></figure>
<p>flow type 规范配置如:函数返回类型是否必须、类型注解冒号前后的空格、自定义的type 的名称的命名方式等等,官方给出了很详细<a href="https://github.com/gajus/eslint-plugin-flowtype" target="_blank" rel="external">说明和例子</a>。注:针对flow的的规范规则配置前添加“flowtype/”</p>
<table>
<thead>
<tr>
<th style="text-align:left">配置名称</th>
<th style="text-align:left">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">boolean-style</td>
<td style="text-align:left">类型注解中布尔值使用boolean还是bool</td>
</tr>
<tr>
<td style="text-align:left">define-flow-type</td>
<td style="text-align:left">将类型注解标记为已定义,no-undef的检查中不会出现报错</td>
</tr>
<tr>
<td style="text-align:left">delimiter-dangle</td>
<td style="text-align:left">Object和Tuple类型定义中分隔符使用规范</td>
</tr>
<tr>
<td style="text-align:left">generic-spacing</td>
<td style="text-align:left">泛型对象的尖括号中类型前后的空格规范</td>
</tr>
<tr>
<td style="text-align:left">space-before-generic-bracket</td>
<td style="text-align:left">泛型对象的尖括号前的空格规范</td>
</tr>
<tr>
<td style="text-align:left">no-dupe-keys</td>
<td style="text-align:left">object类型的定义中是否有重复的属性值</td>
</tr>
<tr>
<td style="text-align:left">no-primitive-constructor-types</td>
<td style="text-align:left">禁止使用原生的类型</td>
</tr>
<tr>
<td style="text-align:left">no-weak-types</td>
<td style="text-align:left">是否可以使用弱类型any、Object、Function</td>
</tr>
<tr>
<td style="text-align:left">object-type-delimiter</td>
<td style="text-align:left">Object类型定义中,属性之前分割符为分号/逗号(注:该属性已被废弃,需要使用分号来分割)</td>
</tr>
<tr>
<td style="text-align:left">require-parameter-type</td>
<td style="text-align:left">函数的参数是否需要类型注解</td>
</tr>
<tr>
<td style="text-align:left">require-return-type</td>
<td style="text-align:left">函数返回值是否需要类型注解</td>
</tr>
<tr>
<td style="text-align:left">require-valid-file-annotation</td>
<td style="text-align:left">文件开头@flow的写法</td>
</tr>
<tr>
<td style="text-align:left">require-variable-type</td>
<td style="text-align:left">什么样的变量是需要类型注解</td>
</tr>
<tr>
<td style="text-align:left">semi</td>
<td style="text-align:left">使用type自定义类型语句结尾是否需要分号结尾</td>
</tr>
<tr>
<td style="text-align:left">sort-keys</td>
<td style="text-align:left">Object类型定义中属性排列顺序</td>
</tr>
<tr>
<td style="text-align:left">space-after-type-colon</td>
<td style="text-align:left">类型注解分号后的空格规范</td>
</tr>
<tr>
<td style="text-align:left">space-before-type-colon</td>
<td style="text-align:left">类型注解分号前的空格规范</td>
</tr>
<tr>
<td style="text-align:left">type-id-match</td>
<td style="text-align:left">使用type自定义类型的名称规范</td>
</tr>
<tr>
<td style="text-align:left">union-intersection-spacing</td>
<td style="text-align:left">union类型、intersection类型连接符号\</td>
<td>、&之间的空格规范</td>
</tr>
<tr>
<td style="text-align:left">use-flow-type</td>
<td style="text-align:left">将通过declare定义的自定义类型标记为已经被使用过,no-unused-vars的检查中不会出现报错</td>
</tr>
</tbody>
</table>
<p>#####名词说明</p>
<p>文中一些中文词直接从英文文档中翻译过来,可能有不准确的地方,这里给出原文,避免歧义。</p>
<ul>
<li>类型注解:原文为 type annotations ,标记变量的类型</li>
<li><p>自定义类型:原文为 type aliases, 类似C语言中的typedef,可以为已有类型定义一个新的名称,或将一个复杂类型进行封装,如</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></pre></td><td class="code"><pre><div class="line"> type a = <span class="built_in">Array</span><<span class="built_in">String</span>></div><div class="line"> type Person = {</div><div class="line"> <span class="attr">name</span>: string,</div><div class="line"> <span class="attr">age</span>: number</div><div class="line">};</div></pre></td></tr></table></figure>
</li>
</ul>
<p>#####相关链接<br> flow 官网(关于 flow 的各种用法官网给出了详细的例子):<a href="https://flowtype.org/" target="_blank" rel="external">https://flowtype.org/</a> </p>
<p> flow 简短教程:<a href="https://www.youtube.com/watch?v=xWMuAUbXcdQ" target="_blank" rel="external">https://www.youtube.com/watch?v=xWMuAUbXcdQ</a> </p>
</div>
</div>
<a class="read-all-link" href="/2016/12/18/flow的使用/">阅读全部</a>
</div>
<div class="post-list">
<div class="post-list-item article">
<h3 class="article-header">
<a href="/2016/11/27/cookie从哪来到哪去/" >
cookie从哪来到哪去
</a>
</h3>
<div class="article-info">
<a href="/2016/11/27/cookie从哪来到哪去/"><span class="article-date">
2016-11-27
</span>
</a>
<span class="article-category tagcloud">
<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/web/">web</a></li></ul>
</span>
<span class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/基础知识/">基础知识</a></li></ul>
</span>
</div>
<div class="article-entry">
<h4 id="从哪来"><a href="#从哪来" class="headerlink" title="从哪来"></a>从哪来</h4><p>浏览器添加cookie的时机:</p>
<ul>
<li><p>有客户端来设置:通过javascript的api——document.cookie来操作</p>
<h5 id="设置"><a href="#设置" class="headerlink" title="设置"></a>设置</h5> <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="built_in">document</span>.cookie = <span class="string">'name=value; maxAge=3000; path=/; domain=xx.com; secure'</span></div></pre></td></tr></table></figure>
<p> cookie的名和值中不能出现分号、逗号、等号和空格,每一个key之间通过分号和空格来分割。</p>
<h5 id="设置多个cookie"><a href="#设置多个cookie" class="headerlink" title="设置多个cookie"></a>设置多个cookie</h5><p> 通过document.cookie的方式来设置cookie每次只能设置一个cookie。如果我们写多个会有什么效果呢?</p>
<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="built_in">document</span>.cookie = <span class="string">'cookie1=value1; cookie2=value2'</span></div></pre></td></tr></table></figure>
</li>
</ul>
<pre><code>放在console中运行一下,会发现,只有第一个cookie1设置成功,而cookie2被无视了。所以要设置多个cookie,最简单的方式就是多次调用document.cookie。
</code></pre><ul>
<li><p>由服务端来设置:http的响应头中。</p>
<p>打开浏览器的控制台,在network下我们可以看到浏览器发出的所有请求。这些请求的返回头中,有些会发现一个Set-Cookie的字段。<br><img src="/images/Set-Cookie.png" style="width:400px;margin:0 auto;display:block;" alt="set-cookie"><br>服务器通过这个字段来告诉浏览器,它需要设置一个cookie,然后浏览器检查一下要设置的内容是否满足浏览器定下的cookie的“条条框框”,如果满足那么一个cookie就诞生了。这里提到了“条条框框”我们稍后做解答。</p>
<p>在上图中,响应头里set-cookie字段可以有多个,每一个对应一个要设置的cookie,且只能对应一个。</p>
</li>
</ul>
<h4 id="到哪去"><a href="#到哪去" class="headerlink" title="到哪去"></a>到哪去</h4><ul>
<li><p>客户端主动获取</p>
<p>和客户端设置相同,获取的时候也是通过document.cookie来读取:</p>
<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> cookies = <span class="built_in">document</span>.cookie</div></pre></td></tr></table></figure>
<p> 读取到的cookie为一串字符串,每个cookie之间通过分号来分割。</p>
</li>
<li><p>随着请求发送</p>
<p>浏览器发送请求时,在请求的头中会自动将“符合条件”的cookie带上。<br>既然是请求头中携带的,那么我们通过ajax发送请求的时候,能否顺便设置一下cookie呢?简单的实验一下即可知晓:</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></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>, url, <span class="literal">true</span>);</div><div class="line">xhr.withCredentials = <span class="literal">true</span>;</div><div class="line">xhr.setRequestHeader(<span class="string">'Cookie'</span>, <span class="string">"key=value"</span>);</div><div class="line">xhr.send(<span class="literal">null</span>);</div></pre></td></tr></table></figure>
<p>然后我们看看实际上浏览器发送出去的请求:<br><img src="/images/ajax-setcookie.jpeg" style="width:400px;margin:0 auto;display:block;" alt=""><br>我们设置的cookie并没有生效,并且chrome浏览器下我们会看到一行报错</p>
<blockquote>
<p>Refused to set unsafe header “Cookie”</p>
</blockquote>
<p>所以说,因为浏览器的安全限制,我们不能自己随便设置请求头中的cookie。</p>
</li>
</ul>
<h4 id="cookies条条框框"><a href="#cookies条条框框" class="headerlink" title="cookies条条框框"></a>cookies条条框框</h4><p> 一个cookie除了value外,还有domain、path、expires/max-age、httpOnly、secure、sameSite这些属性。设置cookie的时候,可以对这些相关属性进行设置,当然也可以不进行设置,这时浏览器会自动给这些属性一个默认值。cookie的条条框框就和这些属性脱不了干系。</p>
<ul>
<li><p>domain</p>
<p>domain限制了cookie的使用范围:只能在domain值的范围中才能访问到该cookie.</p>
<p>同时domain值的设置也有严格的要求。</p>
<ul>
<li><p>自身</p>
<p> 毫无疑问domain的值可以设置为本身。</p>
</li>
<li><p>向下:所有子域名</p>
<p>如果我们当前页面的域名是 sub.test.com, 那么 domain 可以设置为.sub.test.com。允许所有sub.test.com的子域名访问,如xx.sub.test.com、xx.xx.sub.test.com。</p>
</li>
<li><p>向上:父级域名,直到Top-Level的下一级</p>
<p>如果我们当前页面的域名是sub.test.com, 那么domain可以设置为test.com。但是不能设置为.com。因为.com属于<a href="https://en.wikipedia.org/wiki/Top-level_domain" target="_blank" rel="external">Top-Level Domain</a>。</p>
</li>
</ul>
</li>
<li><p>path</p>
<p>domain+path 共同限制了可访问该cookie的URL。如果某个cookie的path=’/home’,那么只有“domain/home”下的所有url可以访问该cookie。</p>
</li>
<li><p>expires/max-age</p>
<p>这两个值决定了cookie能活多久。如果不进行设置,那么浏览器会默认将cookie的有效期设置为 session,当页面关闭后cookie便随之被清理了。如果希望cookie在页面关闭后,仍然能保存一段时间,那么就需要为cookie设置一个过期时间,在过期时间内浏览器都会为我们保留该cookie.</p>
<blockquote>
<p>expires 是 http/1.0协议中的选项,在新的http/1.1协议中expires已经由 max-age 选项代替。expires必须是 GMT 格式的时间。</p>
</blockquote>
<p>max-age的单位为秒,cookie失效时刻 = 创建时刻 + max-age</p>
</li>
<li><p>httpOnly</p>
<p>如果一个cookie被标记为httpOnly, 那么前文所提到的通过document.cookie的方式就无法获取到该cookie。同样的,我们通过js来设置cookie的,也无法被标记为httpOnly。也就说以下写法是不会生效的:</p>
<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="built_in">document</span>.cookie=<span class="string">"cookie1=value1; HttpOnly"</span></div></pre></td></tr></table></figure>
<p>这个值只能通过请求的响应头来设置。默认情况下,cookie不会带httpOnly选项。</p>
</li>
<li><p>Secure</p>
<p>对于被标记为Secure的cookie,只有当请求是HTTPS或者其他安全协议时,该cookie 才能被访问到。同样的,也只有在HTTPS或者其他安全协议时,我们也才能通过js设置secure的cookie。</p>
</li>
<li><p>sameSite</p>
<p>这个值这是谷歌开发的一种安全机制,用来定义cookie如何跨域发送,其目的是尝试阻止CSRF。chrome51版本已经支持。关于各大浏览器的支持情况,参考<a href="https://www.chromestatus.com/feature/4672634709082112" target="_blank" rel="external">chrome官网</a>。关于这个特性,这里不多做介绍了,感兴趣的可参看<a href="https://www.sjoerdlangkemper.nl/2016/04/14/preventing-csrf-with-samesite-cookie-attribute/" target="_blank" rel="external">preventing-csrf-with-samesite-cookie-attribute</a>和<a href="https://chloe.re/2016/04/13/goodbye-csrf-samesite-to-the-rescue/" target="_blank" rel="external">goodbye-csrf-samesite-to-the-rescue</a></p>
<p>最后,这些所有的属性值,一起决定了一件事——这个cookie那个URL可以能用。</p>
</li>
</ul>
<p>参考文献:<br><a href="https://developers.livechatinc.com/blog/setting-cookies-to-subdomains-in-javascript/" target="_blank" rel="external">https://developers.livechatinc.com/blog/setting-cookies-to-subdomains-in-javascript/</a><br><a href="https://www.sjoerdlangkemper.nl/2016/04/14/preventing-csrf-with-samesite-cookie-attribute/" target="_blank" rel="external">https://www.sjoerdlangkemper.nl/2016/04/14/preventing-csrf-with-samesite-cookie-attribute/</a></p>
</div>
</div>
<a class="read-all-link" href="/2016/11/27/cookie从哪来到哪去/">阅读全部</a>
</div>
<div class="post-list">
<div class="post-list-item article">
<h3 class="article-header">
<a href="/2016/11/19/javascript中bind知多少/" >
javascript中bind知多少
</a>
</h3>
<div class="article-info">
<a href="/2016/11/19/javascript中bind知多少/"><span class="article-date">
2016-11-19
</span>
</a>
<span class="article-category tagcloud">
<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/语言/">语言</a></li></ul>
</span>
<span class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/javascript/">javascript</a></li></ul>
</span>
</div>
<div class="article-entry">
<p> 我们经常将apply, call和bind放在一起来对比他们的区别和用法。提到这三个,很容易想到他们可以改变函数中this的指向。对于bind方法,我们最常见的使用方式如下:</p>
<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> otherFn = fn.bind(<span class="keyword">this</span>);</div></pre></td></tr></table></figure>
<p> 其实,bind还有一个被我们忽略了的非常好用的特性——<em style="color: red; font-weight: bold">传参</em></p>
<h4 id="bind参数"><a href="#bind参数" class="headerlink" title="bind参数"></a>bind参数</h4><blockquote>
<p>当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数。</p>
</blockquote>
<p> 来个栗子:</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></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> fn1 = <span class="function"><span class="keyword">function</span> (<span class="params">arg1, arg2, arg3</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(arg1);</div><div class="line"> <span class="built_in">console</span>.log(arg2);</div><div class="line"> <span class="built_in">console</span>.log(arg3);</div><div class="line">}</div><div class="line"><span class="keyword">var</span> fn2 = fn1.bind(<span class="literal">null</span>, <span class="string">'first'</span>);</div><div class="line">fn2(<span class="string">'second'</span>, <span class="string">'third'</span>); <span class="comment">// 输出为: first second third</span></div></pre></td></tr></table></figure>
<h4 id="为什么说好用"><a href="#为什么说好用" class="headerlink" title="为什么说好用"></a>为什么说好用</h4><p> bind的参数可以和绑定函数本身的参数进行拼接,利用这一特性可以实现一些自定义的包装。看下面的使用:</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="comment">// 原始函数</span></div><div class="line"><span class="keyword">var</span> fn = <span class="function"><span class="keyword">function</span>(<span class="params">customizer, a, b</span>) </span>{</div><div class="line"> <span class="keyword">var</span> customResult = customizer(a, b); <span class="comment">// 使用自定义方式对a,b,key进行处理</span></div><div class="line"> <span class="keyword">if</span> (!customResult) {</div><div class="line"> <span class="comment">// 默认的处理</span></div><div class="line"> customResult = a + b</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> customResult;</div><div class="line">}</div><div class="line"><span class="keyword">var</span> decoratoredFn = fn.bind(<span class="literal">null</span>, <span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>) </span>{</div><div class="line"> <span class="comment">// 自定义的处理方法</span></div><div class="line"> <span class="keyword">return</span> a*<span class="number">2</span> + b;</div><div class="line">});</div><div class="line">decoratoredFn(<span class="number">1</span>, <span class="number">2</span>); <span class="comment">// 结果为 4;</span></div></pre></td></tr></table></figure>
<p>在原始的函数中,自定义的函数仅仅是一个参数,而具体的实现是在bind的时候确定的。这样,fn可以认为是一个<em style="color:red; font-weight:bold">通用的抽象的模板</em>。额,有点拗口,让我们想象一下map方法:</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></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> numbers = [<span class="number">1</span>, <span class="number">4</span>, <span class="number">9</span>];</div><div class="line"><span class="keyword">var</span> roots = numbers.map(<span class="built_in">Math</span>.sqrt);</div><div class="line"><span class="comment">// roots is now [1, 2, 3]</span></div><div class="line"><span class="comment">// numbers is still [1, 4, 9]</span></div></pre></td></tr></table></figure>
<p>map方式实现了一个抽象的模板,将一个array转化为另一个array,然后输出。中间具体转化成什么map是不关心的,留给我们来自定义。用bind来搞一搞array的map呢?通用的逻辑:挨个对array中的每一个进行处理得到一个值,这些值组成一个新的array,然后最终输出。具体每一个怎么处理,留给bind了。</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></pre></td><td class="code"><pre><div class="line"><span class="comment">// 原始函数</span></div><div class="line"><span class="keyword">var</span> fn = <span class="function"><span class="keyword">function</span>(<span class="params">customizer, a</span>) </span>{</div><div class="line"> <span class="keyword">var</span> resultArray = [];</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>, len=a.length; i < len; i++) {</div><div class="line"> resultArray.push(customizer(a[i]));</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> resultArray;</div><div class="line">}</div><div class="line"><span class="keyword">var</span> customizerFn = fn.bind(<span class="literal">null</span>, <span class="function"><span class="keyword">function</span>(<span class="params">item</span>) </span>{</div><div class="line"> <span class="comment">// 自定义的处理方法</span></div><div class="line"> <span class="keyword">return</span> item*<span class="number">2</span>;</div><div class="line">});</div><div class="line">decoratoredFn([<span class="number">1</span>, <span class="number">2</span>]); <span class="comment">// 结果为 [2, 4];</span></div></pre></td></tr></table></figure>
<h4 id="贴合点实际的栗子——单位转换"><a href="#贴合点实际的栗子——单位转换" class="headerlink" title="贴合点实际的栗子——单位转换"></a>贴合点实际的栗子——单位转换</h4><p>对于一维的单位转化,我们可以容易的得出一个通用的公式: 原单位*比例 + 起始偏差值 用代码描述一下:</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></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">converter</span>(<span class="params">toUnit, factor, offset, input</span>) </span>{</div><div class="line"> offset = offset || <span class="number">0</span>;</div><div class="line"> <span class="keyword">return</span> [((offset+input)*factor).toFixed(<span class="number">2</span>), toUnit].join(<span class="string">" "</span>);</div><div class="line">}</div></pre></td></tr></table></figure>
<p>基于converter函数,借用bind的可以包装出各种单位转化的方法:</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></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> milesToKm = converter.bind(<span class="literal">undefined</span>, <span class="string">'km'</span>, <span class="number">1.60936</span>, <span class="number">0</span>);</div><div class="line"><span class="keyword">var</span> poundsToKg = converter.bind(<span class="literal">undefined</span>, <span class="string">'kg'</span>, <span class="number">0.45460</span>, <span class="number">0</span>);</div><div class="line"><span class="keyword">var</span> farenheitToCelsius = converter.bind(<span class="literal">undefined</span>, <span class="string">'degrees C'</span>,<span class="number">0.5556</span>, <span class="number">-32</span>);</div><div class="line">milesToKm(<span class="number">10</span>); <span class="comment">// returns "16.09 km"</span></div><div class="line">poundsToKg(<span class="number">2.5</span>); <span class="comment">// returns "1.14 kg"</span></div><div class="line">farenheitToCelsius(<span class="number">98</span>); <span class="comment">// returns "36.67 degrees C"</span></div></pre></td></tr></table></figure>
<p><a href="http://kishorelive.com/2012/02/06/currying-in-javascript-using-bind/" target="_blank" rel="external">该栗子来源戳这里</a></p>
</div>
</div>
<a class="read-all-link" href="/2016/11/19/javascript中bind知多少/">阅读全部</a>
</div>
<div class="post-list">
<div class="post-list-item article">
<h3 class="article-header">
<a href="/2016/11/19/配合event-pointer实现1px边框/" >
配合pointer-events实现1px边框
</a>
</h3>
<div class="article-info">
<a href="/2016/11/19/配合event-pointer实现1px边框/"><span class="article-date">
2016-11-19
</span>
</a>
<span class="article-category tagcloud">
<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/CSS/">CSS</a></li></ul>
</span>
<span class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/CSS/">CSS</a></li></ul>
</span>
</div>
<div class="article-entry">
<p> 从乔帮主发布Retina设备开始兴起后,移动端的h5就多了一个烦人的1px。然后设计师们对1px格外青睐,设计稿(750尺寸)中各种1px分割线,1px边框。</p>
<p> 对于下图中一系列的的1px边框通常的实现方式</p>
<p> <img src="/images/1px边框.png" alt="1px系列边框" style="width: 300px; display:block;margin:auto"></p>
<ol>
<li><p>在最外层A进行transform:scale(0.5)</p>
</li>
<li><p>给每一个B元素加上transform:scale(0.5)</p>
</li>
</ol>
<p>以上两种方式由于transform:scale(0.5)的影响,在写内部元素的大小时,都需要放大两倍,虽然只是*2,但是算起来还是略烦的。</p>
<p>下面介绍另外一种,pointer-events配合transform:scale(0.5)来实现1px边框的方式:</p>
<p>html:</p>
<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">div</span> <span class="attr">class</span>=<span class="string">"b-div"</span>></span></div></pre></td></tr></table></figure>
<p>css:</p>
<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><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="selector-class">.b-div</span> {</div><div class="line"> <span class="attribute">position</span>: relative</div><div class="line"> <span class="comment">/*</span></div><div class="line"> 按照正常的布局计算方式来写</div><div class="line"> */</div><div class="line"> }</div><div class="line"> <span class="comment">/*单独的边框*/</span></div><div class="line"> <span class="selector-class">.b-div</span><span class="selector-pseudo">::before</span> {</div><div class="line"> <span class="attribute">content</span>: <span class="string">''</span>;</div><div class="line"> <span class="attribute">position</span>: absolute;</div><div class="line"> <span class="attribute">display</span>: block;</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">z-index</span>: <span class="number">10</span>;</div><div class="line"> <span class="attribute">pointer-events</span>: none;</div><div class="line"> <span class="attribute">box-sizing</span>: border-box;</div><div class="line"> <span class="attribute">height</span>: <span class="number">200%</span>;</div><div class="line"> <span class="attribute">width</span>: <span class="number">200%</span>;</div><div class="line"> <span class="attribute">overflow</span>: hidden;</div><div class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#fc9153</span>;</div><div class="line"> <span class="attribute">transform</span>: <span class="built_in">scale</span>(0.5);</div><div class="line"> <span class="attribute">transform-origin</span>: left top</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 上面通过伪类before来绘制1px边框。 在before上,将<strong>pointer-events的属性设置为none</strong>,边框元素虽然在b-div上层,但是不会有事件的响应,所有的事件会透到b-div上。如此一来,before伪类就仅仅是能”看到“而已</p>
<p> 配合stylus的话,可以将1px边框的实现抽离出来,写成一个单独的mixin</p>
<figure class="highlight stylus"><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"><span class="function"><span class="title">border-1px</span><span class="params">(<span class="variable">$bordercolor</span>, <span class="variable">$bordertopleftradius</span> = <span class="number">0px</span>, <span class="variable">$bordertoprightradius</span> = <span class="number">0px</span>, <span class="variable">$borderbottomleftradius</span> = <span class="number">0px</span>, <span class="variable">$borderbottomrightradius</span> = <span class="number">0px</span>)</span></span></div><div class="line"> &::before</div><div class="line"> <span class="attribute">content</span>: <span class="string">" "</span></div><div class="line"> <span class="attribute">position</span>: absolute</div><div class="line"> <span class="attribute">display</span>: block</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">z-index</span>: <span class="number">10</span></div><div class="line"> <span class="attribute">pointer-events</span>: none</div><div class="line"> <span class="attribute">box-sizing</span>: border-box</div><div class="line"> <span class="attribute">height</span>: <span class="number">200%</span></div><div class="line"> <span class="attribute">width</span>: <span class="number">200%</span></div><div class="line"> <span class="attribute">overflow</span>: hidden</div><div class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#fc9153</span></div><div class="line"> <span class="attribute">border-top-left-radius</span>: <span class="variable">$bordertopleftradius</span></div><div class="line"> <span class="attribute">border-top-right-radius</span>: <span class="variable">$bordertoprightradius</span></div><div class="line"> <span class="attribute">border-bottom-left-radius</span>: <span class="variable">$borderbottomleftradius</span></div><div class="line"> <span class="attribute">border-bottom-right-radius</span>: <span class="variable">$borderbottomrightradius</span></div><div class="line"> <span class="attribute">transform</span>: scale(<span class="number">0.5</span>);</div><div class="line"> <span class="attribute">transform-origin</span>: left top</div></pre></td></tr></table></figure>
<p> 剩下的就是在有1px边框的元素上,设置position,然后css中加入border-1px(),内部元素计算大小时不需要在*2了。</p>
<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></pre></td><td class="code"><pre><div class="line">.b-div</div><div class="line"> position: relative</div><div class="line"> border-1px(#fc9153)</div></pre></td></tr></table></figure>
<h5 id="兼容性"><a href="#兼容性" class="headerlink" title="兼容性"></a>兼容性</h5><p>pointer-event的兼容性还是比较好的, 具体参看<a href="http://caniuse.com/#feat=pointer-events" target="_blank" rel="external">caniuse</a></p>
<h5 id="该方法的弊端"><a href="#该方法的弊端" class="headerlink" title="该方法的弊端"></a>该方法的弊端</h5><ul>
<li><p>采用rem布局时,计算出的div(下面称为b-div)和边框的div(下面称为1px-div)会出现小数,如果b-div设置了overflow:hidden,则在部分安卓机器下会出现右边或者下边边框线消失的问题。</p>
<p>目前找到的解决方法是b-div不要设置overflow:hidden。</p>
</li>
<li><p>由于1px-div和b-div是两个独立的div,所以如果元素带圆角的话,需要同时设置1px-div和b-div的圆角,并且要一致。</p>
</li>
</ul>
</div>
</div>
<a class="read-all-link" href="/2016/11/19/配合event-pointer实现1px边框/">阅读全部</a>
</div>
<div class="post-list">
<div class="post-list-item article">
<h3 class="article-header">
<a href="/2016/11/19/Webpack-merge插件/" >
Webpack.merge插件
</a>
</h3>
<div class="article-info">
<a href="/2016/11/19/Webpack-merge插件/"><span class="article-date">
2016-11-19
</span>
</a>
<span class="article-category tagcloud">
<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/工程化/">工程化</a></li></ul>
</span>
<span class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/webpack/">webpack</a></li></ul>
</span>
</div>
<div class="article-entry">
<p> webpack-merge插件可以用来merge两个webpack的配置。它的底层引用了lodash中的merge,但针对webpack的特点,专门对loaders,preLoaders,postLoaders专门做了处理。</p>
<p> 一般情况下,对于以下两个module</p>
<figure class="highlight js"><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> <span class="built_in">module</span>: {</div><div class="line"> <span class="attr">loaders</span>: [</div><div class="line"> {</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.css$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'style'</span>, <span class="string">'css'</span>],</div><div class="line"> },</div><div class="line"> ]</div><div class="line"> }</div><div class="line"><span class="keyword">var</span> moduleExtend = {</div><div class="line"> <span class="attr">loaders</span>: [</div><div class="line"> {</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.jsx?$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel?stage=1'</span>,</div><div class="line"> <span class="attr">include</span>: path.join(ROOT_PATH, <span class="string">'app'</span>),</div><div class="line"> },</div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure>
<p>进行merge(module, moduleExtend)后会得到如下结果:</p>
<figure class="highlight js"><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">moduleMerged = {</div><div class="line"> <span class="attr">loaders</span>: [</div><div class="line"> {</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.jsx?$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel?stage=1'</span>,</div><div class="line"> <span class="attr">include</span>: path.join(ROOT_PATH, <span class="string">'app'</span>),</div><div class="line"> },</div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure>
<p>因为loaders是数组,所以结果中的css的loader信息丢失了。所以为了保证merge之后,loaders,preLoaders,postLoaders中的内容不会丢失,webpack-merge中对于loaders,preLoaders,postLoaders进行了特殊处理,采用<strong>concat对数组内容进行合并</strong></p>
<figure class="highlight js"><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="keyword">if</span> (isLoader(key)) {</div><div class="line"> <span class="keyword">return</span> b.concat(a);</div><div class="line">}</div><div class="line"><span class="keyword">return</span> a.concat(b);</div></pre></td></tr></table></figure>
<p>如此,merge的结果为</p>
<figure class="highlight js"><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">loaders: [</div><div class="line"> {</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.css$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'style'</span>, <span class="string">'css'</span>],</div><div class="line"> },</div><div class="line"> {</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.jsx?$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel?stage=1'</span>,</div><div class="line"> <span class="attr">include</span>: path.join(ROOT_PATH, <span class="string">'app'</span>),</div><div class="line"> }</div><div class="line">]</div></pre></td></tr></table></figure>
<p> 但是如果遇到两个test值相同的loader时,仅仅用concat的话,会产生两条结果</p>
<figure class="highlight js"><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></pre></td><td class="code"><pre><div class="line">merge({</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel'</span></div><div class="line"> }]</div><div class="line"> }, {</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'coffee'</span></div><div class="line"> }]</div><div class="line"> });</div><div class="line"><span class="comment">// 结果为</span></div><div class="line">{</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'coffee'</span></div><div class="line"> },</div><div class="line"> {</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel'</span></div><div class="line"> }]</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 这时对于js文件会先用babel-loader处理,然后再用coffee-loader处理。但是更多的,我们希望merge的结果是,后一个可以覆盖掉前一个。此外,在loaders中,除了可以写loader:’coffee’,还会有loaders:[‘xx’]的形式,如果一律采用concat的形式,显然过于粗暴了。所以,webpack-merge提供了更为聪明的的merge.smart函数,可以<strong>将test值相同的loader(preLoaders,postLoaders)进行合并</strong>。</p>
<ul>
<li>对于loader,后面的会覆盖前面的属性</li>
</ul>
<figure class="highlight js"><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">merge.smart({</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel'</span></div><div class="line"> }]</div><div class="line">}, {</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'coffee'</span></div><div class="line"> }]</div><div class="line">});</div><div class="line"><span class="comment">// 结果为</span></div><div class="line">{</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'coffee'</span></div><div class="line"> }]</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>loaders将会合并为一个去重后的数组</li>
</ul>
<figure class="highlight js"><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">merge.smart({</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'babel'</span>]</div><div class="line"> }]</div><div class="line">}, {</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'coffee'</span>]</div><div class="line"> }]</div><div class="line">});</div><div class="line"><span class="comment">// 结果为</span></div><div class="line">{</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="comment">// 由于webpack处理loadersz中的值是按照从右往左的顺序,所以'coffee'放在'babel'的前面</span></div><div class="line"> <span class="comment">// 这种从右往左的方式,让我们可以构造loaders处理链</span></div><div class="line"> loaders: [<span class="string">'coffee'</span>, <span class="string">'babel'</span>]</div><div class="line"> }]</div><div class="line">}</div></pre></td></tr></table></figure>
<p>注意:对于loaders中带参数的形式,如babel?plugins[]=object-assign,在smart merge时会认为和babel、babel?…为同一类,后一个会对前一个产生覆盖</p>
<figure class="highlight js"><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">merge.smart({</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'babel?plugins[]=object-assign'</span>]</div><div class="line"> }]</div><div class="line">}, {</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'babel'</span>, <span class="string">'coffee'</span>]</div><div class="line"> }]</div><div class="line">});</div><div class="line"><span class="comment">// 结果为</span></div><div class="line">{</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'babel'</span>, <span class="string">'coffee'</span>]</div><div class="line"> }]</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>如果后一个loaders,前一个为loader,则merge时会将loader转化为loaders,然后进行merge</li>
</ul>
<figure class="highlight js"><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></pre></td><td class="code"><pre><div class="line">merge.smart({</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel'</span></div><div class="line"> }]</div><div class="line">}, {</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'coffee'</span>]</div><div class="line"> }]</div><div class="line">});</div><div class="line"><span class="comment">// will become</span></div><div class="line">{</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="comment">// 由于webpack处理loadersz中的值是按照从右往左的顺序,所以'coffee'放在'babel'的前面</span></div><div class="line"> loaders: [<span class="string">'coffee'</span>, <span class="string">'babel'</span>]</div><div class="line"> }]</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>如果后一个为loader,前一个为loaders,则merge的结果为loader</li>
</ul>
<figure class="highlight js"><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">merge.smart({</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loaders</span>: [<span class="string">'babel'</span>]</div><div class="line"> }]</div><div class="line">}, {</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'coffee'</span></div><div class="line"> }]</div><div class="line">});</div><div class="line"><span class="comment">// will become</span></div><div class="line">{</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'coffee'</span></div><div class="line"> }]</div><div class="line">}</div></pre></td></tr></table></figure>
<p>注意:include和exclude的配置同时也会影响loader是否会被合并。如果两个loaders有不同的include或者exclude值(后一个loaders不包含include或exclude除外),那么loaders最终不会进行合并,而是像merge中进行了concat。</p>
<figure class="highlight js"><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></pre></td><td class="code"><pre><div class="line">merge.smart({</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">include</span>: <span class="string">'/dir1'</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel'</span></div><div class="line"> }]</div><div class="line">}, {</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">include</span>: <span class="string">'/dir2'</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'coffee'</span></div><div class="line"> }]</div><div class="line">});</div><div class="line"><span class="comment">//merge结果为</span></div><div class="line">{</div><div class="line"> <span class="attr">loaders</span>: [{</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">include</span>: <span class="string">'/dir2'</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'coffee'</span></div><div class="line"> }, </div><div class="line"> {</div><div class="line"> <span class="attr">test</span>: <span class="regexp">/\.js$/</span>,</div><div class="line"> <span class="attr">include</span>: <span class="string">'/dir1'</span>,</div><div class="line"> <span class="attr">loader</span>: <span class="string">'babel'</span></div><div class="line"> }]</div><div class="line">}</div></pre></td></tr></table></figure>
</div>
</div>
<a class="read-all-link" href="/2016/11/19/Webpack-merge插件/">阅读全部</a>
</div>
<div class="main-footer">
本文为原创,对知识的理解有疏漏或者错误的地方,欢迎指正。如有问题,欢迎开issue。
</div>
</div>
</div>
</div>
<script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="/PhotoSwipe/photoswipe.css">
<link rel="stylesheet" href="/PhotoSwipe/default-skin/default-skin.css">
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides.
PhotoSwipe keeps only 3 of them in the DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on. -->
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
<script src="/PhotoSwipe/photoswipe.js"></script>
<script src="/PhotoSwipe/photoswipe-ui-default.js"></script>
<script src="/perfect-scrollbar/js/min/perfect-scrollbar.min.js"></script>
<script src="/scripts/main.js"></script>
</body>
</html>