-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathsearch.xml
1009 lines (1009 loc) · 809 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
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
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[复杂小程序内嵌WebView实战]]></title>
<url>%2F2019%2F09%2F27%2FWeChatWebView%2F</url>
<content type="text"><![CDATA[自用笔记:由于人员、时间问题,通常会有小程序内嵌WebView的需求。这里将整理讲解、注意事项。概况web-view 组件是一个可以用来承载网页的容器,会自动铺满整个小程序页面。个人类型与海外类型的小程序暂不支持使用。属性:src 是String类型,是一个网站的url,默认值是none,webview 指向网页的链接。需登录小程序管理后台配置域名白名单。webView文档固定指向12<!--微信小程序index.wxml--><web-view src="https://www.google.com/"></web-view>创建view壳├── view.wxml└── view.jsview.wxml123<!--pages/view/view.wxml--><web-view src="{{src}}#wechat_redirect" id="view" bindload="fnViewLoad" bindmessage="viewMessage"></web-view><!-- bindload 首次加载 -->view.js1234567891011121314151617wx.navigateTo({ url:`/pages/view/view?url=${encodeURIComponent(`personal/vips`)}`})// pages/view/view.js// 动态修改不同环境URLconst { baseUrl } = require('../../env')Page({ data: { baseUrl, }, onLoad: function(options){ // 地址过滤 options.url ? this._getViewSrc(options.url) : wx.navigateBack({delta: 2}); },})动态设置顶栏1234567891011// url 通常为转码后的地址setBarTitle (url) { let weChatSet = { farmers: { title: 'title', color: '#FFF' } } wx.setNavigationBarTitle({title: weChatSet[url].title}) wx.setNavigationBarColor({backgroundColor: '#ffffff', frontColor: weChatSet[url].color})}地址过滤地址参数必须encodeURIComponent加密才可以传输1234567_getViewSrc (url) { let src = `${this.data.baseUrl}/${decodeURIComponent(url)}` src += decodeURIComponent(url).includes("?") ? `&isMiniProgram=true` : `?isMiniProgram=true` if (wx.getStorageSync("token")) src += `&token=${wx.getStorageSync("token")}` src = src.replace(/([\u4e00-\u9fa5]+)/g, dest => encodeURIComponent(dest)) this.setData({src})}分享页面配置onShareAppMessage12345678onShareAppMessage (e) { let url = e.webViewUrl.split(this.data.baseUrl + '/')[1].split('&').filter(item => !item.includes('token')).join('&'); let url = e.webViewUrl.split(this.data.baseUrl + '/')[1].replace(/$/g, '&').replace(/token=[^]+?[$|&]/g, '').replace(/&$/g, '') let shareId = getApp().globalData.shareId ? getApp().globalData.shareId : ''; return { path: `/pages/view/view?url=${encodeURIComponent(url)}&shareId=${shareId}` }}页面消息透传1viewMessage (e) {}空白的页面从webview页面返回小程序页面(导航栏返回),会先出现一个空白页面,然后再次点击返回才能到小程序页面。(两次点击)这个问题大概就是,默认过来src的值是空,导致页面第一页为空页面,然后进入到正确的页面。请升级微信客户端到 6.5.16web-view采坑打开的域名没有在小程序管理后台设置业务域名(注意是业务域名,不是服务器域名)打开的页面必须为https服务打开的页面302过去的地址也必须设置过业务域名web-view空白问题,请升级微信客户端到 6.5.16页面可以包含iframe,但是iframe的地址必须为业务域名web-view不支持支付能力,web-view的API能力见web-view的文档说明开发者自己检查自己的https服务是否正常,测试方法:普通浏览器打开对应的地址如果web-view使用了公众号授权的服务,开发者工具提示网页开发者的问题,请见:公众号开发关于小程序和web-view的通信,<web-view/> → 小程序只能通过JSSDK 1.3.0提供的接口返回小程序页面,设置参数来传值,反之,小程序到webview也是一样的,只能是src的路径带上参数H5回调小程序如何从H5回到小程序wx.miniProgram.navigateTo1234567891011121314151617import wx from '~/utils/sdk-wechat.js'wx.miniProgram.navigateTo({ url: `/pages/login/login?url=${encodeURIComponent(url)}`})wx.miniProgram.navigateBack({ url: `/pages/login/login?url=${encodeURIComponent(url)}`})wx.miniProgram.switchTab({ url: `/pages/login/login?url=${encodeURIComponent(url)}`})wx.miniProgram.reLaunch({ url: `/pages/login/login?url=${encodeURIComponent(url)}`})wx.miniProgram.redirectTo({ url: `/pages/login/login?url=${encodeURIComponent(url)}`})环境检测123wx.miniProgram.getEnv(res => { if (res.miniprogram) console.log('miniProgram')})向小程序发送消息对消息组件进行封装,添加支付,弹窗,提示,分享等原生接口。123456789share () { // 向小程序发送消息 let postData = { url: window.location.href, title: Response.username + ":" + Response.title, image: Response.image }; wx.miniProgram.postMessage({ data: JSON.stringify(postData) });},postMessage需要配合bindmessage使用分享]]></content>
<categories>
<category>WeChat</category>
</categories>
<tags>
<tag>WeChat</tag>
</tags>
</entry>
<entry>
<title><![CDATA[翻转卡片]]></title>
<url>%2F2019%2F08%2F27%2FJsCardCss%2F</url>
<content type="text"><![CDATA[CSS3动画探秘:平时喜欢研究动效,下面来分析如何实现设计师的效果程序员追着打系列 by Hoang Nguyen☻@keyframes circle{from{transform:rotate(-90deg)}to{transform:rotate(90deg)}}@keyframes inner-circle{from{transform:rotate(-90deg)}to{transform:rotate(-270deg)}}.anim{width:100px;height:100px;margin:20px auto 0;text-align:center;color:orange;font-size:100px;line-height:1;animation:circle 5s linear infinite;transform-origin:50% 200px}.anim>div{animation:inner-circle 5s linear infinite}效果分析卡片移动距离旋转角度计算最大触电移动距离移动速度联动角度、距离的变化由于只有效果图,数值只能靠肉眼感觉来调整。]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[大胆尝试 复杂动画效果]]></title>
<url>%2F2019%2F08%2F27%2FCSSLineAnim%2F</url>
<content type="text"><![CDATA[CSS3动画探秘:平时喜欢研究动效,下面来分析如何实现设计师的效果点与线动效设计——作者:Vitaly Silkin运动的小球直线移动直线运动,固定时间点颜色值变化。由于把时间拆分的很均匀,导致One球移动的不流畅.anim{position:relative;width:389px;margin:auto;padding:39px}.ani{width:40px;height:40px;border-radius:40px;float:left;margin-right:20px;transition:background .5s}.colr1{animation:colr1 2s infinite cubic-bezier(.02,.01,.21,1);opacity:1}.colr2{background:#ff6f22;animation:colr2 2s infinite cubic-bezier(.02,.01,.21,1)}.colr3{background:#ff4c41;animation:colr3 2s infinite cubic-bezier(.02,.01,.21,1)}.colr4{background:#ff2265;animation:colr4 2s infinite cubic-bezier(.02,.01,.21,1)}.colr5{background:#ff0a79;animation:colr5 2s infinite cubic-bezier(.02,.01,.21,1)}@keyframes colr1{0%{background:#ff9206}12.5%{background:#ff6f22;transform:translate(60px)}25%{background:#ff4c41;transform:translate(120px)}37.5%{background:#ff2265;transform:translate(180px)}50%{background:#ff0a79;transform:translate(240px)}62.5%{background:#ff2265;transform:translate(180px)}75%{background:#ff4c41;transform:translate(120px)}87.5%{background:#ff6f22;transform:translate(60px)}100%{background:#ff9206}}@keyframes colr2{0%{transform:rotate(0);transform-origin:20px 0}6.25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}12.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}75%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}87.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}93.75%{transform:rotate(0);transform-origin:20px 0}}@keyframes colr3{12.5%{transform:rotate(0);transform-origin:20px 0}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}75%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}87.5%{transform:rotate(0);transform-origin:20px 0}}@keyframes colr4{25%{transform:rotate(0);transform-origin:20px 0}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}75%{transform:rotate(0);transform-origin:20px 0}}@keyframes colr5{37.5%{transform:rotate(0);transform-origin:20px 0}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(0);transform-origin:20px 0}}1234567<div class="anim"> <div class="ani colr1"></div> <div class="ani colr2"></div> <div class="ani colr3"></div> <div class="ani colr4"></div> <div class="ani colr5"></div></div>123456789101112131415161718192021222324252627282930313233343536@keyframes colr1{ 0%{ background: #ff9206; } 12.5%{ background: #ff6f22; transform: translate(60px); } 25%{ background: #ff4c41; transform: translate(120px); } 37.5%{ background: #ff2265; transform: translate(180px); } 50%{ background: #ff0a79; transform: translate(240px); } 62.5%{ background: #ff2265; transform: translate(180px); } 75%{ background: #ff4c41; transform: translate(120px); } 87.5%{ background: #ff6f22; transform: translate(60px); } 100%{ background: #ff9206; }}直线移动优化效果.anim{position:relative;height:100px}.ani{width:40px;height:40px;border-radius:40px;float:left;margin-right:20px;transition:background .5s}.colrT1{animation:colrT1 2s infinite cubic-bezier(.02,.01,.21,1);opacity:1}.colrT2{background:#ff6f22;animation:colrT2 2s infinite cubic-bezier(.02,.01,.21,1)}.colrT3{background:#ff4c41;animation:colrT3 2s infinite cubic-bezier(.02,.01,.21,1)}.colrT4{background:#ff2265;animation:colrT4 2s infinite cubic-bezier(.02,.01,.21,1)}.colrT5{background:#ff0a79;animation:colrT5 2s infinite cubic-bezier(.02,.01,.21,1)}@keyframes colrT1{0%{background:#ff9206}12.5%{background:#ff6f22}25%{background:#ff4c41}37.5%{background:#ff2265}50%{background:#ff0a79;transform:translate(240px)}62.5%{background:#ff2265}75%{background:#ff4c41}87.5%{background:#ff6f22}100%{background:#ff9206}}@keyframes colrT2{0%{transform:rotate(0);transform-origin:20px 0}6.25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}12.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}70%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}86.5%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrT3{6.25%{transform:rotate(0);transform-origin:20px 0}12.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}58.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}75%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrT4{12.5%{transform:rotate(0);transform-origin:20px 0}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}52.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}65%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrT5{15%{transform:rotate(0);transform-origin:20px 0}39.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(0);transform-origin:20px 0}}优化效果调整距离的控制,但随之而来的是时间的不固定。123456789101112131415161718192021222324252627282930313233343536@keyframes colrT1{ 0%{ background: #ff9206; } 12.5%{ background: #ff6f22; /*transform: translate(60px);*/ } 25%{ background: #ff4c41; /*transform: translate(120px);*/ } 37.5%{ background: #ff2265; /*transform: translate(180px);*/ } 50%{ background: #ff0a79; transform: translate(240px); } 62.5%{ background: #ff2265; /*transform: translate(180px);*/ } 75%{ background: #ff4c41; /*transform: translate(120px);*/ } 87.5%{ background: #ff6f22; /*transform: translate(60px);*/ } 100%{ background: #ff9206; }}选择方式优化☻@keyframes circle{from{transform:rotate(-90deg)}to{transform:rotate(90deg)}}@keyframes inner-circle{from{transform:rotate(-90deg)}to{transform:rotate(-270deg)}}.animB{width:100px;height:100px;margin:20px auto 0;text-align:center;color:orange;font-size:100px;line-height:1;animation:circle 5s linear infinite;transform-origin:50% 200px}.animB>div{animation:inner-circle 5s linear infinite}.anim{position:relative;height:100px}.ani .colrY{width:40px;height:40px;border-radius:40px;float:left;margin-right:20px;transition:background .5s}.colrY1{animation:colrY1 2s infinite cubic-bezier(.02,.01,.21,1);opacity:1}.colrY2{background:#ff6f22;animation:colrY2 2s infinite cubic-bezier(.02,.01,.21,1)}.colrY3{background:#ff4c41;animation:colrY3 2s infinite cubic-bezier(.02,.01,.21,1)}.colrY4{background:#ff2265;animation:colrY4 2s infinite cubic-bezier(.02,.01,.21,1)}.colrY5{background:#ff0a79;animation:colrY5 2s infinite cubic-bezier(.02,.01,.21,1)}@keyframes colrY1{0%{background:#ff9206}12.5%{background:#ff6f22}25%{background:#ff4c41}37.5%{background:#ff2265}50%{background:#ff0a79;transform:translate(240px)}62.5%{background:#ff2265}75%{background:#ff4c41}87.5%{background:#ff6f22}100%{background:#ff9206}}@keyframes colrY2{0%{transform:rotate(0);transform-origin:20px 0}6.25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}12.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}70%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}86.5%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrY3{6.25%{transform:rotate(0);transform-origin:20px 0}12.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}58.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}75%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrY4{12.5%{transform:rotate(0);transform-origin:20px 0}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}52.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}65%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrY5{15%{transform:rotate(0);transform-origin:20px 0}39.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(0);transform-origin:20px 0}}运动的方块.anim{position:relative;height:100px}.ani1{width:40px;height:40px;border-radius:6px;float:left;margin-right:20px;transition:background .5s}.colrB1{animation:colrB1 2s infinite cubic-bezier(.02,.01,.21,1);opacity:1}.colrB2{background:#1c9fff;animation:colrB2 2s infinite cubic-bezier(.02,.01,.21,1)}.colrB3{background:#21b7fd;animation:colrB3 2s infinite cubic-bezier(.02,.01,.21,1)}.colrB4{background:#25ccfb;animation:colrB4 2s infinite cubic-bezier(.02,.01,.21,1)}.colrB5{background:#24d3fb;animation:colrB5 2s infinite cubic-bezier(.02,.01,.21,1)}@keyframes colrB1{0%{background:#1894ff}12.5%{background:#1c9fff}25%{background:#21b7fd}37.5%{background:#25ccfb}50%{background:#24d3fb;transform:translate(240px)}62.5%{background:#25ccfb}75%{background:#21b7fd}87.5%{background:#1c9fff}100%{background:#1894ff}}@keyframes colrB2{0%{transform:rotate(0);transform-origin:20px 0}6.25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}12.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}70%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}86.5%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrB3{6.25%{transform:rotate(0);transform-origin:20px 0}12.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}58.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}75%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrB4{12.5%{transform:rotate(0);transform-origin:20px 0}25%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}37.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}52.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}65%{transform:rotate(0);transform-origin:20px 0}}@keyframes colrB5{15%{transform:rotate(0);transform-origin:20px 0}39.5%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}50%{transform:rotate(-360deg) translate(-60px);transform-origin:-30px -20px}62.5%{transform:rotate(0);transform-origin:20px 0}}]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[ES6 节流和防抖详解]]></title>
<url>%2F2019%2F08%2F27%2FES6Throttle%2F</url>
<content type="text"><![CDATA[自用笔记:在浏览器DOM事件里面,有一些事件会随着用户的操作不间断触发。比如:重新调整浏览器窗口大小(resize),浏览器页面滚动(scroll),鼠标移动(mousemove)。也就是说用户在触发这些浏览器操作的时候,如果脚本里面绑定了对应的事件处理方法,这个方法就不停的触发。这并不是我们想要的,因为有的时候如果事件处理方法比较庞大,DOM 操作比如复杂,还不断的触发此类事件就会造成性能上的损失,导致用户体验下降(UI 反映慢、浏览器卡死等)。所以通常来讲我们会给相应事件添加延迟执行的逻辑。debounce 与 throttle 是开发中常用的高阶函数,作用都是为了防止函数被高频调用,换句话说就是,用来控制某个函数在一定时间内执行多少次。效果可视化在此区域移动你的鼠标节流概念(Throttle)定义: 如果一个函数持续的,频繁地触发,那么让它在一定的时间间隔后再触发。由于执行速度过快,并携带相邻数据相差不大,节流可以高效的优化执行效果。应用场景scroll、touchmove节流实现首次执行通过时间比对,屏蔽多次提交,缺点:最后一个动作不会被触发12345678910111213141516171819202122232425262728function throttles(fn, wait = 100){ let last = 0; console.log('节流函数 启动') return function(){ let curr = +new Date(); // 强制转换为数字Number if(curr - last > wait){ fn.apply(this, arguments); last = curr; } }}let fun = new throttle(test, 2000)function test(e) { console.log(e)}let funss = (m, n) => Array.apply(null, new Array(m)).map(() => n++)let arr = funss(100, 1)arr.forEach(item => { fun('funcs')})// 节流函数 启动// funcswindow.onresize = throttle(test, 200);window.onresize = function () { fun('funcs')}首次不执行首次不执行,delay时间内只执行滞后一次,通过判断timer,进行判断延迟执行,预执行期间,去除其他执行请求。123456789101112131415161718192021function throttles2(fn, delay = 100){ //首先设定一个变量,在没有执行我们的定时器时为null let timer = null; return function(){ //当我们发现这个定时器存在时,则表示定时器已经在运行中,需要返回 if(timer) return; timer = setTimeout(() => { fn.apply(this,arguments); timer = null; }, delay); }}function test(e) { console.log(e)}let fun = new throttle(test, 2000)let funss = (m, n) => Array.apply(null, new Array(m)).map(() => n++)let arr = funss(100, 1)arr.forEach(item => { fun('funcs')})throttle优点:成功的优化最后一针的位置123456789101112131415161718function throttle (fn, wait = 250, options) { let lastTime, timerId return function () { let context = options || this let currentTime = +new Date let args = arguments if (lastTime && currentTime < lastTime + wait) { clearTimeout(timeId) timeId = setTimeout(function() { lastTime = currentTime fn.apply(context, args) }, wait); } else { lastTime = currentTime fn.apply(context, args) } }}lodash缺点无法获取参数,时间比对问题,属于首次执行的防抖的方法1234567891011121314151617181920function throttle(fn, wait, options) { wait = wait || 0; var timerId, lastTime = 0; function throttled() { var currentTime = new Date(); if (currentTime >= lastTime + wait) { fn(); lastTime = currentTime; } else { if (timerId) { clearTimeout(timerId); timerId = null; } timerId = setTimeout(function() { fn() }, wait); } } return throttled;}underscoreunderscore提供了一系列函数式接口123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172// 返回一个函数,只要这段时间被调戏就不会触发。函数停止后N毫秒触发,debounce = function(func, wait, immediate) { var timeout, result; var later = function(context, args) { timeout = null; if (args) result = func.apply(context, args); }; var debounced = restArgs(function(args) { if (timeout) clearTimeout(timeout); if (immediate) { var callNow = !timeout; timeout = setTimeout(later, wait); if (callNow) result = func.apply(this, args); } else { timeout = _.delay(later, wait, this, args); } return result; }); debounced.cancel = function() { clearTimeout(timeout); timeout = null; }; return debounced;};let fun = new debounce(test, 2000)let funss = (m, n) => Array.apply(null, new Array(m)).map(() => n++)let arr = funss(100, 1)arr.forEach(item => { fun('funcs')})// Returns a function, that, when invoked, will only be triggered at most once// during a given window of time. Normally, the throttled function will run// as much as it can, without ever going more than once per `wait` duration;// but if you'd like to disable the execution on the leading edge, pass// `{leading: false}`. To disable execution on the trailing edge, ditto.throttle = function(func, wait, options) { var timeout, context, args, result; var previous = 0; if (!options) options = {}; var later = function() { previous = options.leading === false ? 0 : new Date(); timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; //显示地释放内存,防止内存泄漏 }; var throttled = function() { var now = new Date(); if (!previous && options.leading === false) previous = now; var remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } return result; }; throttled.cancel = function() { clearTimeout(timeout); previous = 0; timeout = context = args = null; }; return throttled;};防抖概念(Debounce)定义: 如果一个函数在一段时间间隔中,持续地触发,那么只在它结束后过一段时间只执行一次。注意:这里的抖动停止表示你停止了触发这个函数,从这个时间点开始计算,当间隔时间等于你设定时间,才会执行里面的回调函数。如果你一直在触发这个函数并且两次触发间隔小于设定时间,则一定不会到回调函数那一步。·应用场景input验证、搜索联想、resize防抖实现思路:首次运行时把定时器赋值给一个变量,第二次执行时,如果间隔没超过定时器设定的时间则会清除掉定时器,重新设定定时器,依次反复,当我们停止下来时,没有执行清除定时器,超过一定时间后触发回调函数。首次立即执行首次执行,延后多次执行的最后一次时间。同上12345678910111213141516171819202122232425262728293031function throttle(fn, wait = 100, options) { let timerId, lastTime = 0; console.log('节流函数 启动') return function() { let currentTime = new Date(); if (currentTime >= lastTime + wait) { console.log(timerId, lastTime) fn.apply(this, arguments); lastTime = currentTime; } else { if (timerId) { clearTimeout(timerId); timerId = null; } timerId = setTimeout(() => { console.log(timerId, lastTime) fn.apply(this, arguments); }, wait); } }}function test(e) { console.log('test', e)}let fun = new throttle(test, 2000)let funss = (m, n) => Array.apply(null, new Array(m)).map(() => n++)let arr = funss(100, 1)arr.forEach(item => { console.log(item) fun('funcs')})延迟执行最后一个指令123456789101112function debounce(fn, delay) { let timerId; return function (...args) { if (timerId) { clearTimeout(timerId); } timerId = setTimeout(() => { fn(...args); timerId = null; }, delay); }}123456789101112function debounce (fn, wait, options) { var timeout; return function () { var context = options || this, args = arguments; var later = function () { timeout = null; fn.apply(context, args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); };},1234567891011121314151617181920function debounce(fn, wait, options) { var timer = null; var previous = null; return function () { var now = +new Date(); if ( !previous ) previous = now; if ( options && now - previous > options ) { fn(); // 重置上一次开始时间为本次结束时间 previous = now; clearTimeout(timer); } else { clearTimeout(timer); timer = setTimeout(function() { fn(); previous = null; }, wait); } }};123456789101112131415161718192021222324function debounce(fn, delay = 200, atBegin = true) { let timer = null, last = 0,during; return function () { let self = this, args = arguments; var exec = function () { fn.apply(self, args); } if (atBegin && !timer) { exec(); atBegin = false; } else { during = Date.now() - last; if (during > delay) { exec(); } else { if (timer) clearTimeout(timer); timer = setTimeout(function () { exec(); }, delay); } } last = Date.now(); }}123456789// 避免在滚动时过分的更新定位jQuery(window).on('scroll', _.throttle(updatePosition, 100));// 点击后就调用 `renewToken`,但5分钟内超过1次。var throttled = _.throttle(renewToken, 300000, { 'trailing': false });jQuery(element).on('click', throttled);// 取消一个 trailing 的节流调用jQuery(window).on('popstate', throttled.cancel);1234567891011121314151617// 避免窗口在变动时出现昂贵的计算开销。jQuery(window).on('resize', _.debounce(calculateLayout, 150));// 当点击时 `sendMail` 随后就被调用。jQuery(element).on('click', _.debounce(sendMail, 300, { 'leading': true, 'trailing': false}));// 确保 `batchLog` 调用1次之后,1秒内会被触发。var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });var source = new EventSource('/stream');jQuery(source).on('message', debounced);// 取消一个 trailing 的防抖动调用jQuery(window).on('popstate', debounced.cancel);以上就是节流和防抖的全部介绍body{font-family:Roboto,Helvetica,Arial;font-weight:200}.box{width:100%;overflow:hidden}#moveonme{width:100%;height:200px;border:1px solid #aaa;box-sizing:border-box;padding:25px;text-align:center;font-size:18px}.backtoblog{width:200px;padding:10px;background:#f5f5f5;border:1px solid #aaa;color:#777;display:inline-block;text-decoration:none;transition:.2s all;box-sizing:border-box;position:relative;top:-1px;text-align:center}.backtoblog:hover{border:1px solid #aaa;background:0 0}var helpers = { /** * debouncing, executes the function if there was no new event in $wait milliseconds * @param func * @param wait * @param options * @returns {Function} */ debounce: function (fn, wait, options) { var timeout; return function () { var context = options || this, args = arguments; var later = function () { timeout = null; fn.apply(context, args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }, throttles: function (fn, wait = 200, options) { let last = 0; console.log('节流函数 启动') return function(){ let curr = +new Date(); // 强制转换为数字Number if(curr - last > wait){ fn.apply(this, arguments); last = curr; } } }, /** * in case of a "storm of events", this executes once every $threshold * @param fn * @param threshhold * @param options * @returns {Function} */ throttle: function (fn, wait = 250, options) { var lastTime, timerId; return function () { var context = options || this; var currentTime = +new Date, args = arguments; if (lastTime && currentTime < lastTime + wait) { // hold on to it clearTimeout(timerId); timerId = setTimeout(function () { lastTime = currentTime; fn.apply(context, args); }, wait); } else { lastTime = currentTime; fn.apply(context, args); } }; } } function NIM_demo(){ this.canvas = document.getElementById("paintonme"); this.context = this.canvas.getContext("2d"); this.movearea = document.getElementById("moveonme"); this.canvasTimeScale = 5 * 1000; this.paintColors = ["#bbd", "#464", "#d99", "#d77", "#d44"]; this.totalLanes = this.paintColors.length; this.leftMargin = 100; var self = this; this.init = function(){ // this.canvas.width = window.innerWidth - 200; this.flush(); this.movearea.addEventListener("mousemove", this.regularHandler); this.movearea.addEventListener("mousemove", helpers.debounce(self.debounceHandler, 100, this)); this.movearea.addEventListener("mousemove", helpers.throttle(self.throttleHander, 100, this)); this.movearea.addEventListener("mousemove", helpers.throttles(self.throttleHanders, 100,this)); } /** * painting the rectangle / line * @param lane * @param time */ this.paintRect = function(lane,time){ if(time > this.canvasTimeScale){ this.startTime += time; time = 0; this.flush() } // console.log(lane,time); this.context.fillStyle = this.paintColors[lane]; var x = (this.canvas.width - this.leftMargin) / this.canvasTimeScale * time + this.leftMargin; var y = this.canvas.height / this.totalLanes * lane; var height = this.canvas.height / this.totalLanes; var width = 1; this.context.fillRect(x, y, width, height); } this.flush = function(){ this.context.fillStyle = "#000"; this.context.fillRect(0,0,this.canvas.width,this.canvas.height); this.context.font = "200 18px Roboto,Helvetica,Arial"; this.context.fillStyle = this.paintColors[0]; this.context.fillText("Regular", 0, 100); this.context.fillStyle = this.paintColors[1]; this.context.fillText("debounce", 0, 200); this.context.fillStyle = this.paintColors[2]; this.context.fillText("throttle", 0, 300); this.context.fillStyle = this.paintColors[3]; this.context.fillText("throttles", 0, 400); } /** * get the time difference * @returns {number} */ this.getTimeDiff = function(){ var time = new Date().getTime(); if(!this.startTime){ this.startTime = time; } time -= this.startTime; return time; } this.regularHandler = function(){ self.paintRect(0, self.getTimeDiff()); } this.debounceHandler = function(){ self.paintRect(1, self.getTimeDiff()); } this.throttleHander = function(){ self.paintRect(2, self.getTimeDiff()); } this.throttleHanders = function(){ self.paintRect(3, self.getTimeDiff()); } } var demo = new NIM_demo(); demo.init();]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo 添加搜索功能]]></title>
<url>%2F2019%2F07%2F27%2FHexoSearch%2F</url>
<content type="text"><![CDATA[** Hexo 主题:最为静态页面最为鸡肋的就是没有搜索功能,查找文件夹十分困难。第三方插件不稳定。今天就来实现内部功能。插件hexo-generator-json-content搜索功能jsonContent:meta: falsepages: falseposts:title: truedate: truepath: truetext: falseraw: falsecontent: trueslug: trueupdated: falsecomments: truelink: falseauthor: truepermalink: trueexcerpt: falsecategories: truetags: true插件会自动生成content.json文件,对文件数据进行查询。动态获取数据123456// 动态获取数据$('#local-search-input').bind('input propertychange', e => { let val = $('#local-search-input').val() if (window.history && window.history.pushState) val ? history.pushState({}, 'jsdig', '?search=' + val) : history.pushState({}, 'jsdig', '/') searchTool.searchGo(val)})123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135var searchTool = { data: [], arrList: [], oldList: [], init () { this.fetchJson() }, fetchJson () { window.fetch(CONFIG.root + 'content.json?t=' + (+ new Date()), { method: 'get', }).then((res) => { console.log(res) return res.json() }).then((data) => { console.log(data) this.data = data this.searchList() }).catch((err) => { console.log(err) }); }, // 搜索字符串里面是否存在关键字 isSreachIndexOF (oldstr, kw) { // console.log(oldstr, kw) var istrue = false // console.log('isSreachIndexOF', oldstr && toString.call(oldstr) === '[object Array]') if (oldstr && toString.call(oldstr) === '[object Array]') { for (var i = 0; i < oldstr.length; i++) { oldstr[i].toLowerCase() === kw.toLowerCase() ? istrue = true : null } return istrue } // console.log('isSreachIndexOF', !oldstr, !kw) if (!oldstr || !kw) return false istrue = oldstr.toLowerCase().indexOf(kw.toLowerCase()) > -1 return istrue }, searchList () { let divList = '' this.data.forEach(item => { divList += ` <li> <a href="/${item.path}" class="search-result-title">${item.title}</a> <div class="main"> <p class="left"> <span>${item.author ? item.author : 'Luuman'}</span> ${item.tags.map(tags => `<a href="/tags/${tags.slug}" class="search-result-tags">${tags.name}</a>`)} </p> <p class="right">${this.getFriendlyTime(item.date.replace('T', ' '), new Date())}</p> </div> </li>` }) // <p class="search-content">${item.content}</p> $('.search-result-list').html(divList) }, clear () { this.oldList.forEach(item => { $(".search-result-list li")[item].style.display = 'none' }) this.oldList = [] }, add () { this.arrList.forEach(item => { $(".search-result-list li")[item].style.display = 'block' }) this.oldList = this.arrList }, searchGo (keywolds) { this.arrList = [] if (!keywolds) { if (this.oldList.length) this.clear() } else { this.data.forEach((item, index) => { if (this.isSreachIndexOF(item.title, keywolds) || this.isSreachIndexOF(item.tags.map(item => item.name).join('-'), keywolds) || this.isSreachIndexOF(item.categories.map(item => item.name).join('-'), keywolds) || this.isSreachIndexOF(item.content, keywolds)) { this.arrList.push(index) } }) if (this.oldList.length) this.clear() if (this.arrList.length) this.add() } }, /** * 获取指定时间的友好时间字符串。 * @param str 指定的时间字符串,如yyyy-MM-dd HH:mm:ss * @param now 当前时间,允许时间戳,GMT时间,如果该参数为undefined,则使用浏览器时间。 */ getFriendlyTime (str, now) { var currentTime = new Date(now); var arr = str.split(/\s+/gi); var temp = 0, arr1, arr2, oldTime, delta; var getIntValue = function(ss, defaultValue){ try{ return parseInt(ss, 10); }catch (e){ return defaultValue; } }; var getWidthString = function(num){ return num < 10 ? ('0' + num) : num; }; if(arr.length >= 2){ arr1 = arr[0].split(/[\/\-]/gi); arr2 = arr[1].split(':'); oldTime = new Date(); oldTime.setYear(getIntValue(arr1[0], currentTime.getFullYear())); oldTime.setMonth(getIntValue(arr1[1], currentTime.getMonth() + 1) - 1); oldTime.setDate(getIntValue(arr1[2], currentTime.getDate())); oldTime.setHours(getIntValue(arr2[0], currentTime.getHours())); oldTime.setMinutes(getIntValue(arr2[1], currentTime.getMinutes())); oldTime.setSeconds(getIntValue(arr2[2], currentTime.getSeconds())); delta = currentTime.getTime() - oldTime.getTime(); if (delta <= 60 * 1000) { return '1分钟内'; } else if (delta < 60 * 60 * 1000) { return Math.floor(delta / (60 * 1000)) + '分钟前'; } else if (delta < 24 * 60 * 60 * 1000) { return Math.floor(delta / (60 * 60 * 1000)) + '小时前'; } else if (delta < 24 * 60 * 60 * 1000 * 30) { return Math.floor(delta / (24 * 60 * 60 * 1000)) + '天前'; } else if (delta < 24 * 60 * 60 * 1000 * 30 * 12) { return Math.floor(delta / (24 * 60 * 60 * 1000 * 30)) + '月前'; } else if (currentTime.getFullYear() != oldTime.getFullYear()){ return [getWidthString(oldTime.getFullYear()), getWidthString(oldTime.getMonth() + 1), getWidthString(oldTime.getDate())].join('-') } else { return [getWidthString(oldTime.getMonth() + 1), getWidthString(oldTime.getDate())].join('-'); } } return ''; }}console.log('err')searchTool.init()]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[LeetCode 报数]]></title>
<url>%2F2019%2F07%2F27%2FLeetCode38%2F</url>
<content type="text"><![CDATA[自用笔记:报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:1112112111112211234567891011121314151617181920function showNum (num, n = 1) { let funss = (m,n)=> Array.apply(null,new Array(m)).map(()=>n++) let arr = funss(num, n) arr.forEach((arrA, key) => { if (key) { let arrY = String(arr[key - 1]).split('') let arrB = [] arrY.filter((item, index) => { if (index && item == arrY[index - 1]) { arrB[arrB.length - 1] += item } else { arrB.push(item) } }) arr[key] = arrB.map(item => `${item.length}${item.slice(0, 1)}`).join('') } }) return arr[num - 1]}console.log(showNum(10))1234567891011function showNum(key) { let Arr = new Array(key).fill('').map((item, index) => String(index + 1)); Arr.reduce((ArrA, ArrB) => { let redA = ArrA == 1 ? '11' : ArrA.split('').reduce((arrC, arrD) => { return arrC.length - 1 == 0 ? arrC == arrD ? `2${arrD}` : `1${arrC}1${arrD}` : arrC.slice(arrC.length - 1, arrC.length) == arrD ? `${arrC.slice(0, arrC.length - 2 > 0 ? arrC.length - 2 : 0)}${+arrC.slice(arrC.length - 2, arrC.length - 1) + 1}${arrD}` : `${arrC}1${arrD}` }) console.log("ArrB", ArrB, redA) return redA })}showNum(10)]]></content>
<categories>
<category>LeetCode</category>
</categories>
<tags>
<tag>LeetCode</tag>
</tags>
</entry>
<entry>
<title><![CDATA[小程序知识点总结]]></title>
<url>%2F2019%2F07%2F27%2FweChatAPI%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyPagepage()函数注册页面属性类型说明dataObject页面的初始数据onLoadfunction生命周期回调—监听页面加载onShowfunction生命周期回调—监听页面显示onReadyfunction生命周期回调—监听页面初次渲染完成onHidefunction生命周期回调—监听页面隐藏onUnloadfunction生命周期回调—监听页面卸载onPullDownRefreshfunction监听用户下拉动作onReachBottomfunction页面上拉触底事件的处理函数onShareAppMessagefunction用户点击右上角转发onPageScrollfunction页面滚动触发事件的处理函数onResizefunction页面尺寸改变时触发,详见 响应显示区域变化onTabItemTapfunction当前是 tab 页时,点击 tab 时触发其他any开发者可以添加任意的函数或数据到 Object 参数中,在页面的函数中用 this 可以访问123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354//index.jsPage({ data: { text: "This is page data." }, onLoad: function(options) { // 页面创建时执行 }, onShow: function() { // 页面出现在前台时执行 }, onReady: function() { // 页面首次渲染完毕时执行 }, onHide: function() { // 页面从前台变为后台时执行 }, onUnload: function() { // 页面销毁时执行 }, onPullDownRefresh: function() { // 触发下拉刷新时执行 }, onReachBottom: function() { // 页面触底时执行 }, onShareAppMessage: function () { // 页面被用户分享时执行 }, onPageScroll: function() { // 页面滚动时执行 }, onResize: function() { // 页面尺寸变化时执行 }, onTabItemTap(item) { // tab 点击时执行 console.log(item.index) console.log(item.pagePath) console.log(item.text) }, // 事件响应函数 viewTap: function() { this.setData({ text: 'Set some data for updating view.' }, function() { // this is setData callback }) }, // 自由数据 customData: { hi: 'MINA' }})下拉刷新onPullDownRefresh () {} 触发下拉刷新时执行下拉效果enablePullDownRefresh123456789{ "enablePullDownRefresh": true //当前页 "backgroundTextStyle": "dark" //顶部显示颜色为深色的三个点}"window": { "enablePullDownRefresh": true //全局 "backgroundTextStyle": "dark" //顶部显示颜色为白色的三个点}1234567891011onPullDownRefresh: function () { var that = this; that.setData({ currentTab: 0 //当前页的一些初始数据,视业务需求而定 }) this.onLoad(); //重新加载onLoad()},onLoad: function (options) { wx.stopPullDownRefresh() //刷新完成后停止下拉刷新动效 //后面的业务代码大家自行发挥},下拉刷新onPullDownRefresh () {} 触发下拉刷新时执行123456789onReachBottom () { console.log('onReachBottom') wx.showLoading({ title: '玩命加载中', })},<!-- 关闭弹窗 -->wx.hideLoading()API获取某个元素wx.createSelectorQuery().select(‘#the-id’).boundingClientRect(function(rect){}).exec()属性说明id节点的IDdataset节点的datasetleft节点的左边界坐标right节点的右边界坐标top节点的上边界坐标bottom节点的下边界坐标width节点的宽度height节点的高度动态设置顶部导航栏的背景色wx.setNavigationBarTitle(OBJECT)属性变量必传解释title类型:String必填:是说明:页面的标题success类型:Function必填:否说明:接口调用成功的回调函数fail类型:Function必填:否说明:接口调用失败的回调函数complete类型:Function必填:否说明:接口调用结束的回调函数(调用成功或失败都会执行)123wx.setNavigationBarTitle({ title: 'title'})动态设置顶部导航栏的背景色属性变量必传解释fontColorString是前景颜色值,包括按钮、标题、状态栏的颜色,仅支持#fff和#000backgroundColorString是背景颜色,有效值为16进制颜色animationObject否动画效果animation.durationNumber否动画变化时间,默认0,单位(毫秒)animation.timingFuncString否动画变化方式,默认linearsuccessFunction否接口调用成功的回调函数failFunction否接口调用失败的回调函数completeFunction否接口调用结束的回调函数(成功、失败都会执行)1234wx.setNavigationBarColor({ frontColor: '#ffffff', backgroundColor: '#ff0000'})12345678wx.setNavigationBarColor({ frontColor: '#ffffff', backgroundColor: '#ff0000', animation: { duration: 400, timingFunc: 'easeIn' }})滑动监听1234onPageScroll: function(res) { console.log(res)},// {scrollTop: 14}返回顶部及获取滑动距离12345678910111213//返回顶部 goScrolltop:function(e){ if (wx.pageScrollTo) { wx.pageScrollTo({ scrollTop: 0 }) } else { wx.showModal({ title: '提示', content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。' }) } },监听数据变化1234567891011121314151617181920212223242526/** * 设置监听器 */setWatcher(data, watch) { // 接收index.js传过来的data对象和watch对象 Object.keys(watch).forEach(v => { // 将watch对象内的key遍历 this.observe(data, v, watch[v]); // 监听data内的v属性,传入watch内对应函数以调用 })},/** * 监听属性 并执行监听函数 */observe(obj, key, watchFun) { var val = obj[key]; // 给该属性设默认值 Object.defineProperty(obj, key, { configurable: true, enumerable: true, set (value) { val = value; watchFun(value, val); // 赋值(set)时,调用对应函数 }, get () { return val; } })},获取某个元素或组件距离顶部的初始高度可以获取元素的到顶部的高度,但是要双层动态监听导致元素效果不够流畅,而且没有必要。1234let query = wx.createSelectorQuery()query.select('#index-nav').boundingClientRect( (rect) => { let top = rect.top}).exec()优化效果获取上层盒子的高度height,细微调整效果。123456setTimeout(f => { let query = wx.createSelectorQuery() query.select('#index').boundingClientRect( (rect) => { let top = rect.top }).exec()}, 500)wx.showLoading()阻止屏幕滑动12345wx.showLoading({ title:'加载中', mask:true})//mask是防止屏幕穿透的,默认是false,所以想要拦截屏幕滑动事件,就一定要记得写这一行组件开发Component 构造函数123456789101112131415161718192021222324252627282930313233343536373839404142Component({ behaviors: [], properties: { myProperty: { // 属性名 type: String, value: '' }, myProperty2: String // 简化的定义方式 }, data: {}, // 私有数据,可用于模板渲染 lifetimes: { // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 attached: function () { }, moved: function () { }, detached: function () { }, }, // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 attached: function () { }, // 此处attached的声明会被lifetimes字段中的声明覆盖 ready: function() { }, pageLifetimes: { // 组件所在页面的生命周期函数 show: function () { }, hide: function () { }, resize: function () { }, }, methods: { onMyButtonTap: function(){ this.setData({ // 更新属性和数据的方法与更新页面数据的方法类似 }) }, // 内部方法建议以下划线开头 _myPrivateMethod: function(){ // 这里将 data.A[0].B 设为 'myPrivateData' this.setData({ 'A[0].B': 'myPrivateData' }) }, _propertyChange: function(newVal, oldVal) { } }})父级调用组件内的自定义方法123<view id="index-nav"></view>this.IndexNav = this.selectComponent("#index-nav")this.triggerEvent(‘myevent’)swiperswiper调用组件中的方法1<card-sroll id="index-nav"></card-sroll>123456789onReady () { this.IndexNav = this.selectComponent("#index-nav") app.getSetting(); this.showIndexList() this.getWeatherInfo(app.globalData.adcode);},setHeight () { this.IndexNav.setHeight('0')},]]></content>
<categories>
<category>WeChat</category>
</categories>
<tags>
<tag>WeChat</tag>
</tags>
</entry>
<entry>
<title><![CDATA[小程序实现卡片]]></title>
<url>%2F2019%2F06%2F27%2FweChatMoveCard%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why返回顶部及获取滑动距离12<!-- 组件 --><card-sroll wx:if="{{List.length}}" catch:cancelAdd="cardAdd" catch:cancelCut="cardCut"></card-sroll>123456789101112<!-- 组件 --><view class="sroll"> <view class="container container1" wx:if="{{page == 1}}" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" animation="{{ani1}}"> 121212 </view> <view class="container container2" wx:if="{{page == 2}}" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" animation="{{ani2}}"> 121212 </view> <view class="container container3" wx:if="{{page == 3}}" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" animation="{{ani3}}"> 1212121 </view></view>123456789101112131415161718.container{ height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 0 25rpx; box-sizing: border-box;}.container1{}.container2{}.container3{}page{ height: 100%}属性说明touchStart触摸开始事件touchMove触摸移动事件touchEnd触摸结束事件clientX触摸目标在视口中的x坐标。clientY触摸目标在视口中的y坐标。forceidentifier标识触摸的唯一ID。pageX触摸目标在页面中的x坐标。pageY触摸目标在页面中的y坐标。move2left向左滑动操作move2right向右滑动操作screenX触摸目标在屏幕中的x坐标。screenY触摸目标在屏幕中的y坐标。12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788const app = getApp()var startX, endX;var moveFlag = true;// 判断执行滑动事件Component({ data: { page : 1, ani1: '', ani2: '', ani3: '' }, touchStart (e) { startX = e.touches[0].pageX; // 获取触摸时的原点 moveFlag = true; }, // 触摸移动事件 touchMove (e) { endX = e.touches[0].pageX; // 获取触摸时的原点 if (moveFlag) { if (endX - startX > 50) { console.log("move right"); this.move2right(); moveFlag = false; } if (startX - endX > 50) { console.log("move left"); this.move2left(); moveFlag = false; } } }, // 触摸结束事件 touchEnd (e) { moveFlag = true; // 回复滑动事件 }, //向左滑动操作 move2left () { let {page, navTab, bottomList} = this.data var that = this if (page == bottomList.length) { return } var animation = wx.createAnimation({ duration: 1000, timingFunction: 'ease', delay: 100 }); animation.opacity(0.2).translate(-500, 0).step() this.setData({ ani1: page == 1 ? animation.export() : '', ani2: page == 2 ? animation.export() : '' }) setTimeout(function () { that.setData({ page: page + 1, ani3: '', ani2: '' }); }, 800) this.triggerEvent('cancelAdd', page) }, //向右滑动操作 move2right () { let {page, navTab, bottomList} = this.data var that = this if (page == 1) { return } var animation = wx.createAnimation({ duration: 1000, timingFunction: 'ease', delay: 100 }); animation.opacity(0.2).translate(500, 0).step() this.setData({ ani3: page == 3 ? animation.export() : '', ani2: page == 2 ? animation.export() : '' }) setTimeout(function () { that.setData({ page: page - 1, ani1: '', ani2: '' }); }, 800) this.triggerEvent('cancelCut', page) }})1234``````wx]]></content>
<categories>
<category>WeChat</category>
</categories>
<tags>
<tag>WeChat</tag>
</tags>
</entry>
<entry>
<title><![CDATA[DropJS文件拖拽上传]]></title>
<url>%2F2019%2F06%2F27%2FDropJS%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why Drop your files to uploadNo recentsDrag & Drop to upload or create a new watch folder for Auto-uploaduploaddiv{color:#898c90}.box,.recent{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);animation-name:mymove;animation-duration:2s}.box .uploads{width:100px;height:100px;background:#5826e9;border-radius:50%;margin:auto;margin-bottom:50px;position:relative;z-index:111}.drop{width:400px;height:500px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin:auto;box-shadow:0 10px 21px rgba(0,0,0,.07)}.icon{color:#FFF;width:50px;height:50px;margin:25px}#box{width:100%;height:100%;position:absolute;display:none}.recent{display:block}.title{text-align:center;font-size:20px;color:#000;line-height:50px}.recent .des{font-size:12px;line-height:20px}.upload{width:120px;height:50px;line-height:50px;text-align:center;color:#FFF;background:#5826e9;border-radius:10px;margin:auto;margin-top:20px}.preloader_bubble{position:absolute;top:50px;left:50px;background-color:#5826e9;border-radius:50%;width:5px;height:5px;animation-name:loader_1;animation-duration:2.2s;animation-delay:0s;animation-iteration-count:infinite;animation-timing-function:linear;animation-play-state:running;margin-left:35px}.preloader_bubble:nth-child(2){background-color:#fd0;margin-left:45px;width:4px;height:4px;animation-delay:.5s}.preloader_bubble:nth-child(3){background-color:#2d1575;margin-left:49px;animation-delay:.6s}.preloader_bubble:nth-child(4){background-color:#2d1575;margin-left:27px;animation-delay:.7s;width:3px;height:3px}.preloader_bubble:nth-child(5){background-color:#2d1575;margin-left:50px;animation-delay:1s}.preloader_bubble:nth-child(6){background-color:#1d0e48;margin-left:14px;animation-delay:.1s}@keyframes loader_1{0%{transform:translateX(0) translateY(50px) scale(1);opacity:1}100%{transform:translateX(0) translateY(100px) scale(1);opacity:0}}@keyframes popup{100%{transform:scale(1)}}@keyframes mymove{from{margin-top:50px}to{margin-top:0}0%{opacity:.1}50%{opacity:.5}100%{opacity:1}}.files{margin:20px}.files .image{float:left;width:100px;height:50px;border-radius:6px;background-position:center;background-size:100%}.left{float:left;width:200px;margin-left:10px}.h1{font-size:16px;line-height:30px;color:#000;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.h2{font-size:14px;margin:0}.loading{float:right}window.onload = function () { var oBox = document.getElementById('box') var oRecent = document.getElementById('recent') var oContent = document.getElementById('content') var oM = document.getElementById('m1') var timer = null document.ondragover = function(){ clearTimeout(timer) timer = setTimeout(function(){ oBox.style.display = 'none' oRecent.style.display = 'block' },200) oBox.style.display = 'block' oRecent.style.display = 'none' } //进入子集的时候 会触发ondragover 频繁触发 不给ondrop机会 oBox.ondragenter = function(){ // oBox.style.display = 'block' // oRecent.style.display = 'none' // oBox.innerHTML = '请释放鼠标' } oBox.ondragover = function(){ return false } oBox.ondragleave = function(){ // oBox.style.display = 'none' // oRecent.style.display = 'block' // oBox.innerHTML = '请将文件拖拽到此区域' } oBox.ondrop = function(ev){ var oFile = ev.dataTransfer.files[0] console.log(oFile) var reader = new FileReader() //读取成功 reader.onload = function(){ console.log(reader) oRecent.style.display = 'none' oContent.innerHTML = ` ${oFile.name} ${oFile.size}字节 ` } reader.onloadstart = function(){ console.log('读取开始') } reader.onloadend = function(){ console.log('读取结束') } reader.onabort = function(){ console.log('中断') } reader.onerror = function(){ console.log('读取失败') } reader.onprogress = function(ev){ var scale = ev.loaded/ev.total if(scale>=0.5){ console.log(1) reader.abort() } oM.value = scale*100 } reader.readAsDataURL(oFile,'base64') return false }; };]]></content>
<categories>
<category>Javascript</category>
</categories>
<tags>
<tag>Javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue SSR Nuxt 国际化]]></title>
<url>%2F2018%2F08%2F25%2FNuxtI18n%2F</url>
<content type="text"><![CDATA[Vue I18n is internationalization plugin for Vue.js安装1$ npm install vue-i18n --save使用~/nuxt.config.js引入插件,启动中间件1234plugins: ['~/plugins/i18n.js'],router: { middleware: 'i18n',}~/plugins/i18n.js1234567891011121314151617181920212223import Vue from 'vue'import VueI18n from 'vue-i18n'Vue.use(VueI18n)export default ({ app, store }) => { let data = {} let Locale = store.state.locales for (let i = 0; i < Locale.length; i++) { data[Locale[i]] = require(`~/locales/${Locale[i]}.json`) } // Set i18n instance on app // This way we can use it in middleware and pages asyncData/fetch app.i18n = new VueI18n({ locale: store.state.locale, fallbackLocale: 'en', messages: data }) // 自定义页面跳转方法 app.i18n.path = (link) => { return `/${app.i18n.locale}/${link}` }}~/middleware/i18n.js123456789101112131415161718192021export default function ({ isHMR, app, store, route, params, error, redirect }) { const defaultLocale = app.i18n.fallbackLocale // If middleware is called from hot module replacement, ignore it if (isHMR) return // Get locale from params const locale = params.lang || defaultLocale if (store.state.locales.indexOf(locale) === -1) { return error({ message: 'This page could not be found.', statusCode: 404 }) } // Set locale store.commit('SET_LANG', store.state.locale) app.i18n.locale = store.state.locale // If route is /<defaultLocale>/... -> redirect to /... if (locale === defaultLocale && route.fullPath.indexOf('/' + defaultLocale) === 0) { const toReplace = '^/' + defaultLocale + (route.fullPath.indexOf('/' + defaultLocale + '/') === 0 ? '/' : '') const re = new RegExp(toReplace) return redirect( route.fullPath.replace(re, '/') ) }}~/locales/index.js创建本地语言库123export default () => { return ['en', 'fr', 'cn']}~/locales/fr.json更加不同页面添加不用的语言12345678910111213141516{ "links": { "home": "Accueil", "about": "à propos", "english": "Version Anglaise", "french": "Version Française" }, "home": { "title": "Bienvenue", "introduction": "Ceci est un texte d'introduction en Français." }, "about": { "title": "à propos", "introduction": "Cette page est faite pour vous donner plus d'informations." }}~/store/index.js123456789101112131415import Locale from '~/locales'export const state = () => ({ locales: Locale(), locale: Locale()[0]})export const mutations = { SET_LANG(state, locale) { if (state.locales.indexOf(locale) !== -1) { console.log(locale) state.locale = locale } }}方法获取1$t('links.english')设置1this.$i18n.locale = name]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Nuxt</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue SSR Nuxt axios封装]]></title>
<url>%2F2018%2F08%2F25%2FNuxtAxios%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why安装1$ npm install axios --save使用~/nuxt.config.js引入插件,启动中间件1plugins: ['~/plugins/api.js'],~/plugins/api.js12345import Vue from 'vue'import API from '~/api/index.js'Vue.prototype.$API = APIVue.use(API)~/api/index.js123456789101112131415161718/** * api接口统一管理 * import API from 'API' * Vue.prototype.$API = API * Vue.use(API) * * this.$API.Login() */import {get, post} from './http'export default { POST (link) { return post(link) }, GET (link) { return get(link) }}~/api/http.js创建本地语言库1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556import axios from 'axios' // 引入axiosimport qs from 'qs' // 引入qs模块,用来序列化post类型的数据,后面会提到import { baseUrl} from './env.js'const TOKEN = '7bf2b13020e1ed2278db4bba3f5e7a53102cbc37'// vuex// import * as Tool from 'UTIL/vuex'// axios 配置axios.defaults.timeout = 5000 // 设置请求超时axios.defaults.baseURL = baseUrl // 默认请求地址axios.defaults.headers.common['Authorization'] = `token ${TOKEN}` // Authorizationaxios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded' // 请求头的设置// 请求axios.interceptors.request.use((config) => { if (config.method === 'post') { config.data = qs.stringify(config.data) } let URL = config.url.split(config.baseURL) // Tool.open(URL[1], config.showLoading) return config}, (error) => { // Tool.toast('错误的传参', 'fail') return Promise.reject(error)})// 返回axios.interceptors.response.use((res) => { // console.log(res) // 拦截器配置 // if (res.data.success) { // Tool.toast(res.data.msg) // Tool.close() // return Promise.reject(res) // } // Tool.close() // return res // 全部数据 return res.data // data数据}, (error) => { // 请求失败 // Tool.toast('网络异常', 'fail') // Tool.close() return Promise.reject(error)})export const get = (url, showLoading) => axios.get(url, { showLoading: showLoading})export const post = (url, params, showLoading) => axios.post(url, params, { showLoading: showLoading})~/api/env.js更加不同页面添加不用的语言1234567891011121314151617181920212223242526/** * 配置编译环境和线上环境之间的切换 * * baseUrl: 域名地址 * routerMode: 路由模式 * imgBaseUrl: 图片所在域名地址 * */let baseUrllet routerModeconst imgBaseUrl = 'https://fuss10.elemecdn.com'if (process.env.NODE_ENV === 'development') { baseUrl = 'https://api.github.com/' routerMode = 'hash'} else { baseUrl = 'https://api.github.com/' routerMode = 'hash'}export { baseUrl, routerMode, imgBaseUrl}~/store/index.js123456789101112131415import Locale from '~/locales'export const state = () => ({ locales: Locale(), locale: Locale()[0]})export const mutations = { SET_LANG(state, locale) { if (state.locales.indexOf(locale) !== -1) { console.log(locale) state.locale = locale } }}方法POST123this.$API.POST('').then((res) => { console.log(res)})GET123this.$API.GET('').then((res) => { console.log(res)})]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Nuxt</tag>
</tags>
</entry>
<entry>
<title><![CDATA[如何将 Nuxt 应用部署至 Heroku?]]></title>
<url>%2F2018%2F08%2F25%2FNuxtDeploy%2F</url>
<content type="text"><![CDATA[服务器端渲染(Server-Side Rendering):Vue.js是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出Vue组件,进行生成DOM和操作DOM。然而,也可以将同一个组件渲染为服务器端的HTML字符串,将它们直接发送到浏览器,最后将静态标记”混合”为客户端上完全交互的应用程序。服务器渲染的Vue.js应用程序也可以被认为是”同构”或”通用”,因为应用程序的大部分代码都可以在服务器和客户端上运行。注册注意:注册不支持QQ邮箱安装set-upWindowsmacOS1$ brew install heroku/brew/herokuUbuntu 16+1$ sudo snap install heroku --classic登录1234$ heroku login Enter your Heroku credentials. Email: <[email protected]> Password: <Password>查看版本12$ node -v$ npm -v配置package.json1234567"scripts": { "heroku-postbuild": "npm run build"},"engines": { "node": "8.9.0", "npm": "5.5.1"},部署应用程序创建APP1234$ heroku createCreating sharp-rain-871... done, stack is cedar-14http://sharp-rain-871.herokuapp.com/ | https://git.heroku.com/sharp-rain-871.gitGit remote heroku added注意:默认会自动创建sharp-rain-开头的名称,也可以指定名称1234$ heroku create <name>Creating <name>... done, stack is cedar-14http://<name>.herokuapp.com/ | https://git.heroku.com/<name>.gitGit remote heroku added设置1$ heroku config:set NPM_CONFIG_PRODUCTION=false主机IP12$ heroku config:set HOST=0.0.0.0$ heroku config:set NODE_ENV=production部署代码1$ git push heroku master打开部署页面1$ heroku open]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Nuxt</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue SSR Nuxt]]></title>
<url>%2F2018%2F08%2F25%2FNuxt%2F</url>
<content type="text"><![CDATA[服务器端渲染(Server-Side Rendering):Vue.js是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出Vue组件,进行生成DOM和操作DOM。然而,也可以将同一个组件渲染为服务器端的HTML字符串,将它们直接发送到浏览器,最后将静态标记”混合”为客户端上完全交互的应用程序。服务器渲染的Vue.js应用程序也可以被认为是”同构”或”通用”,因为应用程序的大部分代码都可以在服务器和客户端上运行。传统打包Vue项目打包后,组件都是JS在html文件返回后再渲染到<div id=app></div>里的。这就合理的解释了SEO缺陷的原因。安装流程新手模板初始化项目1$ vue init nuxt-community/starter-template <project-name>注:如果vue-cli没有安装, 需先通过npm install -g vue-cli来安装。安装依赖包12$ cd <project-name>$ npm install启动项目1$ npm run dev注意:应用现在运行在 http://localhost:3000Nuxt.js 会监听 pages 目录中的文件变更并自动重启, 当添加新页面时没有必要手工重启应用。运行端口占用,如何切换端口模板结构1234567891011121314151617181920212223242526272829303132333435.├── .nuxt/ # 自动生成的配置文件(无需配置) ├── components/ # css 文件夹 ├── views/ # img 文件夹 ├── App.js # css 文件夹 ├── client.js # css 文件夹 ├── empty.js # css 文件夹 ├── index.js # css 文件夹 ├── loading.html # css 文件夹 ├── middleware.js # css 文件夹 ├── router.js # css 文件夹 ├── server.js # css 文件夹 └── utils.js # css 文件夹├── api/ # 资源目录 assets 用于组织未编译的静态资源如 LESS、SASS ├── index.js # API接口配置项 ├── env.js # 开发配置项 └── http.js # Axios├── assets/ # 资源目录 assets 用于组织未编译的静态资源如 LESS、SASS ├── css/ # css 文件夹 ├── img/ # img 文件夹 ├── less/ # less 文件夹 └── scss/ # scss 文件夹├── components/ # 组件目录:Vue.js 组件。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有 asyncData 方法的特性。├── layouts/ # 布局目录:应用的布局组件├── middleware/ # 中间件:存放应用的中间件├── pages/ # 页面目录:用于组织应用的路由及视图├── plugins/ # 插件目录:用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件├── static/ # 静态文件目录:用于存放应用的静态文件├── store/ # Vuex状态树├── .eslintignore # ESLint 检查中需忽略的文件(夹)├── .eslintrc # ESLint 配置├── .gitignore # 需被 Git 忽略的文件(夹)├── nuxt.config.js # 应用的个性化配置,以便覆盖默认配置├── README.md # README 简介└── package.json # 应用的依赖关系、对外暴露的脚本接口工作原理使用方法绝对路径绝对路径路径~/~api/api~assets/assets~components/components~layouts/layouts~middleware/middleware~pages/pages~plugins/plugins~static/static~store/store路由Nuxt.js 根据 pages 目录结构去生成 vue-router 配置,也就是说 pages 目录的结构直接影响路由结构123456789101112131415161718192021222324|-- pages |-- posts |-- index.vue |-- welcome.vue |-- about.vue |-- index.vue=> 生成routes: [ { path: '/posts', component: '~pages/posts/index.vue' }, { path: '/posts/welcome', component: '~pages/posts/welcome.vue' }, { path: '/about', component: '~pages/about.vue' }, { path: '/', component: '~pages/index.vue' }]动态路由123456789101112131415161718192021222324252627282930313233pages/--| _slug/-----| comments.vue-----| index.vue--| users/-----| _id.vue--| index.vue=> 生成router: { routes: [ { name: 'index', path: '/', component: 'pages/index.vue' }, { name: 'users-id', path: '/users/:id?', component: 'pages/users/_id.vue' }, { name: 'slug', path: '/:slug', component: 'pages/_slug/index.vue' }, { name: 'slug-comments', path: '/:slug/comments', component: 'pages/_slug/comments.vue' } ]}错误页面默认访问:layouts/error.vueerror => ~/layouts/error.vue123456789101112<template> <div class="container"> <h1 v-if="error.statusCode === 404">页面不存在</h1> <h1 v-else>应用发生错误异常</h1> <nuxt-link to="/">首 页</nuxt-link> </div></template>export default { props: ['error'], layout: 'blog' // 你可以为错误页面指定自定义的布局}statusCodeName404页面不存在引入静态资源以flexible为例12345678910script: [ { type: 'text/javascript', src: '/flexible.js' }, { type: 'text/javascript', innerHTML: 'console.log(1)' }]页面方法asyncData 异步获取数据Nuxt.js 扩展了 Vue.js,增加了一个叫 asyncData 的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。12345678export default { data () { return { project: 'default' } }, asyncData (context) { return { project: 'nuxt' } }}返回 Promise12345678export default { asyncData ({ params }) { return axios.get(`https://my-api/posts/${params.id}`) .then((res) => { return { title: res.data.title } }) }}使用 async或await123456export default { async asyncData ({ params }) { let { data } = await axios.get(`https://my-api/posts/${params.id}`) return { title: data.title } }}asyncData方法:会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData方法来获取数据并返回给当前组件。属性字段类型可用描述isClientBoolean客户端 & 服务端是否来自客户端渲染isServerBoolean客户端 & 服务端是否来自服务端渲染isDevBoolean客户端 & 服务端是否是开发(dev) 模式,在生产环境的数据缓存中用到routevue-router 路由客户端 & 服务端vue-router 路由实例。storevuex 数据流客户端 & 服务端Vuex.Store 实例。只有vuex 数据流存在相关配置时可用。envObject客户端 & 服务端nuxt.config.js 中配置的环境变量, 见 环境变量 apiparamsObject客户端 & 服务端route.params 的别名queryObject客户端 & 服务端route.query 的别名reqhttp.Request服务端Node.js API 的 Request 对象。如果 nuxt 以中间件形式使用的话,这个对象就根据你所使用的框架而定。nuxt generate 不可用。reshttp.Response服务端Node.js API 的 Response 对象。如果 nuxt 以中间件形式使用的话,这个对象就根据你所使用的框架而定。nuxt generate 不可用。redirectFunction客户端 & 服务端用这个方法重定向用户请求到另一个路由。状态码在服务端被使用,默认 302。redirect([status,] path [, query])errorFunction客户端 & 服务端用这个方法展示错误页:error(params)。params 参数应该包含 statusCode 和 message 字段。错误处理errorNuxt.js 在上下文对象context中提供了一个 error(params) 方法,你可以通过调用该方法来显示错误信息页面。params.statusCode 可用于指定服务端返回的请求状态码。123456789101112export default { asyncData ({ params, error }) { return axios.get(`https://my-api/posts/${params.id}`) .then((res) => { return { title: res.data.title } }) .catch((e) => { error({ statusCode: 404, message: 'Post not found' }) // 执行后直接跳转error页面 }) }}callback1234567891011export default { asyncData ({ params }, callback) { axios.get(`https://my-api/posts/${params.id}`) .then((res) => { callback(null, { title: res.data.title }) }) .catch((e) => { callback({ statusCode: 404, message: 'Post not found' }) }) }}fetchfetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。123456fetch ({ store, params }) { return axios.get('http://my-api/stars') .then((res) => { store.commit('setStars', res.data) })}你也可以使用 async 或 await 的模式简化代码如下1234async fetch ({ store, params }) { let { data } = await axios.get('http://my-api/stars') store.commit('setStars', data)}headNuxt.js 使用了 vue-meta 更新应用的 头部标签(Head) 和 html 属性。12345678910111213141516171819head () { return { title: 'title', // 标题 meta: [ { hid: 'Keywords', // 唯一标识 name: 'Keywords1', // 名称 content: 'Keywords2' // 内容 } ], link: [ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } ] }},注意:为了避免子组件中的meta标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用 hid 键为meta标签配一个唯一的标识编号。layout根目录下的所有文件都属于个性化布局文件,可以在页面组件中利用 layout 属性来引用。1234567export default { layout: 'blog', // 或 layout (context) { return 'blog' }}middleware在应用中的特定页面设置中间件,在服务器中返回。1234567export default { middleware: 'stats'}export default function (context) { context.userAgent = context.isServer ? context.req.headers['user-agent'] : navigator.userAgent}scrollToTop1234567<template> <h1>子页面组件</h1></template>export default { scrollToTop: true}transition12345678export default { // 可以是字符 transition: '' // 或对象 transition: {} // 或函数 transition (to, from) {}}validateNuxt.js 可以让你在动态路由对应的页面组件中配置一个校验方法用于校验动态路由参数的有效性。1234validate({ params, query }) { return true // 如果参数有效 return false // 参数无效,Nuxt.js 停止渲染当前页面并显示错误页面}配置文件目录下的 nuxt.config.js 是我们唯一的配置入口,默认的给力我们三个配置 ·head·css·loading· 分别是头部设置,全局css,loading进度条属性名称build模块管理cache组件缓存css全局样式dev开发配置env环境配置generate静态配置head全局头部配置loading加载配置plugins插件配置rootDir配置router路由配置srcDir配置transition动画配置buildNuxt.js 允许你在自动生成的 vendor.bundle.j 文件中添加一些模块,以减少应用 bundle的体积。如果你的应用依赖第三方模块,这个配置项是十分实用的。analyzeNuxt.js 使用 webpack-bundle-analyzer 分析并可视化构建后的打包文件,你可以基于分析结果来决定如何优化它。1234567891011默认值: falsemodule.exports = { build: { analyze: true // or analyze: { analyzerMode: 'static' } }}提示: 可通过 nuxt build –analyze 或 nuxt build -a 命令来启用该分析器进行编译构建,分析结果可在 http://localhost:8888 上查看。babel为 JS 和 Vue 文件设定自定义的 babel 配置。12345默认值:{ presets: ['vue-app']}1234567module.exports = { build: { babel: { presets: ['es2015', 'stage-0'] } }}extend为客户端和服务端的构建配置进行手工的扩展处理。该扩展方法会被调用两次,一次在服务端打包构建的时候,另外一次是在客户端打包构建的时候。该方法的参数如下:Webpack 配置对象构建环境对象,包括这些属性(全部为布尔类型): isDev, isClient, isServer12345678910module.exports = { build: { extend (config, { isClient }) { // 为 客户端打包 进行扩展配置 if (isClient) { config.devtool = 'eval-source-map' } } }}如果你想了解更多关于webpack的配置,可以移步 Nuxt.js 源码的 webpack 目录。filenames 自定义打包文件名12345678910默认值:module.exports = { build: { filenames: { vendor: 'vendor.[hash].js', app: 'app.[chunkhash].js' } }}loaders 加载器自定义 webpack 加载器1234567891011121314151617181920默认值:[ { test: /\.(png|jpe?g|gif|svg)$/, loader: 'url-loader', query: { limit: 1000, // 1KO name: 'img/[name].[hash:7].[ext]' } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', query: { limit: 1000, // 1 KO name: 'fonts/[name].[hash:7].[ext]' } }]1234567891011121314module.exports = { build: { loaders: [ { test: /\.(png|jpe?g|gif|svg)$/, loader: 'url-loader', query: { limit: 10000, // 10KO name: 'img/[name].[hash].[ext]' } } ] }}当 nuxt.config.js 里有自定义的 loaders 配置时,将会覆盖默认的配置。plugins 插件1234567891011const webpack = require('webpack')module.exports = { build: { plugins: [ new webpack.DefinePlugin({ 'process.VERSION': require('./package.json').version }) ] }}postcss1234567默认值:[ require('autoprefixer')({ browsers: ['last 3 versions'] })]123456789101112module.exports = { build: { postcss: [ require('postcss-nested')(), require('postcss-responsive-type')(), require('postcss-hexrgba')(), require('autoprefixer')({ browsers: ['last 3 versions'] }) ] }}publicPath CDN地址Nuxt.js 允许你将待发布的文件直接上传至 CDN 以获得最佳访问性能,只需设置 publicPath 为你的 CDN 地址即可。1234567默认值: '/_nuxt/'module.exports = { build: { publicPath: 'https://cdn.nuxtjs.org' }}通过以上配置,当运行 nuxt build 时,再将.nuxt/dist/目录的内容上传到您的CDN,然后瞧!vendor 第三方模块Nuxt.js 允许你在自动生成的 vendor.bundle.js 文件中添加一些模块,以减少应用 bundle 的体积。这里说的是一些你所依赖的第三方模块 (比如 axios)12345module.exports = { build: { vendor: ['axios'] }}12345678module.exports = { build: { vendor: [ 'axios', '~plugins/my-lib.js' ] }}cache 组件缓存该配置项让你开启组件缓存策略以提升渲染性能。如 cache 设定的值为 true,那么相当于应用了下面的默认配置:12345678module.exports = { cache: true // or cache: { max: 1000, maxAge: 900000 }}属性名是否可选?类型默认值描述max是整型1000缓存组件的最大数目,当第 1001 个组件被添加至缓存中时, 第一个被缓存的组件会从缓存中移除。maxAge是整型900000缓存时间,单位毫秒, 默认是 15 分钟。css该配置项用于定义应用的全局(所有页面均需引用的)样式文件、模块或第三方库。src: String (文件路径)lang: String (所需的预处理器)123456789101112module.exports = { css: [ // 加载一个 node.js 模块 'hover.css/css/hover-min.css', // 同样加载一个 node.js 模块,不过我们定义所需的预处理器 { src: 'bulma', lang: 'sass' }, // 项目中的 CSS 文件 '~assets/css/main.css', // 项目中的 Sass 文件 { src: '~assets/css/main.scss', lang: 'scss' } // 指定 scss 而非 sass ]}devdev 属性的值会被 nuxt 命令 覆盖当使用 nuxt 命令时,dev 会被强制设置成 true当使用 nuxt build, nuxt start 或 nuxt generate 命令时,dev 会被强制设置成 false123456789101112131415161718192021222324252627module.exports = { dev: (process.env.NODE_ENV !== 'production')}=> server.jsconst {Nuxt, Builder} = require('nuxt')const app = require('express')()const port = process.env.PORT || 3000// 传入配置初始化 Nuxt.js 实例let config = require('./nuxt.config.js')const nuxt = new Nuxt(config)app.use(nuxt.render)// 在开发模式下进行编译if (config.dev) { new Builder(nuxt).build() .catch((error) => { console.error(error) process.exit(1) })}// 监听指定端口app.listen(port, '0.0.0.0')console.log('服务器运行于 localhost:' + port)envNuxt.js 让你可以配置在客户端和服务端共享的环境变量。12345module.exports = { env: { baseUrl: process.env.BASE_URL || 'http://localhost:3000' }}我们可以通过以下两种方式来使用 baseUrl 变量:通过 process.env.baseUrl通过 context.baseUrl,请参考 context api举个例子, 我们可以利用它来配置 axios 的自定义实例。1234567plugins/axios.jsimport axios from 'axios'export default axios.create({ baseURL: process.env.baseUrl})generate配置 Nuxt.js 应用生成静态站点的具体方式。123456789101112131415161718```该配置项用于定义每个动态路由的参数,Nuxt.js 依据这些路由配置生成对应目录结构的静态文件。关于 generate 配置项的详细文档## head借助 head 属性,Nuxt.js 让你可以在 nuxt.config.js 中配置应用的 meta 信息。``` javascriptmodule.exports = { head: { titleTemplate: '%s - Nuxt.js', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: 'Meta description' } ] }}关于 head 配置项的详细文档loading在页面切换的时候,Nuxt.js 使用内置的加载组件显示加载进度条。你可以定制它的样式,禁用或者创建自己的加载组件。禁用加载进度条123module.exports = { loading: false}个性化加载进度条键类型默认值描述colorString‘black’进度条的颜色failedColorString‘red’页面加载失败时的颜色 (当 data 或 fetch 方法返回错误时)。heightString‘2px’进度条的高度 (在进度条元素的 style 属性上体现)。durationNumber5000进度条的最大显示时长,单位毫秒。Nuxt.js 假设页面在该时长内加载完毕。123456module.exports = { loading: { color: 'blue', height: '5px' }}自定义加载组件方法是否必须描述start()是路由更新(即浏览器地址变化)时调用, 请在该方法内显示组件。finish()是路由更新完毕(即asyncData方法调用完成且页面加载完)时调用,请在该方法内隐藏组件。fail()否路由更新失败时调用(如asyncData方法返回异常)。increase(num)否页面加载过程中调用, num 是小于 100 的整数。123module.exports = { loading: '~components/loading.vue'}123456789101112131415161718192021222324252627282930313233343536components/loading.vue<template lang="html"> <div class="loading-page" v-if="loading"> <p>Loading...</p> </div></template>export default { data: () => ({ loading: false }), methods: { start () { this.loading = true }, finish () { this.loading = false } }}<style scoped>.loading-page { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); text-align: center; padding-top: 200px; font-size: 30px; font-family: sans-serif;}</style>plugins该配置项用于配置那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。1234plugins: [ {src: '~plugins/extra.js', ssr: false}, {src: '~plugins/share.js', ssr: true}],src: String (文件的路径)ssr: Boolean (默认为 true) 如果值为 false,该文件只会在客户端被打包引入。有些插件可能只是在浏览器里使用,所以你可以用 ssr: false 变量来配置插件只从客户端还是服务端运行。常见的问题:window对象没有,无法使用。请将插件放入SSR:false的页面。rootDir1该配置项用于配置 Nuxt.js 应用的根目录。关于 rootDir 配置项的详细文档routerbase应用的根URL。举个例子,如果整个单页面应用的所有资源可以通过 /app/ 来访问,那么 base 配置项的值需要设置为 ‘/app/‘。1234567默认值: '/'module.exports = { router: { base: '/app/' }}base 被设置后,Nuxt.js 会自动将它添加至页面中:。该配置项的值会被直接传给 vue-router 的构造器。mode默认值:’history’,配置路由的模式,鉴于服务端渲染的特性,不建议修改该配置。该配置项的值会被直接传给 vue-router 的构造器。12345module.exports = { router: { mode: 'hash' }}linkActiveClass默认值: ‘nuxt-link-active’,全局配置组件默认的激活类名。该配置项的值会被直接传给 vue-router 的构造器。12345module.exports = { router: { linkActiveClass: 'active-link' }}scrollBehaviorscrollBehavior 配置项用于个性化配置跳转至目标页面后的页面滚动位置。每次页面渲染后都会调用 scrollBehavior 配置的方法。该配置项的值会被直接传给 vue-router 的构造器。scrollBehavior 的默认配置为:12345678910111213141516171819202122const scrollBehavior = (to, from, savedPosition) => { // savedPosition 只有在 popstate 导航(如按浏览器的返回按钮)时可以获取。 if (savedPosition) { return savedPosition } else { let position = {} // 目标页面子组件少于两个 if (to.matched.length < 2) { // 滚动至页面顶部 position = { x: 0, y: 0 } } else if (to.matched.some((r) => r.components.default.options.scrollToTop)) { // 如果目标页面子组件中存在配置了scrollToTop为true position = { x: 0, y: 0 } } // 如果目标页面的url有锚点, 则滚动至锚点所在的位置 if (to.hash) { position = { selector: to.hash } } return position }}举个例子,我们可以配置所有页面渲染后滚动至顶部:1234567module.exports = { router: { scrollBehavior: function (to, from, savedPosition) { return { x: 0, y: 0 } } }}middleware为应用的每个页面设置默认的中间件。123456789101112module.exports = { router: { // 在每页渲染前运行 middleware/user-agent.js 中间件的逻辑 middleware: 'user-agent' }}middleware/user-agent.jsexport default function (context) { // 给上下文对象增加 userAgent 属性(增加的属性可在 `asyncData` 和 `fetch` 方法中获取) context.userAgent = context.isServer ? context.req.headers['user-agent'] : navigator.userAgent}了解更多关于中间件的信息,请参考 中间件指引文档。extendRoutes你可以通过 extendRoutes 配置项来扩展 Nuxt.js 生成的路由配置。12345678910111213const resolve = require('path').resolvemodule.exports = { router: { extendRoutes (routes) { routes.push({ name: 'custom', path: '*', component: resolve(__dirname, 'pages/404.vue') }) } }}srcDir1该配置项用于配置应用的源码目录路径。关于 srcDir 配置项的详细文档transition该配置项用于个性化配置应用过渡效果属性的默认值。12345默认值:{ name: 'page', mode: 'out-in'}1234567891011module.exports = { transition: 'page' // or transition: { name: 'page', mode: 'out-in', beforeEnter (el) { console.log('Before enter...'); } }}属性字段类型默认值描述nameString“page”所有路由过渡都会用到的过渡名称。modeString“out-in”所有路由都用到的过渡模式,见 Vue.js transition 使用文档。cssBooleantrue是否给页面组件根元素添加 CSS 过渡类名。如果值为 false,路由过渡时将触发页面组件事件注册的 Javascript 钩子方法。typeStringn/a指定过滤动效事件的类型,用于判断过渡结束的时间点。值可以是 “transition” 或 “animation”。 默认情况下, Nuxt.js 会自动侦测动效事件的类型。enterClassStringn/a目标路由动效开始时的类名。 详情请参考 Vue.js transition 使用文档 。enterToClassStringn/a目标路由动效结束时的类名。 详情请参考 Vue.js transition 使用文档 。enterActiveClassStringn/a目标路由过渡过程中的类名。详情请参考 Vue.js transition 使用文档 。leaveClassStringn/a当前路由动效开始时的类名。 详情请参考 Vue.js transition 使用文档 。leaveToClassStringn/a当前路由动效结束时的类名。 详情请参考 Vue.js transition 使用文档 。leaveActiveClassStringn/a当前路由动效过程中的类名。详情请参考 Vue.js transition 使用文档 。安装插件SAAS1npm install --save-dev node-sass sass-loaderLESS1npm install --save-dev less less-loaderAxios API123456789101112131415```## CROSS_ENV环境变量### nuxt2.0根据不同的环境变量切换接口网址名称``` javascriptif (process.env.PATH_TYPE === 'development') { baseUrl = `http://dev.yktour.com.cn:${port}/development`} else if (process.env.PATH_TYPE === 'release') { baseUrl = `http://test.yktour.com.cn/release`} else if (process.env.PATH_TYPE === 'production') { baseUrl = `http://yktour.com.cn/api`}代理服务,代理不同的变量到不同的接口1234567891011121314151617181920212223242526modules: [ '@nuxtjs/proxy'],proxy: [ [ '/development',{ target: 'https://testapp.yktour.com.cn/ykly-app', changeOrigin: true, pathRewrite: { '^/development' : '' } } ], [ '/release',{ target: 'https://testapp.yktour.com.cn/ykly-app', changeOrigin: true, pathRewrite: { '^/release' : '' } } ], [ '/api',{ target: 'https://testapp.yktour.com.cn/ykly-app', changeOrigin: true, pathRewrite: { '^/api' : '' } } ]],通过设置自定义PATH_TYPE环境变量123env: { PATH_TYPE: process.env.PATH_TYPE || process.env.NODE_ENV},运行方式123"devTest": "cross-env PATH_TYPE=release nuxt","buildTest": "cross-env PATH_TYPE=release nuxt build","startTest": "cross-env PATH_TYPE=release nuxt start",nuxt1.0无法获取process.env.NODE_ENV的值常见问题生命周期Vux初始化时间不会变革案例Nuxt 案例V2ex clone built with Nuxt.js文章发布系统A Nuxtjs Website using Storyblokvuejs, nuxtjs 搭建 新闻聚合网站]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Nuxt</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue SSR]]></title>
<url>%2F2018%2F08%2F25%2FVueSRR%2F</url>
<content type="text"><![CDATA[服务器端渲染(Server-Side Rendering):Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将静态标记”混合”为客户端上完全交互的应用程序。服务器渲染的 Vue.js 应用程序也可以被认为是”同构”或”通用”,因为应用程序的大部分代码都可以在服务器和客户端上运行。工作原理app.jsapp.js是我们的通用entry,它的作用就是构建一个Vue的实例以供服务端和客户端使用,注意一下,在纯客户端的程序中我们的app.js将会挂载实例到dom中,而在ssr中这一部分的功能放到了Client entry中去做了。Client entry.js客户端的入口:功能很简单,就是挂载我们的Vue实例到指定的dom元素上Server entry.js服务端的入口:一个使用export导出的函数。主要负责调用组件内定义的获取数据的方法,获取到SSR渲染所需数据,并存储到上下文环境中。这个函数会在每一次的渲染中重复的调用。双刃剑优点更利于SEO不同爬虫工作原理类似,只会爬取源码,不会执行网站的任何脚本(Google除外,据说Googlebot可以运行javaScript)。使用了Vue或者其它MVVM框架之后,页面大多数DOM元素都是在客户端根据js动态生成,可供爬虫抓取分析的内容大大减少。另外,浏览器爬虫不会等待我们的数据完成之后再去抓取我们的页面数据。服务端渲染返回给客户端的是已经获取了异步数据并执行JavaScript脚本的最终HTML,网络爬中就可以抓取到完整页面的信息。更利于首屏渲染首屏的渲染是node发送过来的html字符串,并不依赖于js文件了,这就会使用户更快的看到页面的内容。尤其是针对大型单页应用,打包后文件体积比较大,普通客户端渲染加载所有所需文件时间较长,首页就会有一个很长的白屏等待时间。缺点服务端压力较大本来是通过客户端完成渲染,现在统一到服务端node服务去做。尤其是高并发访问的情况,会大量占用服务端CPU资源;开发条件受限在服务端渲染中,created和beforeCreate之外的生命周期钩子不可用,因此项目引用的第三方的库也不可用其它生命周期钩子,这对引用库的选择产生了很大的限制;学习成本相对较高webpack要熟悉Vue要熟悉掌握node、Express相关技术,相对于客户端渲染,项目构建、部署过程更加复杂。]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[前端网站SEO执行策略]]></title>
<url>%2F2018%2F03%2F27%2FSEO%2F</url>
<content type="text"><![CDATA[SEO( Search Engine Optimization )搜索引擎优化在搜索引擎时代对于网站来讲意义重大。一个网站,不管是小站还是大站,都离不开搜索引擎的流量导入,所以,做好 SEO 一直都是网站站长\开发者一门重要的功课。爬虫单页面应用优化采坑前端渲染与 SEO 优化踩坑小记fragment1<meta name="fragment" content="!">注:只有 Google 的爬虫认可,其他搜索引擎全部没用!PhantomJSPhantomJS 是一个基于 WebKit 的服务器端 JavaScript API1<meta name="fragment" content="!">注:只有 Google 的爬虫认可,其他搜索引擎全部没用!prerender]]></content>
<categories>
<category>SEO</category>
</categories>
<tags>
<tag>SEO</tag>
</tags>
</entry>
<entry>
<title><![CDATA[移动端调试]]></title>
<url>%2F2018%2F03%2F27%2FMobileDBUG%2F</url>
<content type="text"><![CDATA[随着移动设备的普及以及微信庞大的用户量,移动端的需求也随之爆发式增长,平时我们使用 Chrome 进行手机模拟页面开发,但模拟终究是模拟,不可避免的还是需要真机调试,下面就来讲讲几种调试方案,希望能对你有所帮助。iPhoneiPhone + Safari使用 Lightning 数据线将 iPhone 与 Mac 相连iPhone(iOS 6 +)iPhone 开启 Web 检查器(设置 -> Safari -> 高级 -> 开启 Web 检查器)iPhone 使用 Safari 浏览器打开要调试的页面SafariMac 打开 Safari 浏览器调试(菜单栏 —> 开发 -> iPhone 设备名 -> 选择调试页面)如果你的菜单栏没有“开发”选项,可以到左上角 Safari -> 偏好设置 -> 高级 -> 在菜单栏中显示“开发”菜单。AndroidAndroid + Chrome使用 USB 数据线将手机与电脑相连Android (4.0 +)手机进入开发者模式,勾选 USB 调试,并允许调试Chrome电脑打开 Chrome 浏览器,在地址栏输入:chrome://inspect/#devices 并勾选 Discover USB devices 选项Charlesiphone网络设置(设置 -> 网络 -> 配置代理 -> 手动代理)网址:笔记本网址端口:8888]]></content>
<categories>
<category>Chrome</category>
</categories>
<tags>
<tag>Chrome</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JavaScript 数组方法汇总]]></title>
<url>%2F2018%2F03%2F25%2FArrayMax%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why创建数组隐式创建1var arr=['Audi', 'BMW', 'Volvo']直接实例化1var arr=new Array('Audi', 'BMW', 'Volvo')快速构建数组直接构建法:1let arr = ['mock', 'mock', 'mock']循环法: for循环1234let arr = []for(var i = 0;i < 3;i++){ arr.push('mock')}快速填充数组1let newArr = new Array(3).fill('mock');构建顺序(倒序数组)快速填充数组1let newArr = new Array(10).fill(1).map((item, index) => index + 1)1let funss = (m, n) => Array.apply(null, new Array(m)).map(() => n++)数组最大值es6拓展运算符…12var arr = [-1, 1, 101, -52, 10, 1001, 1001]Math.max(...arr)es5 apply(与方法1原理相同)12var arr = [-1, 1, 101, -52, 10, 1001, 1001]Math.max.apply(null,arr)for循环12345var arr = [-1, 1, 101, -52, 10, 1001, 1001]let max = arr[0]for (let i = 0; i < arr.length - 1; i++) { max = arr[i] < arr[i+1] ? arr[i+1] : arr[i]}数组sort()12345var arr = [-1, 1, 101, -52, 10, 1001, 1001]arr.sort((num1, num2) => { return num1 - num2 < 0})arr[0]数组reducearray.reduce(function(total, currentValue, currentIndex, arr), initialValue)1234var arr = [-1, 1, 101, -52, 10, 1001, 1001]arr.reduce((num1, num2) => { return num1 > num2 ? num1 : num2})数组去重ES6的set12345var arr = [-1, 1, 101, -52, 10, 1001, 1001]console.log(Array.from(new Set(arr)))var arr = [-1, 1, 101, -52, 10, 1001, 1001]console.log([...new Set(arr)])过滤push1234567891011121314151617181920212223242526272829303132333435363738```Array.prototype.distinct = function () { var arr = this, result = [], len = arr.length for (i = 0; i < len; i++) { for (j = i + 1; j < len; j++) { if (arr[i] === arr[j]) { j = ++i } } result.push(arr[i]) } return result}var arra = [1, 2, 3, 4, 4, 1, 1, 2, 1, 1, 1]arra.distinct()// [3, 4, 2, 1]## 过滤splice优点:简单易懂缺点:占用内存高,速度慢``` javascriptArray.prototype.distinct = function () { var arr = this, len = arr.length for (i = 0; i < len; i++) { for (j = i + 1; j < len; j++) { if (arr[i] === arr[j]) { arr.splice(j, 1) len-- j-- } } } return arr}var arra = [1, 2, 3, 4, 4, 1, 1, 2, 1, 1, 1]arra.distinct()// [1, 2, 3, 4]利用对象过滤12345678910111213Array.prototype.distinct = function () { var arr = this, obj = {}, result = [], len = arr.length for (i = 0; i < len; i++) { if (!obj[arr[i]]) { obj[arr[i]] = true; result.push(arr[i]) } } return result}var arra = [1, 2, 3, 4, 4, 1, 1, 2, 1, 1, 1]arra.distinct()// [1, 2, 3, 4]数组递归去重运用递归的思想,先排序,然后从最后开始比较,遇到相同,则删除123456789101112131415161718Array.prototype.distinct = function () { var arr = this, len = arr.length arr.sort(function(a, b) { return a - b }) function loop(index) { if (index >= 1) { if (arr[index] === arr[index - 1]) { arr.splice(index, 1) } loop(index - 1) } } loop(len - 1) return arr}var arra = [1, 2, 3, 4, 4, 1, 1, 2, 1, 1, 1]arra.distinct()利用indexOf以及forEach1234567891011Array.prototype.distinct = function () { var arr = this, result = [], len = arr.length arr.forEach(function (v, i, arr) { if (arr.indexOf(v, i+1) === -1) { result.push(v) } }) return result}var arra = [1, 2, 3, 4, 4, 1, 1, 2, 1, 1, 1]arra.distinct()数组合并去重concat()方法123456789var a = [1, 2, 3];var b = [4, 5, 2];function concatArray(a, b) { a = a.concat(b) a = a.distinct() return a}concatArray(a, b)// [1, 3, 4, 5, 2]apply()方法123456789var a = [1, 2, 3];var b = [4, 5, 2];function concatArray(a, b) { Array.prototype.push.apply(a, b) a = a.distinct() return a}concatArray(a, b)// [1, 3, 4, 5, 2]]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>Array</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JavaScript 算法初探]]></title>
<url>%2F2018%2F03%2F25%2FIntroductionToAlgorithms%2F</url>
<content type="text"><![CDATA[https://www.jianshu.com/p/1b4068ccd505http://louiszhai.github.io/2016/12/23/sort/排序算法冒泡排序基数排序双重多循环,按位循环匹配1234567891011121314151617181920212223242526function radixSort(arr, maxDigit) { var counter = [] var mod = 10 var dev = 1 for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) { for(var j = 0; j < arr.length; j++) { var bucket = ~~((arr[j] % mod) / dev) if(counter[bucket]==null) { counter[bucket] = [] } counter[bucket].push(arr[j]) } var pos = 0 for(var j = 0; j < counter.length; j++) { var value = null if(counter[j]!=null) { while ((value = counter[j].shift()) != null) { arr[pos++] = value } } } } return arr;}var sorts = [23, 10000000, 31, 11, 1, 2, 4]radixSort(sorts, 8)优化123456789101112131415161718192021222324252627function radixSort(arr) { var counter = [] var maxDigit = Math.max(...arr).toString().length for (var i = 0; i < maxDigit; i++) { var reg = RegExp("^\\d*(\\d)\\d{" + i + "}$") arr.forEach((item) => { var bucket = 0 item.toString().replace(reg, ($0, $1) => { bucket = $1 }) if (counter[bucket] == undefined) counter[bucket] = [] counter[bucket].push(item) }) var pos = 0 counter.forEach((item) => { var value = null if (item != null) { while ((value = item.shift()) != null) { arr[pos++] = value } } }) } return arr}var sorts = [23, 10000000, 31, 11, 1, 2, 4]radixSort(sorts, 8)通过正则判断不同位置的数值,默认为0。各种排序性能对比如下:排序类型平均情况最好情况最坏情况辅助空间稳定性冒泡排序O(n²)O(n)O(n²)O(1)稳定选择排序O(n²)O(n²)O(n²)O(1)不稳定直接插入排序O(n²)O(n)O(n²)O(1)稳定折半插入排序O(n²)O(n)O(n²)O(1)稳定希尔排序O(n^1.3)O(nlogn)O(n²)O(1)不稳定归并排序O(nlog₂n)O(nlog₂n)O(nlog₂n)O(n)稳定快速排序O(nlog₂n)O(nlog₂n)O(n²)O(nlog₂n)不稳定堆排序O(nlog₂n)O(nlog₂n)O(nlog₂n)O(1)不稳定计数排序O(n+k)O(n+k)O(n+k)O(k)稳定桶排序O(n+k)O(n+k)O(n²)O(n+k)(不)稳定基数排序O(d(n+k))O(d(n+k))O(d(n+kd))O(n+kd)稳定]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>Algorithms</tag>
</tags>
</entry>
<entry>
<title><![CDATA[上万的数据如何在前端页面快速展示?]]></title>
<url>%2F2018%2F03%2F15%2FmillionDataShow%2F</url>
<content type="text"><![CDATA[前端要呈现百万数据,这个需求是很少见的,但是展示千条稍微复杂点的数据,这种需求还是比较常见,只要内存够,javascript 肯定是吃得消的,计算几千上万条数据,js 效率根本不在话下,但是 DOM 的渲染浏览器扛不住,CPU 稍微搓点的电脑必然会卡爆。首先,这种情况很少见。如果要在前端呈现大量的数据,一般的策略就是分页。虽然这么说,但是如果展示上百条数据,图片资源消耗,也会让页面发生卡顿。JavaScript效率DOM渲染卡顿DOM渲染一直困扰前端的难题,由于设备参差不齐,CPU性能严重影响了页面的渲染能力。方案123456789101112 /==============> box | .... | / +--------------+/+=======|=====List=====|========+| +--------------+ || | List | || +--------------+ |\| | List | | \| +--------------+ | \======> Container+=======|=====List=====|========+ +--------------+ | .... | Created By Barret LeeDemo123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116function VirtualList(config) { var vWidth = config.width ? (config && config.width + 'px') : '100%' var vHeight = config.height ? (config && config.height + 'px') : '100%' var itemHeight = this.itemHeight = config.itemH // this.items = config.items this.generatorFn = config.generatorFn this.totalRows = config.totalRows || (config.items && config.items.length) //List Num var screenItemsLen = Math.ceil(config.height / itemHeight) //cache List Num this.cachedItemsLen = screenItemsLen * 3 console.log(config.height) //Set Scroller init var scroller = VirtualList.createScroller(itemHeight * this.totalRows) this.container = VirtualList.createContainer(vWidth, vHeight) this.container.appendChild(scroller) this.render(this.container, 0) var self = this var lastRepaintY var maxBuffer = screenItemsLen * itemHeight var lastScrolled = 0 this.rmNodeInerval = setInterval(function() { if (Date.now() - lastScrolled > 100) { var badNodes = document.querySelectorAll('[data-virtual="1"]') for (var i = 0, l = badNodes.length; i < l; i++) { self.container.removeChild(badNodes[i]) } } }, 300) function onScroll(e) { var scrollTop = e.target.scrollTop if (!lastRepaintY || Math.abs(scrollTop - lastRepaintY) > maxBuffer) { var first = parseInt(scrollTop / itemHeight) - screenItemsLen self.render(self.container, first < 0 ? 0 : first) lastRepaintY = scrollTop } lastScrolled = Date.now() e.preventDefault && e.preventDefault() } this.container.addEventListener('scroll', onScroll)}VirtualList.prototype.render = function(node, num) { var allItem = num + this.cachedItemsLen if (allItem > this.totalRows) { allItem = this.totalRows } var fragment = document.createDocumentFragment() // for add Item console.log(allItem) for (var i = num; i < allItem; i++) { fragment.appendChild(this.createRow(i)) } console.log(fragment) for (var j = 1, l = node.childNodes.length; j < l; j++) { node.childNodes[j].style.display = 'none' node.childNodes[j].setAttribute('data-virtual', '1') } node.appendChild(fragment)}VirtualList.prototype.createRow = function(i) { var item; if (this.generatorFn) { item = this.generatorFn(i) } else if (this.items) { } item.classList.add('item') item.style.position = 'absolute' item.style.top = (i * this.itemHeight + 'px') console.log(item) return item}VirtualList.createContainer = function(width, height) { var box = document.createElement('div') box.style.width = width box.style.height = height box.style.overflow = 'auto' box.style.position = 'relative' box.style.padding = 0 box.style.border = '1px solid black' return box}VirtualList.createScroller = function(boxH) { var scroller = document.createElement('div') scroller.style.opacity = 0 scroller.style.position = 'absolute' scroller.style.top = 0 scroller.style.left = 0 scroller.style.width = '1px' scroller.style.height = boxH + 'px' return scroller}function dataInit (rows, cloumns) { var data = [] for (var i = 0; i < cloumns; i++) { var list = [] for (var j = 0; j < rows; j++) { list.push({ content: 'item-' + (rows * i + j + 1), id: rows * i + j + 1, cloumns: i + 1, rows: j + 1, isNo: [true, false][Math.floor(Math.random()*[true, false].length)] }) } data.push({ id: i + 1, list: list }) } return data}初始化12345678910var List = new VirtualList({ width: 600, // box width height: 300, // box height itemH: 30, // item height totalRows: data.length, // data generatorFn: function(key) { // 生成器 var el = document.createElement('div') return el }})计算容器何以显示的List个数1var screenItemsLen = Math.ceil(config.height / itemHeight)缓存的List Div的数码1this.cachedItemsLen = screenItemsLen * 3容器的整体高度1itemHeight * this.totalRowsrender() 计算需要展示的内容,即将替换的内容createRow() 创建ListcreateContainer() 创建容器createScroller() 创建将容器撑起div]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Javascript call apply bind]]></title>
<url>%2F2018%2F02%2F28%2FcallApplyBind%2F</url>
<content type="text"><![CDATA[来源继承自Function.prototype中的,所以这三个方法都可以在对象,数组,函数中使用。123456console.log(Function.prototype.hasOwnProperty('call'))// trueconsole.log(Function.prototype.hasOwnProperty('apply'))// trueconsole.log(Function.prototype.hasOwnProperty('bind'))// true12345678910111213141516171819202122function Person(name) { this.name = name;}Person.prototype = { constructor: Person, showName: function() { console.log(this.name); }}var person = new Person('qianlong');person.showName();// qianlongvar animal = { name: 'cat'}person.showName.call(animal);// catperson.showName.apply(animal);// catperson.showName.bind(animal)();// cat上面看起来三个函数的作用差不多,干的事几乎是一样的,那为什么要存在3个家伙呢,留一个不就可以。所以其实他们干的事从本质上讲都是一样的动态的改变this上下文,但是多少还是有一些差别的..call()调用一个对象的一个方法,以另一个对象替换当前对象。1fun.call(thisArg[, arg1[, arg2[, ...]]])Object.prototype.toString.call([]),就是一个Array对象借用了Object对象上的方法。thisArg函数运行时指定的this值,可能的值为:不传,或者传null,undefined, this指向window对象传递另一个函数的函数名fun2,this指向函数fun2的引用值为原始值(数字,字符串,布尔值),this会指向该原始值的自动包装对象,如 String、Number、Boolean传递一个对象,函数中的this指向这个对象案例12345678910111213141516171819202122232425262728function a() { //输出函数a中的this对象 console.log(this); }//定义函数bfunction b() {} //定义对象objvar obj = { name:'这是一个屌丝'};a.call();// windowa.call(null);// windowa.call(undefined);// windowa.call(1);// Numbera.call('');// Stringa.call(true);// Booleana.call(b);// function b(){}a.call(obj);// {name: "这是一个屌丝"}使用call方法调用匿名函数并且指定上下文的this123456789function greet() { var reply = [this.person, '是一个轻量的', this.role].join(' '); console.log(reply);}var i = { person: 'JSLite.io', role: 'Javascript 库。'};greet.call(i); // JSLite.io 是一个轻量的 Javascript 库。使用call方法调用匿名函数1234567891011121314var animals = [ {species: 'Lion', name: 'King'}, {species: 'Whale', name: 'Fail'}];for (var i = 0; i < animals.length; i++) { (function (i) { this.print = function () { console.log('#' + i + ' ' + this.species + ': ' + this.name); } this.print(); }).call(animals[i], i);}//#0 Lion: King//#1 Whale: Fail使用call方法调用函数传参数1234567891011121314151617var a = { // 定义a的属性 name: 'JSLite.io', // 定义a的方法 say: function() { console.log("Hi,I'm function a!"); }};function b(name){ console.log("Post params: " + name); console.log("I'm " + this.name); this.say();}b.call(a,'test');//Post params: test//I'm JSLite.io//I'm function a!arguments转成数组12345678function list() { return Array.prototype.slice.call(arguments); // return [].call(arguments); // Array.from(arguments) // [].from(arguments)}list(1, 2, 3);// [1, 2, 3]为什么能实现这样的功能将arguments转成数组?(arguments对象借用了Array对象上的方法。)首先call了之后,this指向了所传进去的arguments。我们可以假设slice方法的内部实现是这样子的:创建一个新数组,然后for循环遍历this,将this[i]一个个地赋值给新数组,最后返回该新数组。因此也就可以理解能实现这样的功能了。将伪数组转化为数组1234567891011121314var fakeArr = { 0: 'a', 1: 'b', length: 2};var arr1 = Array.prototype.slice.call(fakeArr);console.log(arr1[0]);// avar arr2 = [].slice.call(fakeArr);console.log(arr2[0]);// aarr1.push('c');console.log(arr1);// ["a", "b", "c"]判断变量类型1234567function isArray(obj) { return Object.prototype.toString.call(obj) == '[object Array]';}isArray([]);// trueisArray('qianlong');// falseapply()应用某一对象的一个方法,用另一个对象替换当前对象。语法与 call() 方法的语法几乎完全相同,唯一的区别在于,apply的第二个参数必须是一个包含多个参数的数组(或类数组对象)。1fun.apply(thisArg[, argsArray])注意: 需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受类数组对象。如果传入类数组对象,它们会抛出异常。argsArray一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。12345function jsy(x, y, z) { console.log(x, y, z);}jsy.apply(null, [1, 2, 3]); // 1 2 3案例使用apply来链接构造器的例子12345678910111213141516171819202122Function.prototype.construct = function(aArgs) { var fConstructor = this, fNewConstr = function() { fConstructor.apply(this, aArgs); }; fNewConstr.prototype = fConstructor.prototype; return new fNewConstr();};function MyConstructor () { for (var i = 0; i < arguments.length; i++) { console.log(arguments, this) this["property" + i] = arguments[i]; }}var myArray = [4, "Hello world!", false];var myInstance = MyConstructor.construct(myArray);console.log(myInstance.property1);// Hello world!console.log(myInstance instanceof MyConstructor);// trueconsole.log(myInstance.constructor);// MyConstructor() {}内置函数调用数组拼接12345678910111213141516var array1 = [1 , 2 , 3, 5];var array2 = ["xie" , "li" , "qun" , "tsrot"];Array.prototype.push.apply(array1, array2);console.log(array1);// [1, 2, 3, 5, "xie", "li", "qun", "tsrot"]var array1 = [1 , 2 , 3, 5];array1.push("xie" , "li" , "qun" , "tsrot");console.log(array1);// [1, 2, 3, 5, "xie", "li", "qun", "tsrot"]var array1 = [1 , 2 , 3, 5];var array2 = ["xie" , "li" , "qun" , "tsrot"];var arrays = array1.concat(array2);console.log(arrays);// [1, 2, 3, 5, "xie", "li", "qun", "tsrot"]最大或者最小值12345678910/* 使用 Math.min/Math.max 在 apply 中应用 */// 里面有最大最小数字值的一个数组对象// 一般情况是用 Math.max(5, 6, ..) 或者 Math.max(numbers[0], ...) 来找最大值var numbers = [5, 6, 2, 3, 7];var max = Math.max.apply(null, numbers);var min = Math.min.apply(null, numbers);console.log('max: ', max);// max: 7console.log('min: ', min);// min: 2123456789//通常情况我们会这样来找到数字的最大或者最小值//比对上面的栗子,是不是下面的看起来没有上面的舒服呢?max = -Infinity, min = +Infinity;for (var i = 0; i < numbers.length; i++) { if (numbers[i] > max) max = numbers[i]; if (numbers[i] < min) min = numbers[i];}参数数组切块后循环传入找到数字的最小值1234567891011function minOfArray(arr) { var min = Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < len; i += QUANTUM) { var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len))); min = Math.min(submin, min); } return min;}var min = minOfArray([5, 6, 2, 3, 7]);// 2bind() +ES5函数会创建一个新函数(称为绑定函数),在ECMAScript5中扩展了叫bind的方法(IE6,7,8不支持),应用某一对象的一个方法,用另一个对象替换当前对象。1fun.bind(thisArg[, arg1[, arg2[, ...]]]);bind是ES5新增的一个方法传参和call或apply类似不会执行对应的函数,call或apply会自动执行对应的函数返回对函数的引用案例保存this变量123456789101112131415161718var foo = { bar: 1, eventBind: function() { var _this = this; $('.someClass').on('click', function(event) { console.log(_this.bar); }); }}var foo = { bar: 1, eventBind: function() { $('.someClass').on('click', function(event) { console.log(this.bar); }.bind(this)); }}EventClick123456789101112131415/** * 给document添加click事件监听,并绑定EventClick函数 * 通过bind方法设置EventClick的this为obj,并传递参数p1,p2 */document.addEventListener('click',EventClick.bind(obj,'p1','p2'),false);var obj = {name:'JSLite.io'};function EventClick(a,b) { console.log( this.name, //JSLite.io a, //p1 b //p2 )}// 当点击网页时触发并执行// JSLite.io p1 p2call页面会直接输出 JSLite.io p1 p212345678910var obj = {name:'JSLite.io'};document.addEventListener('click',EventClick.call(obj,'p1','p2'),false);function EventClick(a,b) { console.log( this.name, //JSLite.io a, //p1 b //p2 )}// JSLite.io p1 p2bind()方法会创建一个新函数,称为绑定函数。 bind是ES5新增的一个方法,不会执行对应的函数(call或apply会自动执行对应的函数),而是返回对绑定函数的引用。 当调用这个绑定函数时,thisArg参数作为 this,第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。 简单地说,bind会产生一个新的函数,这个函数可以有预设的参数。12345678910111213function list() { return Array.prototype.slice.call(arguments); var leadingThirtysevenList = list.bind(undefined, 37); var list = leadingThirtysevenList(1, 2, 3); console.log(list); bind调用简单把类数组换成真正的数组,bind能够更简单地使用:var slice = Array.prototype.slice;slice.apply(arguments); var unboundSlice = Array.prototype.slice;var slice = Function.prototype.apply.bind(unboundSlice);slice(arguments);原型扩展12345678910111213141516function test() { // 检测arguments是否为Array的实例 console.log( arguments instanceof Array, //false Array.isArray(arguments) //false ); // 判断arguments是否有forEach方法 console.log(arguments.forEach); // undefined // 将数组中的forEach应用到arguments上 Array.prototype.forEach.call(arguments,function(item){ console.log(item); // 1 2 3 4 });}test(1, 2, 3, 4);兼容处理-Polyfill(兼容旧浏览器)123456789101112131415161718192021222324252627if (!Function.prototype.bind) { Function.prototype.bind = function (self) { if (typeof this !== "function") { // bind是ES5新增的一个方法 // 抛出异常 throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), // this在这里指向的是目标函数 fToBind = this, fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP // 此时的this就是new出的obj ? this // 如果传递的oThis无效,就将fBound的调用者作为this : self || this, // 将通过bind传递的参数和调用时传递的参数进行合并,并作为最终的参数传递 aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; //将目标函数的原型对象拷贝到新函数中,因为目标函数有可能被当作构造函数使用 fBound.prototype = new fNOP(); //返回fBond的引用,由外部按需调用 return fBound; };}区别call的arg传参需一个一个传,apply则直接传一个数组。call和apply直接执行函数,而bind需要再一次调用。this123456789var name = 'windowsName';function a() { var name = 'Cherry'; console.log(this.name);// windowsName console.log('inner: ' + this);// inner: Window}a();console.log('outer: ' + this);// outer: Windowthis -> window.a() -> window12345678910var name = 'windowsName';var a = { name: 'Cherry', fn: function () { console.log(this.name); }}a.fn();// Cherrythis -> a.fn() -> a12345678910var name = 'windowsName';var a = { name: 'Cherry', fn: function () { console.log(this.name); }}window.a.fn();// Cherrythis -> window.a.fn() -> a123456789var name = 'windowsName';var a = { fn: function () { console.log(this.name); }}window.a.fn();// undefinedthis -> window.a.fn() -> a12345678910var name = 'windowsName';var a = { fn: function () { console.log(this.name); }}var f = a.fn();fn();// windowsNamethis -> window.f() -> window12345678910111213var name = 'windowsName';var a = { name: 'Cherry', fn: function () { innerFunction(); function innerFunction() { console.log(this.name); } }}window.a.fn();// windowsNamethis -> window.innerFunction() -> window改变this指向使用 ES6 的箭头函数在函数内部使用 _this = this使用 apply、call、bindnew 实例化一个对象1234567891011121314var name = 'windowsName';var a = { name: 'Cherry', func1: function () { console.log(this.name); }, func2: function () { setTimeout(function () { this.func1(); }, 100); }};a.func2();// this.func1 is not a function在不使用箭头函数的情况下,是会报错的,因为最后调用 setTimeout 的对象是 window,但是在 window 中并没有 func1 函数。箭头函数1234567891011121314var name = 'windowsName';var a = { name: 'Cherry', func1: function () { console.log(this.name); }, func2: function () { setTimeout(() => { this.func1(); }, 100); }};a.func2();// Cherry函数内部使用123456789101112131415var name = 'windowsName';var a = { name: 'Cherry', func1: function () { console.log(this.name); }, func2: function () { var self = this; setTimeout(function() { self.func1(); }, 100); }};a.func2();// Cherry使用 apply、call、bind1234567891011121314var name = 'windowsName';var a = { name: 'Cherry', func1: function () { console.log(this.name); }, func2: function () { setTimeout(function() { this.func1(); }.apply(a), 100); }};a.func2();// Cherry1234567891011121314var name = 'windowsName';var a = { name: 'Cherry', func1: function () { console.log(this.name); }, func2: function () { setTimeout(function() { this.func1(); }.call(a), 100); }};a.func2();// Cherry1234567891011121314var name = 'windowsName';var a = { name: 'Cherry', func1: function () { console.log(this.name); }, func2: function () { setTimeout(function() { this.func1(); }.bind(a)(), 100); }};a.func2();// CherryJS 中的函数调用作为一个函数调用1234567891011var name = 'windowsName';function a() { var name = 'Cherry'; console.log(this.name); console.log('inner: ' + this);}a();console.log('outer: ' + this);// windowsName// inner: Window// outer: Window函数作为方法调用123456789var name = 'windowsName';var a = { name: 'Cherry', fn : function () { console.log(this.name); }}a.fn();// Cherry使用构造函数调用函数123456function myFunction(arg1, arg2) { this.firstName = arg1; this.lastName = arg2;}var a = new myFunction('Li', 'Cherry');a.lastName;伪代码表示:1234567891011var a = new myFunction('Li', 'Cherry');new myFunction { var obj = {}; obj.__proto__ = myFunction.prototype; var result = myFunction.call(obj, 'Li', 'Cherry'); return typeof result === 'obj' ? result : obj;}创建一个空对象 obj;将新创建的空对象的隐式原型指向其构造函数的显示原型。使用 call 改变 this 的指向如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。作为函数方法调用函数(call、apply)123456789101112131415161718192021222324var name = 'windowsName';function fn() { var name = 'Cherry'; innerFunction(); function innerFunction() { console.log(this.name); // windowsName }}fn();var name = 'windowsName';var a = { name : 'Cherry', func1: function () { console.log(this.name) }, func2: function () { setTimeout( function () { this.func1() },100); }};a.func2();// this.func1 is not a functionfunction属性length:形参的个数;name:函数名;prototype:类的原型,在原型上定义的方法都是当前这个类的实例的公有方法;__proto__:把函数当做一个普通对象,指向Function这个类的原型拓展-回味JS基础:call apply 与 bind-JS 中的 call、apply、bind 方法详解-JS 中 call、apply、bind 那些事-this、apply、call、bind-JavaScript 中的 call、apply、bind 深入理解]]></content>
<categories>
<category>Javascript</category>
</categories>
<tags>
<tag>Javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JavaScript currying]]></title>
<url>%2F2018%2F02%2F28%2FfnCurrying%2F</url>
<content type="text"><![CDATA[在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由克里斯托弗·斯特雷奇以逻辑学家哈斯凯尔·加里命名的,尽管它是Moses Schönfinkel和戈特洛布·弗雷格发明的。高阶函数的特点:函数可以作为参数被传递;函数可以作为返回值输出。1234567var foo = function(a) { return function (b) { return function (c) { return a+b+c; }; };};反柯里化:函数柯里化的对偶是Uncurrying,一种使用匿名单参数函数来实现多参数函数的方法。理解Currying概念其实很简单,只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。简单求和函数a+b+c1234567function add(a, b, c) { return a + b + c;}console.log(add(1, 2, 3))=>6a+b+c Currying1234567891011function add(x) { return function (y) { return function (z) { return x + y + z; } }}var addOne = add(1);var addOneAndTwo = addOne(2);var addOneAndTwoAndThree = addOneAndTwo(3);console.log(addOneAndTwoAndThree);这里我们定义了一个add函数,它接受一个参数并返回一个新的函数。调用add之后,返回的函数就通过闭包的方式记住了add的第一个参数。一次性地调用它实在是有点繁琐,好在我们可以使用一个特殊的curry帮助函数(helper function)使这类函数的定义和调用更加容易。用ES6的箭头函数,我们可以将上面的add实现成这样:1const add = x => y => z => x + y + z;好像使用箭头函数更清晰了许多。12345678910function addFn(x) { return function fn(y) { console.log(y) return fn }}console.log(addFn(1)(2)(3)(4))=>addFn(1) fn(2) fn(3) fn(4)1234567891011121314151617181920212223function Arguments() { console.log(arguments) var fn = function () { console.log(arguments) return fn } fn.toString = function () { return arguments; } return fn;}console.log(Arguments(1)(2)(3)(4))function add(x) { return function (y) { return function (z) { return function (d) { return x + y + z + d; } } }}console.log(add(1)(2)(3)(4))场景使用实际场景的运用能更好的加深我们的理解,所以我们用实际的生活场景来看看 柯里化 如何运用。获取数据默认参数剩余参数(Array)arguments对象(非Array)数组拼接arguments转数组12Array.from(arguments)Array.prototype.slice.call(arguments)剩余参数1[...[1,3],...[1,2]] => [1, 3, 1, 2]concat()连接两个或更多的数组,并返回结果。12345var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])sum.concat(Array.from(arguments))a.concat(4,[1, 2]) => [4, 1, 2][].concat(4, 5) => [4, 5]slice方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象。原始数组不会被修改。12[].slice.call([1, 2, 4], 1) => [2, 4][].slice.call([1, 2]) => [1, 2]123456789Array.slice()var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];console.log(animals.slice(2));// ["camel", "duck", "elephant"]console.log(animals.slice(2, 4));// ["camel", "duck"]console.log(animals.slice(1, 5));// ["bison", "camel", "duck", "elephant"]除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用 [].slice.call(arguments) 来代替。另外,你可以使用 bind 来简化该过程。1234567var unboundSlice = Array.prototype.slice;var slice = Function.prototype.call.bind(unboundSlice);function list() { return slice(arguments);}var list1 = list(1, 2, 3);// [1, 2, 3]push向数组的末尾添加一个或更多元素,并返回新的长度。1234567[].push.apply(_args, [].slice.call(arguments));Array.prototype.push.apply(_args, [].slice.call(arguments))var a = [1];var c = [1, 3, 2];[].push.apply(a, c); // 返回lengthconsole.log(a).apply()a+b+cx + y + z + d12345678910function add(x) { return function (y) { return function (z) { return function (d) { return x + y + z + d; } } }}console.log(add(1)(2)(3)(4))求和这段代码实际上还是不能满足要求的,题主测试成功也只是因为所在环境的 console.log 会将结果转为 string 输出,为了 return tmp 不至于输出一个function,所以重新定义了函数 tmp 的 toString 方法,使其返回 sum 值。比如如果使用以下代码测试会发现问题1234567891011function add(a) { function fn(b) { a = a + b; return fn; } fn.toString = function () { return a; } return fn;}console.log(add(1)(2)(3)(4));12345678910111213function addCurry(x) { var sum = x; var fn = function (y) { sum = sum + y; return fn; }; fn.valueOf = function () { return sum; }; console.log('addCurry', fn); return fn;}console.log(addCurry(1)(2)(3)(4))123456789101112function add() { var sum = arguments[0]; var fn = function () { sum = sum + arguments[0]; return arguments.callee; } fn.valueOf = function () { return sum; } return fn;}console.log(add(1)(2)(3)(4));12345678910var add = function(x, y) { if (arguments.length == 1) { return function(z) { return x + z; } } else { return x + y; }}console.log(add(2,5)(2)(5));剩余参数1234567891011function addReduce(...a){ let b = function(...b){ console.log(...[...a,...b]) return addReduce(...[...a,...b]) } b.valueOf = () => { return a.reduce((x,y) => x+y ) } return b;}console.log(addReduce(1)(2)(3)(4));1234567891011121314function add(...a){ let sum = Array.from(a); let fn = function(...b) { sum = sum.concat(Array.from(b)); return fn; } fn.valueOf = () => { return sum.reduce((x, y) => { return x + y; }) } return fn;}console.log(add(1,11)(2)(2,3,4)(4));arguments1234567891011121314function add(){ var sum = Array.from(arguments); var fn = function() { let argsC = sum.concat(Array.from(arguments)); return add.apply(null, argsC) } fn.valueOf = function() { return sum.reduce((x,y) => { return x + y; }) } return fn;}console.log(add(1)(2)(3)(4));123456789101112131415function add(){ let sum = Array.from(arguments); let fn = function() { sum = sum.concat(Array.from(arguments)); // return fn; return arguments.callee; } fn.valueOf = () => { return sum.reduce((x, y) => { return x + y; }) } return fn;}console.log(add(1)(2)(3)(4));自定义方法(偏函数)1234567891011121314151617181920212223242526272829303132var currying = function (fn) { let args = []; let cuy = function() { [].push.apply(args, arguments); return arguments.callee; } cuy.valueOf = function() { return fn.apply(null, args); } return cuy}var add = currying(function() { let num = Array.from(arguments) return num.reduce((x, y) => { // console.log('add', num) return x + y })})var ride = currying(function() { let num = Array.from(arguments) return num.reduce((x, y) => { // console.log('ride', num) return x * y })})console.log(add(1)(2))console.log(add(1, 2))console.log(add())// 6console.log(ride(1, 2, 5))console.log(ride())// 10编写一个通用的 curry()1234567891011121314151617181920212223function curry(fn) { return function curried() { var args = [].slice.call(arguments); return args.length >= fn.length ? fn.apply(null, args) : function () { var rest = [].slice.call(arguments); return curried.apply(null, args.concat(rest)); }; };}function foo(a,b,c) { return a+b+c;}var curriedFoo = curry(foo);console.log(curriedFoo(1,2,3));// 6console.log(curriedFoo(1)(2,3));// 6console.log(curriedFoo(1)(2)(3));// 6console.log(curriedFoo(1,2)(3));// 6123456789101112131415161718192021222324252627282930var currying = function (fn) { let args = []; let cuy = function() { [].push.apply(args, arguments); return arguments.callee; } cuy.valueOf = function() { return fn.apply(null, args); } return cuy}var add = currying(function() { return args.reduce((x, y) => { // console.log('add', args) return x + y })})var ride = currying(function() { return args.reduce((x, y) => { // console.log('ride', args) return x * y })})console.log(add(1)(2))console.log(add(1, 2))console.log(add())// 6console.log(ride(1, 2, 5))console.log(ride())// 10记账本记账本,每天记录使用多少钱,一个月算一次总花费(或者在我想要知道的时候)123456789101112131415161718192021222324252627function account(){ var total = []; function money(p) { if (arguments.length === 0) { // 计算一共花了多少钱 total = total.reduce((sum, value) => { return sum + value; }, 0); console.log('一共花了', total + ' 元'); } else { // 记录每天花了多少钱 total.push(p); console.log('今天花了', p+' 元'); } } return money;}var spend = account();console.log(spend(15));console.log(spend(30));// 不传参数的时候就返回真正的结果console.log(spend());=>今天花了 15 元今天花了 30 元一共花了 45 元老婆的测试12345678910111213141516171819202122232425262728293031323334353637383940414243var currying = function(fn) { // fn 指官员消化老婆的手段 console.log(arguments); var args = [].slice.call(arguments, 1); console.log(args); // args 指的是那个合法老婆 return function() { console.log(arguments); // 已经有的老婆和新搞定的老婆们合成一体,方便控制 var newArgs = args.concat([].slice.call(arguments)); // 这些老婆们用 fn 这个手段消化利用,完成韦小宝前辈的壮举并返回 return fn.apply(null, newArgs); };};// 下为官员如何搞定7个老婆的测试// 获得合法老婆var getWife = currying(function() { console.log(arguments); var allWife = [].slice.call(arguments); // allwife 就是所有的老婆的,包括暗渡陈仓进来的老婆 console.log(allWife.join(";"));}, "合法老婆");// 获得其他6个老婆console.log('大老婆')getWife("大老婆","小老婆","俏老婆","刁蛮老婆","乖老婆","送上门老婆");// 换一批老婆console.log('超越韦小宝的老婆')getWife("超越韦小宝的老婆");=>Arguments(2) [ƒ, "合法老婆", callee: ƒ, Symbol(Symbol.iterator): ƒ]["合法老婆"]大老婆Arguments(6) ["大老婆", "小老婆", "俏老婆", "刁蛮老婆", "乖老婆", "送上门老婆", callee: ƒ, Symbol(Symbol.iterator): ƒ]Arguments(7) ["合法老婆", "大老婆", "小老婆", "俏老婆", "刁蛮老婆", "乖老婆", "送上门老婆", callee: ƒ, Symbol(Symbol.iterator): ƒ]合法老婆;大老婆;小老婆;俏老婆;刁蛮老婆;乖老婆;送上门老婆超越韦小宝的老婆Arguments ["超越韦小宝的老婆", callee: ƒ, Symbol(Symbol.iterator): ƒ]Arguments(2) ["合法老婆", "超越韦小宝的老婆", callee: ƒ, Symbol(Symbol.iterator): ƒ]合法老婆;超越韦小宝的老婆实现柯里化12345678910111213141516171819202122232425262728293031323334var currying = function(fn) { var args = []; return function() { if (arguments.length === 0) { // 没传参数时,调用这个函数 return fn.apply(this, args); } else { // 传入了参数,把参数保存在args [].push.apply(args, arguments); // 返回这个函数的引用 return arguments.callee; } }}var cost = (function() { var money = 0; return function() { for (var i = 0; i < arguments.length; i++) { money += arguments[i]; } return money; }})();// 返回currying function的方法var costs = currying(cost);console.log(costs());// 传入了参数,不真正求值(返回这个函数的引用)console.log(costs(100));// 传入了参数,不真正求值(返回这个函数的引用)console.log(costs(200)(300));// 传入了参数,不真正求值(返回这个函数的引用)console.log(costs(300));// 求值并且输出900console.log(costs());1234567891011121314151617181920212223242526272829303132333435363738394041var currying = function(fn) { var args = Array.prototype.slice.call(arguments, 1); return function() { if (arguments.length === 0) { // 没传参数时,调用这个函数 return fn.apply(this, args); } else { // 传入了参数,把参数保存在args [].push.apply(args, arguments); // 返回这个函数的引用 return arguments.callee; } }}var cost = (function() { var money = 0; return function() { for (var i = 0; i < arguments.length; i++) { money += arguments[i]; } return money; }})();function uncurrying(fn) { return function(...args) { var ret = fn; for (let i = 0; i < args.length; i++) { // 反复调用currying版本的函数 ret = ret(args[i]); } // 返回结果 return ret; };}// 返回currying function的方法var curryingCost = currying(cost);// 返回uncurrying function的方法var uncurryingCost = uncurrying(curryingCost);// 600console.log(uncurryingCost(100, 200, 300));console.log(uncurryingCost()());f([‘1’,’2’]) => ‘12’123456789var concatArray = function(chars) { return chars.reduce(function(a, b) { return a.concat(b); });}concat(['1','2','3'])=>'123'固定易变因素柯里化特性决定了它这应用场景。提前把易变因素,传参固定下来,生成一个更明确的应用函数。最典型的代表应用,是bind函数用以固定this这个易变对象。1234567Function.prototype.bind = function(context) { var _this = this, _args = Array.prototype.slice.call(arguments, 1); return function() { return _this.apply(context, _args.concat(Array.prototype.slice.call(arguments))) }}Uncurrying函数柯里化的对偶是Uncurrying,一种使用匿名单参数函数来实现多参数函数的方法。1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253可能遇到这种情况:拿到一个柯里化后的函数,却想要它柯里化之前的版本,这本质上就是想将类似f(1)(2)(3)的函数变回类似g(1,2,3)的函数。下面是简单的uncurrying的实现方式:function uncurrying(fn) { return function(...args) { var ret = fn; for (let i = 0; i < args.length; i++) { ret = ret(args[i]); // 反复调用currying版本的函数 } return ret; // 返回结果 };}注意,不要以为uncurrying后的函数和currying之前的函数一模一样,它们只是行为类似!var currying = function(fn) { var args = Array.prototype.slice.call(arguments, 1); return function() { if (arguments.length === 0) { return fn.apply(this, args); // 没传参数时,调用这个函数 } else { [].push.apply(args, arguments); // 传入了参数,把参数保存下来 return arguments.callee; // 返回这个函数的引用 } }}function uncurrying(fn) { return function(...args) { var ret = fn; for (let i = 0; i < args.length; i++) { ret = ret(args[i]); // 反复调用currying版本的函数 } return ret; // 返回结果 };}var cost = (function() { var money = 0; return function() { for (var i = 0; i < arguments.length; i++) { money += arguments[i]; } return money; }})();var curryingCost = currying(cost);var uncurryingCost = uncurrying(curryingCost);console.log(uncurryingCost(100, 200, 300)()); // 600偏函数Partial Application(偏函数应用) 是指使用一个函数并将其应用一个或多个参数,但不是全部参数,在这个过程中创建一个新函数。1234567function add3(a, b, c) { return a+b+c; } add3(2,4,8);// 14var add6 = add3.bind(this, 2, 4); add6(8);// 14var toString=object.prototype.toString;var isString=function(obj){return toString.call(obj)==’[object String]’;};var isFunction=function(obj){return toString.call(obj)==’[object Function]’;};……….偏函数方法:var isType=function(type){return function(obj){return tostring.call(obj)==’[object ‘ + type+ ‘ ]’;}}12345678910111213141516171819202122//生成偏函数的函数var isType = function(type) { return function(obj) { return toString.call(obj) == '[object ' + type + ']'; }};//生成偏函数var isArray = isType('Array');var isBoolean = isType('Boolean');var isFunction = isType('Function');var isNumber = isType('Number');//使用偏函数var isArray_ = isArray(['a','d']);var isBoolean_ = isBoolean(true);var isFunction_ = isFunction(isType);var isNumber_ = isNumber(888);alert("['a','d'] is an Array?" + isArray_);alert("true is a Boolean? " + isBoolean_);alert('isType is a Function?' + isFunction_);alert('888 is a Number?' + isNumber_);拓展-JavaScript函数柯里化-我理解的函数柯里化-高阶函数应用–currying-从一道面试题谈谈函数柯里化 (Currying)-Javascript中有趣的反柯里化技术-为什么要柯里化(why-curry-helps)slide-前端开发者进阶之函数柯里化Currying-JS中的柯里化(currying)-何为Curry化/柯里化?-一道题看透函数柯里化(currying)-掌握 JavaScript 函数的柯里化-----ES6 中 curry 和 apply 的实现apply() 在 ES6 中的实现:123456789function curry(fn) { return function curried(...args) { return args.length >= fn.length ? fn.call(this, ...args) : (...rest) => { return curried.call(this, ...args, ...rest); }; };}apply() 在 ES6 中的实现:123456// 应用左边任意数量的参数function apply(fn, ...args) { return (..._args) => { return fn(...args, ..._args); };}]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JavaScript RegExpObjects 正则表达式]]></title>
<url>%2F2018%2F02%2F27%2F1.10-RegExpObjects%2F</url>
<content type="text"><![CDATA[一个个音符杂乱无章的组合在一起,弹奏出的或许就是噪音,同样的音符经过作曲家的手,就可以谱出非常动听的乐曲,一个演奏者同样可以照着乐谱奏出动听的乐曲,但他/她或许不知道该如何去改变音符的组合,使得乐曲更动听。作为正则的使用者也一样,不懂正则引擎原理的情况下,同样可以写出满足需求的正则,但是不知道原理,却很难写出高效且没有隐患的正则。所以对于经常使用正则,或是有兴趣深入学习正则的人,还是有必要了解一下正则引擎的匹配原理的。定义正则表达式(regular expression)是一个描述字符模式的对象,使用正则表达式可以进行强大的模式匹配和文本检索与替换功能。JavaScript 的正则表达式语法是 Perl5 的正则表达式语法的大型子集,所以对于有 Perl 编程经验的程序员来说,学习 JavaScript 中的正则表达式是小菜一碟。正则表达式是描述字符模式的对象,用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的强大工具。JavaScript中的正则表达式用RegExp对象表示,可以使用RegExp()构造函数来创建RegExp对象,不过RegExp对象更多是通过字面量的语法来创建。创建构造函数12345<!-- // 不推荐写法 -->var patt = new RegExp(pattern模式,modifiers修饰符)<!-- // 匹配所有的a或A -->var reg = new RegExp("a","gi")注意:当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \)。字面量12345<!-- // 推荐写法 -->var patt = /pattern/modifiers<!-- // 匹配所有的a或A -->var reg = /a/gi12var reg = new RegExp("\\w+")var reg = /\w+/版本区别在ECMAScript5中这种情况有所改变,相同正则表达式字面量的每次计算都会创建新的实例对象,目前很多现代浏览器也对此做了纠正。123456789101112131415161718function getRE(){ var re = /[a-z]/ re.foo = 'bar' return re}var reg = getRE()re2 = getRE()console.log(reg === re2)reg.foo = 'baz'console.log(re2.foo)ECMAScript3同一对象<!-- // true --><!-- // "baz" -->ECMAScript5不同对象<!-- // false --><!-- // "bar" -->表达式模式修饰词表达式描述i执行对大小写不敏感的匹配g执行全局匹配模式(查找所有匹配而非在找到第一个匹配后停止)m执行多行匹配模式12345678910111213141516var str='HwwwwLwello orllld lLll!'console.log(str.match(/l/))<!-- // ["l", index: 8, input: "HwwwwLwello orllld lLll!"] -->console.log(str.match(/l/i))<!-- // ["L", index: 5, input: "HwwwwLwello orllld lLll!"] -->console.log(str.match(/l/g))<!-- // ["l", "l", "l", "l", "l", "l", "l", "l"] -->var str='Hwwwwl\nwello orllld lLll!'console.log(str)<!-- // Hwwwwl --><!-- // wello orllld lLll! -->console.log(str.match(/l$/))<!-- // null -->console.log(str.match(/l$/m))<!-- // ["l", index: 5, input: "Hwwwwl↵wello orllld lLll!"] -->元字符与其他语言中的正则表达式类似,模式中使用的所有元字符都必须转义。正则表达式中的元字符包括:1( [ { \ ^ $ | ) ? * + . ] }这些元字符在正则表达式中都有一或多种特殊用途,因此如果想要匹配字符串中包含的这些字符,就必须对它们进行转义。下面给出几个例子。12345var pattern1 = /[bc]at/i<!-- // 匹配第一个"bat"或"cat",不区分大小写 -->var pattern2 = /\[bc\]at/i<!-- // 匹配第一个" [bc]at",不区分大小写 -->直接量字符字符描述字母数字自身\0查找 NUL 字符(\u0000)\t查找制表符(\u0009)\v查找垂直制表符(\u000A)\n查找换行符(\u000B)\f查找换页符(\u000C)\r查找回车符(\u000D)\xdd查找以十六进制数 dd 规定的字符(\x0A => \n)\uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符(\u0009 => \t)\cX控制字符^X (\cJ => \n)12345678var str='null \t \n \f \r 'console.log(str.match(/\n/))// ["↵", index: 7, input: "null ↵ "]console.log(str.match(/\f/))// [" ", index: 9, input: "null ↵ "]var str='null'console.log(str.test(/\0/))//字符类字符描述.查找单个字符,除了换行和行结束符\w(word)查找单词字符:[a-zA-Z_0-9](单词字符包括:a-z、A-Z、0-9,以及下划线)\W查找非单词字符:[^a-zA-Z_0-9](单词字符包括:a-z、A-Z、0-9,以及下划线)\s(white space)查找空白字符\S查找非空白字符\d(digit)查找数字:[0-9]\D查找非数字字符:[^0-9][0-9]查找任何从 0 至 9 的数字[a-z]查找任何从小写 a 到小写 z 的字符[A-Z]查找任何从大写 A 到大写 Z 的字符[A-z]查找任何从大写 A 到小写 z 的字符[…]查找方括号之间的任何字符(没有顺序同级)[^…]查找不在方括号之间的任何字符[adgk]查找给定集合内的任何字符[^adgk]查找给定集合外的任何字符如果要匹配任意字符怎么办?可以使用 [\d\D]、[\w\W]、[\s\S] 和 [^] 中任何的一个。12345678910111213141516171819202122232425262728293031323334353637383940414243var str='3 o !_..'console.log(str.match(/\w/g))<!-- // ["3", "o", "_"] -->var str='3 o !_..'console.log(str.match(/\W/g))<!-- // [" ", " ", "!", ".", "."] -->var str='3 o !_..'console.log(str.match(/\s/g))<!-- // [" ", " "] -->var str='3 o !_..'console.log(str.match(/\S/g))<!-- // ["3", "o", "!", "_", ".", "."] -->var str='3 o !_..'console.log(str.match(/\d/g))<!-- // ["3"] -->var str='3 o !_..'console.log(str.match(/\b/g))<!-- // ["", "", "", "", "", ""] -->注:单词前后var str='3 o A!_..'console.log(str.match(/[A-Z]/g))<!-- // ["A"] -->var str='3 o A!_..'console.log(str.match(/[A-z]/g))<!-- // ["o", "A", "_"] -->注:此处出现了"_",a-z、A-Z,以及下划线var str='12323 orllbld lLll!'console.log(str.match(/[abc]/g))<!-- // ["b"] -->console.log(str.match(/[ro3]/g))<!-- // ["3", "3", "o", "r"] -->console.log(str.match(/[^abc]/g))<!-- // ["1", "2", "3", "2", "3", " ", "o", "r", "l", "l", "l", "d", " ", "l", "L", "l", "l", "!"] -->重复字符字符描述X{n,m}匹配包含 n 至 m 个 X 的序列的字符串。X{n,}匹配包含至少 n 个 X 的序列的字符串。X{n}匹配包含 n 个 X 的序列的字符串。X?(有吗?)匹配任何包含零个或一个 X 的字符串 {0,1}X+(加号是追加的意思)匹配任何包含至少一个 X 的字符串 {1,}X*(任意次)匹配任何包含零个或多个 X 的字符串 {0,}1234567891011121314151617181920212223242526272829303132333435363738394041424344var str='Hwwwwlllll orlllld lll!'console.log(str.match(/l{3,5}/))<!-- // ["lllll", index: 5, input: "Hwwwwlllll orlllld lll!"] -->console.log(str.match(/l{2,3}/))<!-- // ["lll", index: 5, input: "Hwwwwlllll orlllld lll!"] -->注:匹配出去l为3、4、5console.log(str.match(/l{0,1}/))<!-- // ["", index: 0, input: "Hwwwwlllll orlllld lll!"] -->console.log(str.match(/l?/))<!-- // ["", index: 0, input: "Hwwwwlllll orlllld lll!"] -->console.log(str.match(/l{1,}/))<!-- // ["lllll", index: 5, input: "Hwwwwlllll orlllld lll!"] -->console.log(str.match(/l+/))<!-- // ["lllll", index: 5, input: "Hwwwwlllll orlllld lll!"] -->var str='Hwwwwwello orllld llll!'console.log(str.match(/l{3,5}/))<!-- // ["lll", index: 13, input: "Hwwwwwello orllld llll!"] -->console.log(str.match(/l{1,4}/))<!-- // ["ll", index: 7, input: "Hwwwwwello orllld llll!"] -->console.log(str.match(/l{2}/))注:匹配两个l<!-- // ["ll", index: 7, input: "Hwwwwwello orllld llll!"] -->console.log(str.match(/l{4,}/))<!-- // ["llll", index: 18, input: "Hwwwwwello orllld llll!"] -->var str='01';console.log(str.match(/0?/));<!-- // ["0", index: 0, input: "01"] -->console.log(str.match(/1?/));<!-- // ["", index: 0, input: "01"] -->注:尽可能少的匹配{0,1}console.log(str.match(/0*/));<!-- // ["0", index: 0, input: "01"] -->console.log(str.match(/1*/));<!-- // ["", index: 0, input: "01"] -->注:{0,}console.log(str.match(/1+/));<!-- // ["1", index: 1, input: "01"] -->注:{1,}非贪婪重复尽可能少的匹配:??、+?、*?、{1,4}?123456789101112131415161718192021222324252627282930313233var str='0111'console.log(str.match(/00?/))<!-- ["0", index: 0, input: "011"] -->console.log(str.match(/01?/))<!-- ["01", index: 0, input: "011"] -->console.log(str.match(/11?/))<!-- ["11", index: 1, input: "011"] -->console.log(str.match(/01+/))<!-- ["0111", index: 0, input: "011"] -->console.log(str.match(/01+?/))<!-- ["01", index: 0, input: "011"] -->注:{1}var str='0111'console.log(str.match(/11??/))<!-- ["1", index: 1, input: "011"] -->console.log(str.match(/01??/))<!-- ["0", index: 0, input: "011"] -->console.log(str.match(/01*/))<!-- ["0111", index: 0, input: "0111"] -->console.log(str.match(/01*?/))<!-- ["0", index: 0, input: "0111"] -->注:?? = *? ==》 {0}var str='0111'console.log(str.match(/1{1,4}?/))<!-- ["1", index: 1, input: "0111"] -->var regex = /\d{2,5}?/g;var string = "123 1234 12345 123456";console.log(string.match(regex));// => ["12", "12", "34", "12", "34", "12", "34", "56"]锚字符字符描述^匹配字符串开头(用正则表达式处理多行时匹配行的开始)$匹配字符串结尾(处理多行时匹配行尾)\b匹配单词边界\B匹配非单词边界(?=p)零宽正向先行断言,要求接下来的字符都与p匹配,但不能包括匹配p的那些字符 (?=p) => p(?!p)零宽正向先行断言,要求接下来的字符不与p匹配 (?!p) => [^p]1234567891011121314151617181920212223242526272829303132333435var str='orllld'console.log(str.match(/^o/))<!-- // ["o", index: 0, input: "orllld"] -->console.log(str.match(/d$/))<!-- // ["d", index: 5, input: "orllld"] -->var str='orllld'<!-- 0o1r2l3l4l5d6 -->console.log(str.replace(/(?=d)/, ','))<!-- // ["", index: 5, input: "orllld"] --><!-- // orlll,d -->var str='orllld 'console.log(str.match(/d$/))<!-- // null -->console.log(str.match(/l(?=d)/))<!-- // ["l", index: 4, input: "orllld "] -->console.log(str.match(/l(?!d)/))<!-- // ["l", index: 2, input: "orllld "] -->var str='JavaScript'console.log(str.match(/Java(Script)([A-Z]\w*)/))<!-- // null -->console.log(str.match(/Java(?=Script)([A-Z]\w*)/))<!-- // ["JavaScript", "Script", index: 0, input: "JavaScript"] -->console.log(str.match(/Java(?=Bcript)([A-Z]\w*)/))<!-- // null -->console.log(str.match(/Java(?!Script)([A-Z]\w*)/))<!-- // null -->console.log(str.match(/Java(?!Bcript)([A-Z]\w*)/))<!-- // ["JavaScript", "Bcript", index: 0, input: "JavaScript"] -->var str='JavaScriptS'console.log(str.match(/Java(Script)([A-Z]\w*)/))<!-- // null -->1234567891011121314151617var str='JavaScriptS'console.log(str.replace(/Java(?!Script)([A-Z]\w*)/, function($0, $1, $2) { return $0 + ',' + $1 + ',' + $2 }))<!-- // JavaScriptS -->var str='JavaSs'console.log(str.match(/Java(?!Script)([A-Z]\w*)/))<!-- // ["JavaSs", "Ss", index: 0, input: "JavaSs"] -->console.log(str.replace(/Java(?!Script)([A-Z]\w*)/, function($0, $1, $2) { return $0 + ',' + $1 + ',' + $2 }))<!-- // JavaSs,Ss,0 -->var str='JavaType'console.log(str.match(/Java(?!Script)([A-Z]\w*)/))<!-- // ["JavaType", "Type", index: 0, input: "JavaType"] -->选择、分组、引用字符字符描述(…)组合,将几个项组合为一个单元,这个单元可通过*、+、?、等符号加以修饰,而且可以记住和这个组合相匹配的字符串以供使用的字符。(?:…)只组合,把项组合到一个单元,但不记住与该组相匹配的字符\n反向引用。比如 \2,表示引用的是第二个括号里的捕获的数据。red|blue|green 查找任何指定red、blue、green的选项。用()表示的就是要提取的分组(Group)^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码1234567891011121314151617181920<!-- 识别合法的时间 -->var re = /^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$/;console.log(re.exec('19:05:30'))<!-- // ["19:05:30", "19", "05", "30", index: 0, input: "19:05:30"] -->console.log(re.exec('25:05:30'))<!-- // null -->var str='JavaScript'console.log(str.match(re))<!-- // null -->var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;<!-- \1 分组序号1 -->var string1 = "2017-06-12";var string2 = "2017/06/12";var string3 = "2017.06.12";var string4 = "2016-06/12";console.log(regex.test(string1)); // trueconsole.log(regex.test(string2)); // trueconsole.log(regex.test(string3)); // trueconsole.log(regex.test(string4)); // false123456789var str='JavaScriptS'console.log(str.replace(/Java(?:Script)([A-Z]\w*)/, function($0, $1) { return $0 + ',' + $1 }))<!-- // JavaScriptS,S,0 -->var str='JavaScript'console.log(str.match(/'a/))<!-- // null -->非捕获性分组1234567891011121314151617181920212223reg = /abc{2}/<!-- // 将匹配abcc -->reg = /(abc){2}/<!-- // 将匹配abcabc --><!-- // 上面的分组都是捕获性分组 -->str = "abcabc ###"console.log(str.match(/(abc){2}/))<!-- // ["abcabc", "abc", index: 0, input: "abcabc ###"] --><!-- // 非捕获性分组 (?:) -->console.log(str.match(/(?:abc){2}/))<!-- // ["abcabc", index: 0, input: "abcabc ###"] -->console.log(str.match(/(?:abc)/))<!-- // ["abc", index: 0, input: "abcabc ###"] -->str = "candy"console.log(str.match(/^(?:can|candy)$/))<!-- // ["candy", index: 0, input: "candy"] -->str = "can"console.log(str.match(/^(?:can|candy)$/))<!-- // ["can", index: 0, input: "can"] -->方法实例方法exec检索字符串中指定的值。返回找到的值,并确定其位置。123456789101112var date = 'Ubuntu 8'reg = /^[a-z]+\s+\d+$/iconsole.log(reg.exec(date))<!-- // ["Ubuntu 8", index: 0, input: "Ubuntu 8"] -->reg = /\d+/console.log(reg.exec(date))<!-- // ["8", index: 7, input: "Ubuntu 8"] -->reg = /o/console.log(reg.exec(date))<!-- // null -->1234567891011121314151617181920var text = "mom and dad baby"var pattern = /mom( and dad( and baby)?)?/givar matches = pattern.exec(text)console.log(text.match(pattern))console.log(matches)<!-- // ["mom and dad", " and dad", undefined, index: 0, input: "mom and dad baby"] -->var text = "mom and dad and baby"var pattern = /mom( and dad( and baby)?)?/giconsole.log(text.match(pattern))<!-- // ["mom and dad and baby"] -->console.log(text.replace(pattern, '($0) ($1) ($2) ($3)'))<!-- // ($0) ( and dad and baby) ( and baby) ($3) --><!-- var text = "mom and dad and baby"; --><!-- // ($0) ( and dad) () ($3) baby -->console.log(text.replace(pattern, function($0, $1, $2, $3) { return $0 + ',' + $1 + ',' + $2 + ',' + $3 }))<!-- // mom and dad and baby, and dad and baby, and baby,0 -->这个例子中的模式包含两个捕获组。最内部的捕获组匹配 "and baby",而包含它的捕获组匹配 "and dad" 或者 "and dad and baby"。当把字符串传入 exec() 方法中之后,发现了一个匹配项。因为整个字符串本身与模式匹配,所以返回的数组 matchs 的 index 属性值为 0。数组中的第一项是匹配的整个字符串,第二项包含与第一个捕获组匹配的内容,第三项包含与第二个捕获组匹配的内容。对于 exec() 方法而言,即使在模式中设置了全局标志 g,它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用 exec() 将始终返回第一个匹配项的信息。而在设置全局标志的情况下,每次调用 exec() 则都会在字符串中继续查找新匹配项,如下面的例子所示。12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849var text = "cat, bat, sat, fat"var pattern1 = /.at/<!-- // 非全局模式,第一次匹配 -->var matches = pattern1.exec(text)<!-- ["cat", index: 0, input: "cat, bat, sat, fat"] -->console.log(matches.index)<!-- // 0 -->console.log(matches[0])<!-- // cat -->console.log(pattern1.lastIndex)<!-- // 0 --><!-- // 非全局模式,第二次匹配 -->matches = pattern1.exec(text)console.log(matches.index)<!-- // 0 -->console.log(matches[0])<!-- // cat -->console.log(pattern1.lastIndex)<!-- // 0 -->var text = "cat, bat, sat, fat"var pattern2 = /.at/g<!-- // 全局模式,第一次匹配 -->var matches = pattern2.exec(text)console.log(matches.index)<!-- // 0 -->console.log(matches[0])<!-- // cat -->console.log(pattern2.lastIndex)<!-- // 0 --><!-- // 全局模式,第二次匹配 -->matches = pattern2.exec(text)console.log(matches.index)<!-- // 5 -->console.log(matches[0])<!-- // bat -->console.log(pattern2.lastIndex)<!-- // 8 -->var text = "cat, bat, sat, fat"var pattern2 = /.at/gconsole.log(pattern2.exec(text))<!-- ["cat", index: 0, input: "cat, bat, sat, fat"] -->console.log(pattern2.exec(text))<!-- ["bat", index: 5, input: "cat, bat, sat, fat"] -->这个例子中的第一个模式 pattern1 不是全局模式,因此每次调用 exec() 返回的都是第一个匹配项 "cat"。而第二个模式 pattern2 是全局模式,因此每次调用 exec() 都会返回字符串中的下一个匹配项,直至搜索到字符串末尾为止。此外,还应该注意模式的 lastIndex 属性的变化情况。在全局匹配模式下,lastIndex 的值在每次调用 exec() 后都会增加,而在非全局模式下则始终保持不变。IE 的 JavaScript 实现在 lastIndex 属性上存在偏差,即使在非全局模式下,lastIndex 属性每次也会变化。正则表达式的第二个方法是 test(),它接受一个字符串参数。在模式与该参数匹配的情况下返回 true;否则,返回 false。在只想知道目标字符串与某个模式是否匹配,但不需要知道其文本内容的情况下,使用这个方法非常方便。因此,test() 方法经常被用在 if 语句中,如下面的例子所示。123456var text = "000-00-0000"var pattern = /\d{3}-\d{2}-\d{4}/if (pattern.test(text)){ console.log("The pattern was matched.")}在这个例子中,我们使用正则表达式来测试了一个数字序列。如果输入的文本与模式匹配,则显示一条消息。这种用法经常出现在验证用户输入的情况下,因为我们只想知道输入是不是有效,至于它为什么无效就无关紧要了。RegExp 实例继承的 toLocaleString() 和 toString() 方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。例如:12345var pattern = new RegExp("\\[bc\\]at", "gi")console.log(pattern.toString())<!-- // /\[bc\]at/gi -->console.log(pattern.toLocaleString())<!-- // /\[bc\]at/gi -->即使上例中的模式是通过调用 RegExp 构造函数创建的,但 toLocaleString() 和 toString() 方法仍然会像它是以字面量形式创建的一样显示其字符串表示。test检索字符串中指定的值。返回 true 或 false。可以修改lastIndex从指定位置开始匹配。123456789101112131415161718192021222324var date = 'Ubuntu 8'var reg = /^[a-z]+\s+\d+$/iconsole.log(reg.test(date))<!-- // true -->var date = '1buntu 8'var reg = /^[a-z]+\s+\d+$/iconsole.log(reg.test(date))<!-- // false -->var regex = /^((\d)(\d(\d)))\1\2\3\4$/;var string = "1431431433";console.log(string.match(regex));<!-- ["1431431433", "143", "1", "43", "3", index: 0, input: "1431431433"] -->console.log(regex.test(string));<!-- // true -->console.log(RegExp.$1);<!-- // 143 -->console.log(RegExp.$2);<!-- // 1 -->console.log(RegExp.$3);<!-- // 43 -->console.log(RegExp.$4);<!-- // 3 -->字符串方法search可在字符串内检索指定的值,或找到一个正则表达式的匹配,得到第一个位置,没有则返回-1123456789101112131415var str='Hello world!'console.log(str.search(/l/))<!-- // 2 -->str='HLelo world!'console.log(str.search(/l/i))<!-- // 1 -->str='Hello world!'console.log(str.search(/l/gi))<!-- // 2 -->str='Hello world!'console.log(str.search(/g/i))<!-- // -1 -->split方法用于把一个字符串分割成字符串数组。1stringObject.split(separator,howmany)separator: 字符串或正则表达式separator: 该参数可指定返回的数组的最大长度参数是字符串转换数组后间隔的参照物,但是有一些复杂的转换就比较麻烦了,这时候我们可以使用正则表达式对字符串进行筛选后再组成注释:如果把空字符串 (“”) 用作 separator,那么 stringObject 中的每个字符之间都会被分割。String.split() 执行的操作与 Array.join 执行的操作是相反的。123456789101112131415161718192021222324252627282930str ="some some \tsome\t\f"console.log(str.split(/\s+/i))<!-- // ["some", "some", "some", ""] -->console.log(str.split(/\s+/g))<!-- // ["some", "some", "some", ""] -->console.log(str.split(/\s/g))<!-- // ["some", "some", "", "", "", "", "", "", "", "", "", "", "", "", "", "some", "", ""] -->a = 'a1b2c3d4'console.log(a.split(/[a-z]+/g))<!-- // ["", "1", "2", "3", "4"] -->str =".how.show.show"console.log(str.split(''))<!-- // [".", "h", "o", "w", ".", "s", "h", "o", "w", ".", "s", "h", "o", "w"] -->str =".how.show.show"console.log(str.split(/\./))<!-- // ["", "how", "show", "show"] -->console.log(str.match(/\./g))<!-- // [".", ".", "."] -->str =".how.sh.show"console.log(str.split(/\./, 2))<!-- // ["", "how"] -->console.log(str.split(/\./, 3))<!-- ["", "how", "sh"] -->match方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置。12stringObject.match(searchvalue)stringObject.match(regexp)123456789101112131415161718192021222324252627282930313233343536检索字母l:index位数input字符串length长度var str='Hello world!'console.log(str.match('l'))<!-- ["l", index: 2, input: "Hello world!"] -->console.log(str.match(/l/i))<!-- ["l", index: 2, input: "Hello world!"] -->正则匹配数字:var str="1 plus 2 equal 3"str.match(/\d+/g)<!-- // ['1','2','3'] -->length长度var str="1 plus 2 equal 3"var reg = /\d+/gstr.match(reg)<!-- ["1", "2", "3"] -->var str = "My name is CJ.Hello everyone!"var re = /[A-Z]/var arr = str.match(re)console.log(arr)<!-- ["M", index: 0, input: "My name is CJ.Hello everyone!"] -->re = /[A-Z]/garr = str.match(re)console.log(arr)<!-- ["M", "C", "J", "H"] -->re = /\b[a-z]*\b/gistr = "on e two three four"str.match(re)<!-- ["on", "", "e", "", "two", "", "three", "", "four", ""] -->replace可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配,并将其替换。值对应match所解读的位置字符描述$n匹配第n个匹配正则表达式中的圆括号子表达式文本$&匹配正则表达式的子串$`匹配子串左边的文本$’匹配子串右边的文本$$匹配美元符号12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273var date = ' Ubuntu 8 'var reg = /(^\s+)|(\s+$)/g<!-- [" ", " "] -->console.log(date.replace(reg, "($')"))<!-- (Ubuntu 8 )Ubuntu 8() -->console.log(date.replace(reg, '($$)'))<!-- ($)Ubuntu 8($) -->console.log(date.replace(reg, '($`)'))<!-- ()Ubuntu 8( Ubuntu 8) -->console.log(date.replace(reg, '($&)'))<!-- ( )Ubuntu 8( ) -->console.log(date.replace(reg, '($0)'))($0)Ubuntu 8($0)console.log(date.replace(reg, '($0) ($1) ($2)'))($0) ( ) ()Ubuntu 8($0) () ( )var date = ' Ubuntu 8 'var reg = /(^\s+)|(\s+$)/gconsole.log(date.match(reg))<!-- [" ", " "] -->console.log(date.replace(reg, function($0, $1, $2){ console.log('$0' + $0) console.log('$1' + $1) console.log('$2' + $2) return ','}))<!-- $0 --><!-- $1 --><!-- $2undefined --><!-- $0 --><!-- $1undefined --><!-- $2 --><!-- ,Ubuntu 8, -->str ="z d l"console.log(str.replace('z', 'f'))<!-- // f d l -->console.log(str.match(/(\w)\s(\w)\s(\w)/))<!-- // ["z d l", "z", "d", "l", index: 0, input: "z d l"] -->console.log(str.replace(/(\w)\s(\w)\s(\w)/, '$0 $3 $2 $1'))<!-- // $0 l d z -->console.log(str.replace(/(\w)\s(\w)\s(\w)/, function($0, $1, $2, $3) { return $0 + ',' + $1 + ',' + $2 + ',' + $3}))<!-- // z d l,z,d,l --><!-- console.log(str.replace(/(\w)\s(\w)\s(\w)/, function($0, $1, $2, $3 ,$& ,$` ,$' ,$$) { return $0 + ',' + $1 + ',' + $2 + ',' + $3 + ',' + $& + ',' + $` + ',' + $' + ',' + $$})); -->let str = '他今年22岁,她今年20岁,他的爸爸今年45岁,她的爸爸今年44岁,一共有4人'let reg = /(\d+)岁/gconsole.log(str.match(reg))<!-- ["22岁", "20岁", "45岁", "44岁"] -->console.log(str.replace(reg, function($0, $1) { console.log($0 + ',' + $1) let gyear = (new Date()).getYear() - parseInt($0) + 1 return $0 + '(' + gyear + '年出生)'}))<!-- 他今年22岁(96年出生),她今年20岁(98年出生),他的爸爸今年45岁(73年出生),她的爸爸今年44岁(74年出生),一共有4人 -->function test($1){ return '<font color="red">' + $1 + '</font>' }var s=prompt('请输入在查找的字符','人')var reg=new RegExp('('+s+')','g')var str='中华人民共和国,中华人民共和国'var newstr=str.replace(reg,test)document.write(newstr + '<br>')1234567891011str ='some some \tsome\t\f'res = /\s+/console.log(str.match(res))<!-- // [" ", index: 4, input: "some some some "] -->console.log(str.replace(res,"#"))<!-- // some#some some -->res = /\s+/gconsole.log(str.match(res))<!-- // [" ", " ", " "] -->console.log(str.replace(res,"@"))<!-- // some@some@some@ -->属性每个实例都具有下列属性,通过这些属性可以取得有关模式的各种信息。实例属性global:布尔值,表示是否设置了 g 标志。ignoreCase:布尔值,表示是否设置了 i 标志。lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0算起。multiline:布尔值,表示是否设置了 m 标志。source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。1234567891011121314151617181920212223var pattern1 = /\[bc\]at/iconsole.log(pattern1.global)<!-- // false -->console.log(pattern1.ignoreCase)<!-- // true -->console.log(pattern1.multiline)<!-- // false -->console.log(pattern1.lastIndex)<!-- // 0 -->console.log(pattern1.source)<!-- // "\[bc\]at" -->var pattern2 = new RegExp("\\[bc\\]at", "i")console.log(pattern2.global)<!-- // false -->console.log(pattern2.ignoreCase)<!-- // true -->console.log(pattern2.multiline)<!-- // false -->console.log(pattern2.lastIndex)<!-- // 0 -->console.log(pattern2.source)<!-- // "\[bc\]at" -->source正则表达式文本123var reg = /[a-z]/ireg.source<!-- // "[a-z]" -->global只读布尔值,是否有修饰符g123var reg = /[a-z]/ireg.global<!-- // false -->ignoreCase只读布尔值,是否有修饰符i123var reg = /[a-z]/ireg.ignoreCase<!-- // true -->multiline只读布尔值,是否有修饰符m123var reg = /[a-z]/ireg.multiline<!-- // false -->lastIndex下一次检索开始的位置,用于exec() 和 test()123456789101112var text = "cat, bat, sat, fat"var pattern1 = /.at/gvar matches = pattern1.exec(text)<!-- ["cat", index: 0, input: "cat, bat, sat, fat"] -->console.log(pattern1.lastIndex)<!-- // 3 -->var text = "cat, bat, sat, fat"var pattern1 = /.at/gvar matches = pattern1.test(text)console.log(pattern1.lastIndex)<!-- // 3 -->构造函数属性RegExp 构造函数包含一些属性(这些属性在其他语言中被看成是静态属性)。这些属性适用于作用域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。关于这些属性的另一个独特之处,就是可以通过两种方式访问它们。换句话说,这些属性分别有一个长属性名和一个短属性名(Opera是例外,它不支持短属性名)。下表列出了RegExp构造函数的属性。长属性名短属性名说明input$_最近一次要匹配的字符串。Opera未实现此属性。lastMatch$&最近一次的匹配项。Opera未实现此属性。lastParen$+最近一次匹配的捕获组。Opera未实现此属性。leftContext$`input字符串中lastMatch之前的文本。multiline$*布尔值,表示是否所有表达式都使用多行模式。IE和Opera未实现此属性。rightContext$’Input字符串中lastMatch之后的文本。使用这些属性可以从 exec() 或 test() 执行的操作中提取出更具体的信息。请看下面的例子。123456789101112131415161718192021var text = "this has been a short summer"var pattern = /(.)hort/g/* * 注意:Internet Explorer 不支持 multiline 属性 * Opera 不支持 input、lastMatch、lastParen 和 multiline 属性 */if (pattern.test(text)){ console.log(RegExp.input) <!-- // this has been a short summer --> console.log(RegExp.leftContext) <!-- // this has been a --> console.log(RegExp.rightContext) <!-- // summer --> console.log(RegExp.lastMatch) <!-- // short --> console.log(RegExp.lastParen) <!-- // s --> console.log(RegExp.multiline) <!-- // false -->}如前所述,例子使用的长属性名都可以用相应的短属性名来代替。只不过,由于这些短属性名大都不是有效的 JavaScript 标识符,因此必须通过方括号语法来访问它们,如下所示。123456789101112131415161718192021var text = "this has been a short summer"var pattern = /(.)hort/g/* * 注意:Internet Explorer 不支持 multiline 属性 * Opera 不支持 input、lastMatch、lastParen 和 multiline 属性 */if (pattern.test(text)){ console.log(RegExp.$_) <!-- // this has been a short summer --> console.log(RegExp["$`"]) <!-- // this has been a --> console.log(RegExp["$'"]) <!-- // summer --> console.log(RegExp["$&"]) <!-- // short --> console.log(RegExp["$+"]) <!-- // s --> console.log(RegExp["$*"]) <!-- // false -->}除了上面介绍的几个属性之外,还有多达9个用于存储捕获组的构造函数属性。访问这些属性的语法是 RegExp.$1、RegExp.$2…RegExp.$9,分别用于存储第一、第二…第九个匹配的捕获组。在调用 exec() 或 test() 方法时,这些属性会被自动填充。然后,我们就可以像下面这样来使用它们。123456789var text = "this has been a short summer"var pattern = /(..)or(.)/gif (pattern.test(text)){ console.log(RegExp.$1) <!-- // sh --> console.log(RegExp.$2) <!-- // t -->}这里创建了一个包含两个捕获组的模式,并用该模式测试了一个字符串。即使 test() 方法只返回一个布尔值,但 RegExp 构造函数的属性 $1 和 $2 也会被匹配相应捕获组的字符串自动填充。模式的局限性尽管 JavaScript 中的正则表达式功能还是比较完备的,但仍然缺少某些语言(特别是 Perl)所支持的高级正则表达式特性。下面列出了 JavaScript 正则表达式所不支持的特性。匹配字符串开始和结尾的\A和\Z锚向后查找(lookbehind)并集和交集类原子组(atomic grouping)Unicode支持(单个字符除外,如\uFFFF)命名的捕获组s(single,单行)和x(free-spacing,无间隔)匹配模式条件匹配正则表达式注释即使存在这些限制,JavaScript 正则表达式仍然是非常强大的,能够帮我们完成绝大多数模式匹配任务。运行原理NFA引擎匹配原理环视(Lookaround)环视只进行子表达式的匹配,不占有字符,匹配到的内容不保存到最终的匹配结果,是零宽度的。环视匹配的最终结果就是一个位置。表达式描述(?<=Expression)逆序肯定环视,表示所在位置左侧能够匹配Expression(?<!Expression)逆序否定环视,表示所在位置左侧不能匹配Expression12345var str = 'aa<p>one</ps>bb<div>two</div>cc'console.log(str.replace(/<(?!\/?p\b)([^>]+)>/g, function($0, $1) { return '(' + $1 + ')' }))<!-- // aa<p>one(/ps)bb(div)two(/div)cc -->回溯法原理正则表达式匹配字符串的这种方式,有个学名,叫回溯法也称试探法123456789没有回溯str = "abbbc"console.log(str.match(/ab{1,3}c/))<!-- // ["abbbc", index: 0, input: "abbc"] -->有回溯str = "abbc"console.log(str.match(/ab{1,3}c/))<!-- // ["abbc", index: 0, input: "abbc"] -->123456789分支结构str = "abbbc"console.log(str.match(/ab{1,3}c/))<!-- // ["abbbc", index: 0, input: "abbc"] -->有回溯str = "abbc"console.log(str.match(/ab{1,3}c/))<!-- // ["abbc", index: 0, input: "abbc"] -->万能的‘正则’比如匹配这样的字符串:1010010001…。 虽然很有规律,但是只靠正则就是无能为力。要认识到正则的局限,不要去研究根本无法完成的任务。同时,也不能走入另一个极端:无所不用正则。能用字符串 API 解决的简单问题,就不该正则出马。日期选取123456789var string = "2017-07-01";var regex = /^(\d{4})-(\d{2})-(\d{2})/;console.log(string.match(regex));// => ["2017-07-01", "2017", "07", "01", index: 0, input: "2017-07-01"]var string = "2017-07-01";var result = string.split("-");console.log(result);// => ["2017", "07", "01"]字符串判断1234567var string = "?id=xx&act=search";console.log(string.search(/\?/));// => 0var string = "?id=xx&act=search";console.log(string.indexOf("?"));// => 0获取子串1234567var string = "JavaScript";console.log(string.match(/.{4}(.+)/)[1]);// => Scriptvar string = "JavaScript";console.log(string.substring(4));// => Script提取数据提取出年、月、日,可以这么做:1234567891011121314151617181920var regex = /(\d{4})-(\d{2})-(\d{2})/;var string = "2017-06-12";console.log(string.match(regex));<!-- // => ["2017-06-12", "2017", "06", "12", index: 0, input: "2017-06-12"] -->var regex = /(\d{4})-(\d{2})-(\d{2})/;var string = "2017-06-12";console.log(regex.exec(string));<!-- // => ["2017-06-12", "2017", "06", "12", index: 0, input: "2017-06-12"] -->var regex = /(\d{4})-(\d{2})-(\d{2})/;var string = "2017-06-12";regex.test(string);<!-- // 正则操作即可,例如 //regex.exec(string); //string.match(regex); -->console.log(RegExp.$1);<!-- // "2017" -->console.log(RegExp.$2);<!-- // "06" -->console.log(RegExp.$3);<!-- // "12" -->替换想把 yyyy-mm-dd 格式,替换成 mm/dd/yyyy 怎么做12345678910111213141516171819202122var regex = /(\d{4})-(\d{2})-(\d{2})/;var string = "2017-06-12";var result = string.replace(regex, "$2/$3/$1");console.log(result);<!-- // => "06/12/2017" -->var regex = /(\d{4})-(\d{2})-(\d{2})/;var string = "2017-06-12";<!-- // => ["2017-06-12", "2017", "06", "12", index: 0, input: "2017-06-12"] -->var result = string.replace(regex, function () {return RegExp.$2 + "/" + RegExp.$3 + "/" + RegExp.$1;});console.log(result);// => "06/12/2017"var regex = /(\d{4})-(\d{2})-(\d{2})/;var string = "2017-06-12";var result = string.replace(regex, function (match, year, month, day) { return month + "/" + day + "/" + year;});console.log(result);// => "06/12/2017"案例分析正则表达式1234567<!-- // 挑战一:数字 -->var pattern1 = null<!-- // 补全该正则表达式 -->console.log(pattern1.test('123'))<!-- // true -->console.log(pattern1.test('abc'))<!-- // false -->1234567<!-- // 挑战二:3位的数字 -->var pattern2 = null<!-- // 补全该正则表达式 -->console.log(pattern2.test('123'))<!-- // true -->console.log(pattern2.test('1234'))<!-- // false -->1234567<!-- // 挑战三:至少3位的数字 -->var pattern3 = null<!-- // 补全该正则表达式 -->console.log(pattern3.test('1234'))<!-- // true -->console.log(pattern3.test('12'))<!-- // false -->1234567<!-- // 挑战四:3-5位的数字 -->var pattern4 = null<!-- // 补全该正则表达式 -->console.log(pattern4.test('1234'))<!-- // true -->console.log(pattern4.test('1'))<!-- // false -->1234567<!-- // 挑战五:由26个英文字母组成的字符串 -->var pattern5 = null<!-- // 补全该正则表达式 -->console.log(pattern5.test('abc'))<!-- // true -->console.log(pattern5.test('1abc'))<!-- // false -->1234567<!-- // 挑战六:由数字和26个英文字母组成的字符串 -->var pattern6 = null<!-- // 补全该正则表达式 -->console.log(pattern6.test('1abc'))<!-- // true -->console.log(pattern6.test('_abc'))<!-- // false -->1234567<!-- // 挑战七:日期格式:年-月-日 -->var pattern7 = null<!-- // 补全该正则表达式 -->console.log(pattern7.test('2016-08-20'))<!-- // true -->console.log(pattern7.test('2016/08/20'))<!-- // false -->1234567<!-- // 挑战八:时间格式:小时:分钟, 24小时制 -->var pattern8 = null<!-- // 补全该正则表达式 -->console.log(pattern8.test('13:45'))<!-- // true -->console.log(pattern8.test('13点45'))<!-- // false -->1234567<!-- // 挑战九:中国大陆身份证号,15位或18位 -->var pattern9 = null<!-- // 补全该正则表达式 -->console.log(pattern9.test('4223222199901090033'))<!-- // true -->console.log(pattern9.test('asdfasdfasfasdf1234'))<!-- // false -->判断匹配整数注:就是像-3,-2,-1,0,1,2,3,10等这样的数。-: 0-1[1-9]: 0-[0-9]: 11234567891011121314151617181920var reg = /^-?[1-9]*\d$/var date = 'Ubuntu 8'console.log(reg.test(date))<!-- false -->date = '213'console.log(reg.test(date))<!-- true -->date = '-213'console.log(reg.test(date))<!-- true -->date = '0'console.log(reg.test(date))<!-- true -->date = '01'console.log(reg.test(date))<!-- false -->date = 0console.log(reg.test(date))<!-- true -->匹配负浮点数注:必须负数,第一位1-9,点后面位随机数字,第一位为0,点后面要有个不为零的数字。12345678910111213141516var reg = /^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$/var date = '-0.00000'console.log(reg.test(date))date = '-0.1231231'console.log(reg.test(date))date = '-1231213.1231231'console.log(reg.test(date))date = '-.1231231'console.log(reg.test(date))date = '-1.0001'console.log(reg.test(date))date = '-1.000'console.log(reg.test(date))date = '-1'console.log(reg.test(date))匹配浮点数注:为了表示更大范围的数据,数学上通常采用科学计数法,把数据表示成一个小数乘以一个以10为底的指数。12345678var reg = /^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$/var date = '0'console.log(reg.test(date))<!-- true -->date = '0.0'console.log(reg.test(date))<!-- true -->123456var reg = /\<(.*?)\>/var date = '<ps>jdfjdsl</ps>'console.log(date.replace(reg, function($0, $1) { return <span>$1</span>}))匹配非负浮点数注:正浮点数 + 0(0.0是浮点数吗?浮点数是什么)1234567891011var reg = /^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$/var date = '0'console.log(reg.test(date))<!-- true -->date = '0.0'console.log(reg.test(date))<!-- true -->date = '.0'console.log(reg.test(date))<!-- true -->匹配非正浮点数注:负浮点数 + 01234567891011var reg = /^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$/var date = '0'console.log(reg.test(date))<!-- true -->date = '0.0'console.log(reg.test(date))<!-- true -->date = '.0'console.log(reg.test(date))<!-- true -->匹配HTML元素1234567var reg = /\<(.*?)\>/gvar date = '<ps>jdfjdsl</ps>dsfds'console.log(date.replace(reg, function ($0, $1) { return '(' + $1 + ')'}))<!-- (ps)jdfjdsl(/ps)dsfds -->验证密码问题密码长度 6-12 位,由数字、小写字符和大写字母组成,但必须至少包括 2 种字符。123456789101112131415161718192021222324252627282930var reg = /^[0-9A-Za-z]{6,12}$/判断是否包含有某一种字符/(?=.*[0-9])^[0-9A-Za-z]{6,12}$/同时包含具体两种字符/(?=.*[0-9])(?=.*[a-z])^[0-9A-Za-z]{6,12}$/同时包含数字和小写字母同时包含数字和大写字母同时包含小写字母和大写字母同时包含数字、小写字母和大写字母var regex = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A- Z]))^[0-9A-Za-z]{6,12}$/console.log(regex.test("1234567") ) // false 全是数字console.log(regex.test("abcdef") ) // false 全是小写字母console.log(regex.test("ABCDEFGH") ) // false 全是大写字母console.log(regex.test("ab23C") ) // false 不足6位console.log(regex.test("ABCDEF234") ) // true 大写字母和数字console.log(regex.test("abcdEF234") ) // true 三者都有“至少包含两种字符”的意思就是说,不能全部都是数字,也不能全部都是小写字母,也不能全部都是大写字母。var regex = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/console.log(regex.test("1234567") ) // false 全是数字console.log(regex.test("abcdef") ) // false 全是小写字母console.log(regex.test("ABCDEFGH") ) // false 全是大写字母console.log(regex.test("ab23C") ) // false 不足6位console.log(regex.test("ABCDEF234") ) // true 大写字母和数字console.log(regex.test("abcdEF234") ) // true 三者都有判断PDF后缀12345var reg = /^.+\.pdf$/ivar date = 'Ubuntu.pdf'console.log(reg.test(date))<!-- true -->匹配中文字符1234567891011var reg = /^[\u4e00-\u9fa5]+$/var date = '京东方s'console.log(reg.test(date))<!-- false -->var date = '京东方'console.log(reg.test(date))<!-- true -->var date = ''console.log(reg.test(date))<!-- false -->两位小数1234567891011121314151617181920<!-- var reg = /^((?:-?0)|(?:-?[1-9]\d*))(?:\.\d{1,2})?$/ -->var reg = /^-?([1-9]\d*\.\d{2}|0\.[1-9]\d)$/var date = '8.12'console.log(reg.test(date))<!-- true -->date = '0.12'console.log(reg.test(date))<!-- true -->date = '-100.12'console.log(reg.test(date))<!-- true -->date = '00.120'console.log(reg.test(date))<!-- false -->date = '1.00'console.log(reg.test(date))<!-- true -->date = '-12.0'console.log(reg.test(date))<!-- false -->至少3位的数字12345678var reg = /^\d{3,}$/var date = '888'console.log(reg.test(date))<!-- // true -->date = '88'console.log(reg.test(date))<!-- // false -->中国邮政编码注:中国邮政编码为6位数字,前两位数字表示省(直辖市,自治区);前三位数字表示邮区;前四位数字表示县(市);最后两位数字表示投递局(所)。1234var reg = /^[1-9]\d{5}$/var date = '223805'console.log(reg.test(date))<!-- // true -->验证帐号是否合法注:字母、数字、下划线组成,字母开头,4-16位。1234var reg = /^[a-zA-z]\w{3,15}$/var date = 'Ubuntu8'console.log(reg.test(date))<!-- // true -->匹配常用正则表达式更复杂的用法,使用子匹配1234567891011121314151617181920212223242526272829<!-- // exec返回的数组第1到n元素中包含的是匹配中出现的任意一个子匹配 -->re=/^[a-z]+\s+(\d+)$/i<!-- // 用()来创建子匹配 -->arr =re.exec(date)console.log(arr[0])<!-- // 整个date,也就是正则表达式的完整匹配 -->console.log(arr[1])<!-- // 8,第一个子匹配,事实也可以这样取出主版本号 -->console.log(arr.length)<!-- // 2 -->date = "Ubuntu 8.10"<!-- // 取出主版本号和次版本号 -->re = /^[a-z]+\s+(\d+)\.(\d+)$/i<!-- // .是正则表达式元字符之一,若要用它的字面意义须转义 -->arr = re.exec(date)console.log(arr[0])<!-- // 完整的date -->console.log(arr[1])<!-- // 8 -->console.log(arr[2])<!-- // 10 -->匹配空行注:匹配空白字符1234567<!-- var 空格 = /[ ]+/g -->var reg = /[\s| ]+/gvar date = ' \r Ubuntu 8 \n 'console.log(date.replace(reg, ','))<!-- ,Ubuntu,8, -->匹配首尾空格注:匹配首空格和尾空格,空格有一个以上,肯能同时存在12345678910111213var reg = /(^\s+)|(\s+$)/gvar date = ' Ubuntu 8 'console.log(date.match(reg))<!-- ["", "", undefined, index: 0, input: "Ubuntu 8 "] -->console.log(date.replace(reg, function($0, $1, $2){ console.log('$0' + $0 + ',') console.log('$1' + $1 + ',') console.log('$2' + $2 + ',') return ','}))console.log(date.replace(reg, ','))m~n位的数字1234var date = '8888'var reg = /^\d{3,5}$/console.log(reg.test(date))<!-- // true -->匹配非负整数注:正确格式为:0 1 9 1001234var date = '011'var reg = /^(0|[1-9][0-9]*)$/console.log(reg.test(date))<!-- // false -->验证一年的12个月注:正确格式为:”01”~”09”和”1”~”12”123var date = '01'var reg = /^(0?[1-9]|1[0-2])$/console.log(reg.test(date))IPV4 地址注:提取ip地址时有用123var date = '192.168.0.1'var reg = /^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])){3}$/console.log(reg.test(date))Email注:12345678910Email : /^\w+([-+.]\w+)*@\w+([-.]\\w+)*\.\w+([-.]\w+)*$/isEmail1 : /^\w+([\.\-]\w+)*\@\w+([\.\-]\w+)*\.\w+$/isEmail2 : /^.*@[^_]*$/var date = '[email protected]'var reg = /^\w+@\w+(\.(com|cn|net|org|edu)){1,2}$/gconsole.log(reg.test(date))var date = '[email protected]'var reg = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/console.log(reg.test(date))验证身份证号第二代身份证号码编排规则注:15位或18位数字(第二代身份证最后一位可能为X)1234var reg = /^(\d{15}|\d{17}[\dxX])$/var date = '32082519640706573X'console.log(reg.test(date))<!-- // true -->Phone手机号码注:只有13、15和18开头的11位手机号码123456var date = '18961856168'var reg = /^((13|18)(\d{9}))$|^(14[57]\d{8})$|^(17[07]\d{8})$|(^15[0-35-9]\d{8}$)/<!-- // var reg = /^[1][358]\d{9}$/; -->console.log(reg.test(date))<!-- // true -->网址注:https、http1234var date = 'https://zhidao.baidu.com/'var reg = /^(http|https):\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/var reg = /^http:// ([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$/console.log(reg.test(date))顶级域名123var date = 'http://zhidao.baidu.com/jdslfjdsf'var reg = /https?:\/\/[^\/]+\/?/console.log(date.match(reg))驼峰化1234567891011121314function camelize (str) { return str.replace(/[-_\s]+(.)?/g, function ($0, $1) { console.log($0) return $1 ? $1.toUpperCase() : '' })}console.log(camelize('-moz-transform'))<!-- MozTransform -->console.log(camelize('font-size'))<!-- fontSize -->console.log(camelize('font-'))<!-- font -->中划线化1234567891011function dasherize (str) { return str.replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();}console.log( dasherize('MozTransform') );<!-- // => "-moz-transform" -->console.log( dasherize('Moz_Transform') );<!-- // => "-moz-transform" -->console.log( dasherize('Moz Transform') );<!-- // => "-moz-transform" -->匹配成对标签1234567var regex = /<([^>]+)>[\d\D]*<\/\1>/;var string1 = "<title>regular expression</title>";var string2 = "<p>laoyao bye bye</p>";var string3 = "<title>wrong!</p>";console.log( regex.test(string1) ); // trueconsole.log( regex.test(string2) ); // trueconsole.log( regex.test(string3) ); // false千位分隔符(js 实现)方法一匹配内容进行替换1234567891011121314151617181920function thousandBitSeparator(num) { return num && Number(num) .toString() .replace(/(\d)(?=(\d{3})+(\.|$))/g, function($0, $1) { return $1 + "," })}console.log(thousandBitSeparator(-1234567.901))<!-- // -1,234,567.901 -->console.log(thousandBitSeparator(-1234567))<!-- // -1,234,567 -->console.log(thousandBitSeparator(0))<!-- // 0 -->console.log(thousandBitSeparator(100000000000))<!-- // 100,000,000,000 -->console.log(thousandBitSeparator(.111))<!-- 0.111 -->console.log(thousandBitSeparator('...'))<!-- NaN -->方法二通过匹配位置来判断123456789101112131415161718192021<!-- 弄出最后一个逗号 -->/(?=\d{3}$)/g// => 12345,678<!-- 弄出所有的逗号 -->/(?=(\d{3})+$)/g// => 12,345,678// => ,123,456,789var string = '12345678 123456789',regex = /(?!\b)(?=(\d{3})+\b)/gvar result = string.replace(regex, ',')console.log(result)// => 12,345,678 123,456,789条件:两位小数的数字 => function format (num) { return num.toFixed(2).replace(/\B(?=(\d{3})+\b)/g, ',').replace(/^/, '$$ ')}console.log(format(1888))// => $ 1,888.00支持2-10位的汉字或数字的正则表达式(还包含汉字和数字混合哦)数字 0-9汉子 \u4e00-\u9fa5:这两个unicode值正好是Unicode表中的汉字的头和尾。1234567var regex = /^([0-9\u4e00-\u9fa5]{2,10})$/;var string1 = "210位的汉字";var string2 = "210";var string3 = "210位的汉字eff";console.log( regex.test(string1) ); // trueconsole.log( regex.test(string2) ); // trueconsole.log( regex.test(string3) ); // false拓展正则基础之——NFA引擎匹配原理正则基础之——环视javascript正则表达式什么是正则表达式?正则表达式的图形工具[精通JS正则表达式](http:// www.cnblogs.com/aaronjs/archive/2012/06/30/2570970.html “newraina”)JAVASCRIPT学习笔记之正则表达式正则表达式30分钟入门教程廖雪峰官网学习可视化图片]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[页面生命周期]]></title>
<url>%2F2018%2F02%2F27%2F2.2.3-DomLifeCycle%2F</url>
<content type="text"><![CDATA[DOMContentLoaded浏览器已经完全加载了HTML,DOM树已经构建完毕,但是像是 和样式表等外部资源可能并没有下载完毕。123document.addEventListener("DOMContentLoaded", function() { console.log('DOMContentLoaded')})DOMContentLoaded 和脚本当浏览器在解析HTML页面时遇到了...标签,将无法继续构建DOM树(译注:UI渲染线程与JS引擎是互斥的,当JS引擎执行时UI线程会被挂起),必须立即执行脚本。所以 DOMContentLoaded 有可能在所有脚本执行完毕后触发。外部脚本(带src的)的加载和解析也会暂停DOM树构建,所以 DOMContentLoaded 也会等待外部脚本。不过有两个例外是带async和defer的外部脚本,他们告诉浏览器继续解析而不需要等待脚本的执行,所以用户可以在脚本加载完成前可以看到页面,有较好的用户体验。async和defer属性仅仅对外部脚本起作用,并且他们在src不存在时会被自动忽略。它们都告诉浏览器继续处理页面上的内容,而在后台加载脚本,然后在脚本加载完毕后再执行。所以脚本不会阻塞DOM树的构建和页面的渲染。其实这里是不对的,带有async和defer的脚本的下载是和HTML的下载与解析是异步的,但是js的执行一定是和UI线程是互斥的,像下面这张图所示,async在下载完毕后的执行会阻塞HTML的解析两处不同asyncdefer带有async的脚本是优先执行先加载完的脚本,他们在页面中的顺序并不影响他们执行的顺序。带有defer的脚本按照他们在页面中出现的顺序依次执行。带有async的脚本也许会在页面没有完全下载完之前就加载,这种情况会在脚本很小或本缓存,并且页面很大的情况下发生。带有defer的脚本会在页面加载和解析完毕后执行,刚好在 DOMContentLoaded之前执行。浏览器的自动补全Firefox, Chrome和Opera会在DOMContentLoaded执行时自动补全表单。例如,如果页面有登录的界面,浏览器记住了该页面的用户名和密码,那么在 DOMContentLoaded运行的时候浏览器会试图自动补全表单(如果用户设置允许)。所以如果DOMContentLoaded被一个需要长时间执行的脚本阻塞,那么自动补全也会等待。你也许见过某些网站(如果你的浏览器开启了自动补全)—— 浏览器并不会立刻补全登录项,而是等到整个页面加载完毕后才填充。这就是因为在等待DOMContentLoaded事件。使用带async和defer的脚本的一个好处就是,他们不会阻塞DOMContentLoaded和浏览器自动补全。(译注:其实执行还是会阻塞的)load附加资源已经加载完毕,可以在此事件触发时获得图像的大小(如果没有被在HTML/CSS中指定)123window.onload = function() { console.log('onload')}readyStatedocument.readyStateloading 加载 - document仍在加载。interactive 互动 - 文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。complete - 文档和所有子资源已完成加载。状态表示 load 事件即将被触发。123456789function work() { console.log('work')}if (document.readyState == 'loading') { document.addEventListener('DOMContentLoaded', work);} else { work();}readystatechange每当文档的加载状态改变的时候就有一个readystatechange事件被触发,所以我们可以打印所有的状态。1document.addEventListener('readystatechange', () => console.log(document.readyState))unloadbeforeunload即将离开页面或者关闭窗口时有些浏览器像Chrome和火狐会忽略返回的字符串取而代之显示浏览器自身的文本,这是为了安全考虑,来保证用户不受到错误信息的误导。需要指出的是,许多浏览器会忽略该事件并自动关闭页面无需用户的确认。火狐浏览器在配置页面about:config设有一个dom.disable_beforeunload的开关变量用于开启这个功能。要重新加载该网站吗?注意:可以通过检查e.clientX、e.clientY判断用户是否点击,右上角关闭浏览器的,但是实践发现 只有 IE6,IE7,IE8 能获取得到具体数值,其他浏览器均为 undefined。要离开此网站吗?12345678910111213141516window.onbeforeunload = function (e) { console.log(e) return 'close'}window.onbeforeunload = function (e) { e = e || window.event; // 兼容IE8和Firefox 4之前的版本 if (e) { e.returnValue = '关闭提示'; } <!-- alert("你取消了离开网页!") --> <!-- Blocked alert('你取消了离开网页!') during beforeunload. --> // Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+ return '关闭提示';};returnValuewindow.onbeforeunload各浏览器对 onbeforeunload 事件的支持与触发条件实现有差异兼容性IE、Chrome、Safari 完美支持Firefox 不支持文字提醒信息Opera 不支持问题IE6,IE7 使用 onbeforeunload 遇到的bug凡是<a>标签 都会触发 onbeforeunload事件 包括 href=”javascript:void(0)” 这种。在IE6,IE7 下面 点击 里面的 a 标签,蛋疼的事情就发生了。解决方法:给这 a标签的 父级 添加 onclick=function(){return false} 即可,不过添加了这个之后 要确保 父级里面没有 input type=”checkbox” 的标签,否则会导致其无效不可点击。判断页面是否关闭123456789101112window.onbeforeunload = function(e) { e = e || window.event; if (e) { e.returnValue = '关闭提示'; } setTimeout(beforeloadResult, 50) return '确认离开网页?'}function beforeloadResult () { localStorage.setItem('beforeloadResult', true) alert("你取消了离开网页!")}思考通过用户触发onbeforeunload,滞后执行beforeloadResult,注入localStorage(如果关闭页面beforeloadResult,将不会执行),用户可以选择取消。由于javascript的阻塞性质,不管我们这个setTimeout设定的时间间隔有多小(太小如0貌似不行),都要等到这个我们把这个alert关闭才会执行。如果我们时间间隔够小,那么一关闭alert就会执行了。问题:onbeforeunload在刷新、关闭页面都和触发,在火狐浏览器下,即使页面关闭了,也依然会执行beforeloadResult();但是并没有暂停脚本执行,没有达到理想的效果。可能是因为网页关闭的时间比 执行 beforeloadResult() 所花的时间要长的原因。创建一个定时任务,这个定时任务的功能是创建另一个定时任务。在另一个定时任务里,定时执行我们的beforeloadResult();这个定时任务开始计算时间的时候,就是我们确定(或取消)关闭网页的时候。123456789101112131415161718192021222324252627282930window.onload = function(e) { if (localStorage.getItem('beforeloadResult')) { // 页面刷新 alert(localStorage.getItem('beforeloadResult')) localStorage.removeItem('beforeloadResult') }}window.onbeforeunload = function(e) { if (localStorage.getItem('beforeloadResult')) { localStorage.removeItem('beforeloadResult') } e = e || window.event // 兼容IE8和Firefox 4之前的版本 if (e) { e.returnValue = '关闭提示' } // 清除localStorage // 火狐浏览器BUG setTimeout(function() { setTimeout(beforeloadResult, 50) }, 50) return '确认离开网页?'}function beforeloadResult () { localStorage.setItem('beforeloadResult', true) console.log(true) alert("你取消了离开网页!")}测试了Chromebefore-unloadbefore-unload不同的条件判断引用onbeforeunload兼容性Firefox (Gecko) >= 1Chrome >= 1Internet Explorer >= 4Opera >= 12Safari (Webkit) >= 3unload浏览器卸载页面后执行的事件(由于种种限制,很少被使用)1234//JS documentwindow.onunload = function() { alert("unload is work")}兼容性IE6,IE7,IE8 中 刷新页面、关闭浏览器之后、页面跳转之后都会执行;IE9 刷新页面 会执行,页面跳转、关闭浏览器不能执行;firefox(包括firefox3.6) 关闭标签之后、页面跳转之后、刷新页面之后能执行,但关闭浏览器不能执行;Safari 刷新页面、页面跳转之后会执行,但关闭浏览器不能执行;Opera、Chrome 任何情况都不执行。]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JavaScript Introduction 简介]]></title>
<url>%2F2018%2F02%2F25%2F1.1-Introduction%2F</url>
<content type="text"><![CDATA[JavaScript是面向Web的编程语言,绝大多数现代网站都使用了JavaScript,并且所有的现代Web浏览器(电脑,手机,平板)均包含了JavaScript解释器。这使得JavaScript能够称得上史上使用最广泛的编程语言。JavaScript也是前端开发工程师必须掌握的三种技能之一:描述网页内容的HTML、描述网页样式的CSS、以及描述网页行为的JavaScript。JavaScript 起源JavaScript 从一个简单的输入验证器发展成为一门强大的编程语言,完全出乎人们的意料。应该说,它既是一门非常简单的语言,又是一门非常复杂的语言。说它简单,是因为学会使用它只需片刻功夫;而说它复杂,是因为要真正掌握它则需要数年时间。语言特性JavaScript是一门动态的、弱类型的、面向对象的、解释型的编程语言,非常适合面向对象和函数式的编程风格。JavaScript的语法来自于Java它的一等函数(first-classfunction)来自于Scheme,它的基于原型(prototype-based)的继承来自于Self。但学习本课程不必去了解那些(Java/Scheme/Slef)语言或熟悉那些术语。优点更少的服务器交互即时反馈给访问者增加互动性丰富的接口脚本语言往往不独立使用,要和HTML/jsp/php/asp/asp.net配合使用,脚本语言有自己的变量、函数、控制语句(顺序、分支、循环)等。编译语言Java程序 === .java → .class(编译) → jvm执行解释性语言JS脚本 → 浏览器(JS引擎解释)区别相比编译语言翻译成机器语言(字节码、二进制码)效率高。JavaScript 实现ECMA欧洲计算机制造商协会(ECMA,European Computer Manufactures Association)定义了名为ECMAScript(发音为 ek-ma-script)的脚本语言标准,它是通用的,与平台无关的语言标准。自此以后,浏览器开发商开始致力于将 ECMAScript 作为各自 JavaScript 实现的基础。虽然基础相同,但具体实现在不同浏览器上却略有差异。组成核心(ECMAScript),由 ECMA-262 定义,提供核心语言功能。文档对象模型(DOM),提供访问和操作网页内容的方法和接口。浏览器对象模型(BOM),提供与浏览器交互的方法和接口。在当前5个主要浏览器(IE、FireFox、Chrome、Safari 和 Opera)中都得到了不同程度的支持。其中,所有浏览器对 ECMAScript 3 版本的支持大体上都还不错,而对 ECMAScript 5 的支持程度越来越高,但对 DOM 的支持则彼此相差比较多。对于已经正式纳入 HTML5 标准的 BOM 来说,尽管各浏览器都实现了某些众所周知的共同特性,但其他特性还是会因浏览器而异。Standard ECMA-262 5.1 EditionECMAScript 5 浏览器兼容一览表ECMAScriptECMAScript 标准由 语法、数据类型、语句、关键字、保留字、运算符、对象 组成。它与 Web 浏览器没有任何依赖关系,并且这门语言本身并不包含输入和输出定义。ECMAScript 定义的只是这门语言的基础,而在此基础之上可以构建更完善的脚本语言。环境Web浏览器只是ECMAScript 实现的宿主环境之一,其他宿主环境包括 Node 和 Adobe Flash。宿主环境不仅提供基本的 ECMAScript 实现,同时也会提供该语言的扩展(例如:DOM、BOM),这些扩展则利用 ECMAScript 的核心类型和语法提供更多更具体的功能。JavaScript 是 Web 浏览器对 ECMAScript 标准的实现,ActionScript 是 Adobe Flash 对 ECMAScript 标准的实现。ECMAScript历史1997年,ECMAScript 1 版发布。1998年6月,ECMAScript 2 版发布。1999年12月,ECMAScript 3 版发布。2000年,ECMAScript 4 开始酝酿,最终这个版本没有通过。2009年12月,ECMAScript 5 版发布。2011年6月,ECMAscript 5.1 版发布,成为国际标准。2015年6月,ECMAScript 6 正式通过,成为国际标准。ECMAScript 2017ECMAScript 6入门ECMAScript 2017注:3.0版是一个巨大的成功,在业界得到广泛支持,成为通行标准,奠定了 JavaScript 语言的基本语法,以后的版本完全继承。直到今天,初学者一开始学习 JavaScript,其实就是在学3.0版的语法。DOM文档对象模型(DOM,Document Object Model)是用于HTML的应用程序编程接口(API),它把整个页面映射为一个多层节点结构。HTML页面中的每个组成部分都是某种类型的节点,这些节点又包含着不同类型的数据。看下面这个HTML页面:123456789<html> <head> <title>Sample Page</title> </head> <body> <h1>h1</h1> <p><span>Hello World!</span></p> </body></html>DOM节点层次图12345678html head meta title body h1 p span通过 DOM 创建的这个表示文档的树形图,开发人员获得了控制页面内容和结构的主动权。借助 DOM 提供的 API,开发人员可以轻松自如地删除、添加、替换或修改任何节点。注:由于Netscape和微软实现的DOM互不兼容,负责制定Web通信标准的W3C(World Wide Web Consortium,万维网联盟)开始着手规划 DOM。DOM1 级DOM 核心:映射文档结构,简化对文档中任意部分的操作和访问。DOM HTML:在 DOM 核心的基础上,添加了针对 HTML 的对象和方法。DOM2 级DOM 视图:定义了跟踪不同文档视图的接口。DOM 事件:定义了事件和事件处理的接口。DOM 样式:定义了基于 CSS 伪元素应用样式的接口。DOM 遍历和范围:定义了遍历和操作文档树的接口。DOM3 级DOM 加载和保存:引入了以统一方式加载和保存文档的方法。DOM 验证:新增了验证文档的方法。DOM 核心扩展。BOM浏览器对象模型(BOM,Browser Object Model)是用于浏览器的应用程序编程接口(API),它把整个浏览器窗口映射为一个对象。从根本上讲,BOM 只处理浏览器窗口和框架,但人们习惯上也把所有针对浏览器的 JavaScript 扩展算作 BOM 的一部分,例如:弹出新浏览器窗口的功能。移动、缩放和关闭浏览器窗口的功能。提供浏览器详细信息的 navigator 对象。提供浏览器所加载页面的详细信息的 localtion 对象。提供用户显示器分辨率详细信息的 screen 对象。对 cookies 的支持。XMLHttpRequest 和 IE 的 ActiveXObject 这样的自定义对象。注:BOM 最让人头疼的是没有相关的规范和标准,每个浏览器都有独有的实现,这个问题在 HTML5 中得到了解决.HTML5 致力于把很多 BOM 功能写入正式规范。]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Git Workflows]]></title>
<url>%2F2017%2F08%2F29%2FGitWorkflows%2F</url>
<content type="text"><![CDATA[概要随着团队不断的壮大,业务流程迭代。代码工作流的规范是显而易见的。为了保证开发速度,我们不断改进完善这个发布流程,让这个过程更简单、高效。这篇指南以大家在SVN中已经广为熟悉使用的集中式工作流作为起点,循序渐进地演进到其它高效的分布式工作流,还介绍了如何配合使用便利的Pull Request功能,体系地讲解了各种工作流的应用。在阅读过程中,请记住这些工作流是指导原则,而不是具体规则。我们想向您展示什么是可能的,因此您可以混合和匹配来自不同工作流的方面,以满足您的个人需求。常见问题:我们以使用SVN的工作流来使用Git有什么不妥?如何控制开发版本?Git方便的branch在哪里,团队多人如何协作?冲突了怎么办?如何进行发布控制?经典的master-发布、develop-主开发、hotfix-bug修复如何避免代码不经过验证上线?如何在GitHub上面与他人一起协作,star-fork-pull request是怎样的流程?集中式工作流集中式工作流以中央仓库作为项目所有修改的单点实体。相比 SVN 缺省的开发分支 trunk ,Git 叫做master,所有修改提交到这个分支上。本工作流只用到 master 这一个分支。工作方式要发布修改到正式项目中,开发者要把本地 master 分支的修改『推』到中央仓库中。这相当于 svn commit 操作,但 push 操作会把所有还不在中央仓库的本地提交都推上去。Gitflow工作流Gitflow工作流通过为功能开发、发布准备和维护分配独立的分支,让发布迭代过程更流畅。严格的分支模型也为大型项目提供了一些非常必要的结构。特点健壮的用于管理大型项目的框架分支分配明确功能分支,在做准备、维护和记录发布也使用各自的分支工作方式Gitflow工作流仍然用中央仓库作为所有开发者的交互中心。和其它的工作流一样,开发者在本地工作并push分支到要中央仓库中。分支命名:master版本、develop开发、release-*发布、feature-*功能、hotfix-*修复特点1234567├── master ├── hotfix-* ├── release-* ├── develop ├── hotfix-* ├── release-* ├── feature-*master版本分支正式发布历史分支:用于管理发布的版本,发布Tagdevelop开发分支功能的集成分支:用于开发项目feature功能分支功能分支:每个新功能位于一个自己的分支,这样可以push到中央仓库以备份和协作。新功能提交应该从不直接与master分支交互,案例小红和小明开始各自的功能开发。他们需要为各自的功能创建相应的分支。新分支不是基于master分支,而是应该基于develop分支进行开发创建feature分支12345678910<!-- develop分支 -->$ git checkout develop<!-- 创建dev分支并切换 -->$ git checkout -b feature-devSwitched to branch 'feature-dev'=><!-- 以develop创建dev分支并切换 -->git checkout -b feature-dev develop编辑、暂存、提交123456$ git status$ git add$ git commit -m "branch"[feature-dev fec145a] branch 1 file changed, 1 insertion(+)$ git push完成合并12345678910<!-- 拉取develop代码并合并 -->$ git pull origin develop$ git checkout develop<!-- 合并指定分支到feature-dev分支 -->$ git merge feature-dev$ git push<!-- 删除分支 -->$ git branch -d feature-devrelease发布分支发布分支:用于发布准备的专门分支。一旦develop分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从develop分支上fork一个发布分支。新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上 —— 这个分支只应该做Bug修复、文档生成和其它面向发布任务。一旦对外发布的工作都完成了,发布分支合并到master分支并分配一个版本号打好Tag。另外,这些从新建发布分支以来的做的修改要合并回develop分支。hotfixes修复分支维护分支:用于生成快速给产品发布版本。这是唯一可以直接从master分支fork出来的分支。修复完成,修改应该马上合并回master分支和develop分支(当前的发布分支),master分支应该用新的版本号打好Tag。Gitflow 工作流没有用超出功能分支工作流的概念和命令,而是为不同的分支分配一个很明确的角色,并定义分支之间如何和什么时候进行交互。 除了使用功能分支,在做准备、维护和记录发布也使用各自的分支。 当然你可以用上功能分支工作流所有的好处:Pull Requests 、隔离实验性开发和更高效的协作。Forking工作流Forking工作流是分布式工作流,充分利用了Git在分支和克隆上的优势。可以安全可靠地管理大团队的开发者(developer),并能接受不信任贡献者(contributor)的提交。冲突解决大幅度Git工作流指南:Gitflow工作流Comparing Workflows拓展Git 工作流指南A successful Git branching model改进合作 Git 工作流:自动提取、合并提交Comparing Workflowsmy-git]]></content>
<categories>
<category>Tool</category>
</categories>
<tags>
<tag>Git</tag>
</tags>
</entry>
<entry>
<title><![CDATA[JavaScript FirstExploration 初探]]></title>
<url>%2F2017%2F08%2F25%2F1.2-FirstExploration%2F</url>
<content type="text"><![CDATA[当学习一门新的编程语言的时候,应该边学边做,反复演练以加深理解。因此,你需要一个 JavaScript 解释器。幸运的是,每一个 Web 浏览器都包含一个 JavaScript 解释器。注:现代浏览器可以使用函数 console.log() 来向控制台输出消息,通过这种方式可以非常方便地调试代码。引入方式三种加载时间不同1234567891011121、头部:在<head>区域中,在页面被载入之前,脚本已经载入,准备好被调用。(放置:函数代码)<script type="text/javascript"></script>2、内部:在<body>区域中,在页面载入时,脚本被载入并立即执行。放置函数不会立即执行,只用调用时才执行,而且必须脚本成功加载完成之后,才能正确调用函数。<script type="text/javascript"></script>3、外部:在外部引用JavaScript,以.js为扩展名的文件中,在HTML页面中链接到这个脚本文件,不同的位置决定加载时机。<script type="text/javascript" src="xxx.js"></script>4、输出JavaScript通常用来操作HTML,文档输出:document.write("<p>this is my first JavaScript</p>");案例123456789101112131415161718<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>javascript-lesson-1.2</title> <link rel="stylesheet" href="http://qiniu.shijiajie.com/blog/javascript-lesson/1.2/layer.css"> <!-- 开启页面加载效果 --> <script src="http://qiniu.shijiajie.com/blog/javascript-lesson/1.2/layer.js"></script> <script>layer.open({ type: 2, shadeClose: false });</script> <!-- 关闭页面加载效果 --> <script>setTimeout(function(){ layer.closeAll(); },500);</script> <!-- 引入 10MB 外部 JavaScript,比较耗时 --> <script src="http://qiniu.shijiajie.com/blog/javascript-lesson/1.2/external.js"></script></head><body> 本页面用来测试 &lt;script&gt; 加载顺序~</body></html>挑战一实现打开页面就能看到网页内容「本页面用来测试 <script> 加载顺序~」,不必等外部 JavaScript 文件全部下载完毕才显示。123456789101112131415161718<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>javascript-lesson-1.2</title> <link rel="stylesheet" href="http://qiniu.shijiajie.com/blog/javascript-lesson/1.2/layer.css"></head><body> <!-- 开启页面加载效果 --> <script src="http://qiniu.shijiajie.com/blog/javascript-lesson/1.2/layer.js"></script> <script>layer.open({ type: 2, shadeClose: false });</script> 本页面用来测试 &lt;script&gt; 加载顺序~ <!-- 关闭页面加载效果 --> <script>setTimeout(function(){ layer.closeAll(); },500);</script> <!-- 引入 10MB 外部 JavaScript,比较耗时 --> <script src="http://qiniu.shijiajie.com/blog/javascript-lesson/1.2/external.js"></script></body></html>属性src可选。表示包含要执行代码的外部文件。type可选。可以看成是language 的替代属性;表示编写代码使用的脚本语言的内容类型(也称为MIME 类型)。虽然text/javascript 和text/ecmascript 都已经不被推荐使用,但人们一直以来使用的都还是text/javascript。实际上,服务器在传送JavaScript 文件时使用的MIME 类型通常是application/x–javascript,但在type 中设置这个值却可能导致脚本被忽略。另外,在非IE浏览器中还可以使用以下值:application/javascript 和application/async可选。立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本。只对外部脚本文件有效。charset可选。表示通过src 属性指定的代码的字符集。由于大多数浏览器会忽略它的值,因此这个属性很少有人用。defer可选。脚本可延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。IE7 及更早版本对嵌入脚本也支持这个属性。language(已废弃)原来用于表示编写代码使用的脚本语言(如JavaScript、JavaScript1.2或VBScript)。大多数浏览器会忽略这个属性,因此也没有必要再用了。注:在 HTML5 规范中,<script> 的 type 属性默认是 “text/javascript”,所以可以省略;但是在 HTML 4.01 和 XHTML 1.0 规范中,type 属性是必须的。可以参考 Stack Overflow 上的回答:stackoverflow]]></content>
<categories>
<category>JavaScript</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Git速查手册]]></title>
<url>%2F2017%2F08%2F19%2FGit%2F</url>
<content type="text"><![CDATA[安装Linux打开控制台,然后通过包管理安装,在Ubuntu上命令是:1sudo apt-get install git-allWindows推荐使用git forwindows,它包括了图形工具以及命令行模拟器。OS X最简单的方式是使用homebrew安装,命令行执行1brew install git如果你是在是先用图形工具的话,那么推荐你使用Github desktop,Sourcetree。但我还是推荐你使用命令行,下面的内容就都是命令行的。Git 术语术语定义仓库(Repository)一个仓库包括了所有的版本信息、所有的分支和标记信息。在Git中仓库的每份拷贝都是完整的。仓库让你可以从中取得你的工作副本。分支(Branches)一个分支意味着一个独立的、拥有自己历史信息的代码线(code line)。你可以从已有的代码中生成一个新的分支,这个分支与剩余的分支完全独立。默认的分支往往是叫master。用户可以选择一个分支,选择一个分支执行命令git checkout branch.标记(Tags)一个标记指的是某个分支某个特定时间点的状态。通过标记,可以很方便的切换到标记时的状态,例如2009年1月25号在testing分支上的代码状态提交(Commit)提交代码后,仓库会创建一个新的版本。这个版本可以在后续被重新获得。每次提交都包括作者和提交者,作者和提交者可以是不同的人修订(Revision)用来表示代码的一个版本状态。Git通过用SHA1 hash算法表示的id来标识不同的版本。每一个 SHA1 id都是160位长,16进制标识的字符串.。最新的版本可以通过HEAD来获取。之前的版本可以通过”HEAD~1”来获取,以此类推。创建新建仓库12345<!-- 在当前目录新建一个Git代码库 -->$ git init<!-- 新建一个目录,将其初始化为Git代码库 -->$ git init [project-name]复制远程仓库12<!-- 下载一个项目和它的整个代码历史 -->$ git clone [url]配置配置账号信息Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。123456789<!-- 设置提交代码时的用户信息 -->$ git config --global user.name "My Name"$ git config --global user.email [email protected]<!-- 显示仓库的Git配置 -->$ git config --list<!-- 编辑Git配置文件 -->$ git config -e [--global]配置好这两项,用户就能知道谁做了什么,并且一切都更有组织性了不是吗?生成SSH秘钥用于上传到你对应的github账号12345678$ ssh-keygen -t rsa -C "[email protected]"<!-- 这的密码不是我们GitHub的密码,而是Git SSH的密码 --><!-- 打开Git生成的密码文件,将其复制到GitHub上 -->$ vim ~/.ssh/id_rsa.pub<!-- 验证GitHub SSH是否成功 -->$ ssh -T [email protected]案例提交流程12345$ git pull$ git start$ git add$ git commit -m ""$ git push修改与提交修改123456789101112131415161718192021<!-- 添加指定文件到暂存区 -->$ git add [file1] [file2] ...<!-- 添加指定目录到暂存区,包括子目录 -->$ git add [dir]<!-- 添加当前目录的所有文件到暂存区 -->$ git add .<!-- 添加每个变化前,都会要求确认 --><!-- 对于同一个文件的多处变化,可以实现分次提交 -->$ git add -p<!-- 删除工作区文件,并且将这次删除放入暂存区 -->$ git rm [file1] [file2] <!-- 停止追踪指定文件,但该文件会保留在工作区 -->$ git rm --cached [file]<!-- 改名文件,并且将这个改名放入暂存区 -->$ git mv [file-original] [file-renamed]提交123456789101112131415161718<!-- 提交暂存区到仓库区 -->$ git commit -m [message]<!-- 提交暂存区的指定文件到仓库区 -->$ git commit [file1] [file2] ... -m [message]<!-- 提交工作区自上次commit之后的变化,直接到仓库区 -->$ git commit -a<!-- 提交时显示所有diff信息 -->$ git commit -v<!-- 使用一次新的commit,替代上一次提交 --><!-- 如果代码没有任何新变化,则用来改写上一次commit的提交信息 -->$ git commit --amend -m [message]<!-- 重做上一次commit,并包括指定文件的新变化 -->$ git commit --amend [file1] [file2]分支与标签分支123456789101112131415161718192021222324252627282930313233343536373839404142<!-- 列出所有本地分支 -->$ git branch<!-- 列出所有远程分支 -->$ git branch -r<!-- 列出所有本地分支和远程分支 -->$ git branch -a<!-- 新建一个分支,但依然停留在当前分支 -->$ git branch [branch-name]<!-- 新建一个分支,并切换到该分支 -->$ git checkout -b [branch]<!-- 新建一个分支,指向指定commit -->$ git branch [branch] [commit]<!-- 新建一个分支,与指定的远程分支建立追踪关系 -->$ git branch --track [branch] [remote-branch]<!-- 切换到指定分支,并更新工作区 -->$ git checkout [branch-name]<!-- 切换到上一个分支 -->$ git checkout -<!-- 建立追踪关系,在现有分支与指定的远程分支之间 -->$ git branch --set-upstream [branch] [remote-branch]<!-- 合并指定分支到当前分支 -->$ git merge [branch]<!-- 选择一个commit,合并进当前分支 -->$ git cherry-pick [commit]<!-- 删除分支 -->$ git branch -d [branch-name]<!-- 删除远程分支 -->$ git push origin --delete [branch-name]$ git branch -dr [remote/branch]标签1234567891011121314151617181920212223242526<!-- 列出所有tag -->$ git tag<!-- 新建一个tag在当前commit -->$ git tag [tag]<!-- 新建一个tag在指定commit -->$ git tag [tag] [commit]<!-- 删除本地tag -->$ git tag -d [tag]<!-- 删除远程tag -->$ git push origin :refs/tags/[tagName]<!-- 查看tag信息 -->$ git show [tag]<!-- 提交指定tag -->$ git push [remote] [tag]<!-- 提交所有tag -->$ git push [remote] --tags<!-- 新建一个分支,指向某个tag -->$ git checkout -b [branch] [tag]查看信息123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263<!-- 显示有变更的文件 -->$ git status<!-- 显示当前分支的版本历史 -->$ git log<!-- 显示commit历史,以及每次commit发生变更的文件 -->$ git log --stat<!-- 搜索提交历史,根据关键词 -->$ git log -S [keyword]<!-- 显示某个commit之后的所有变动,每个commit占据一行 -->$ git log [tag] HEAD --pretty=format:%s<!-- 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件 -->$ git log [tag] HEAD --grep feature<!-- 显示某个文件的版本历史,包括文件改名 -->$ git log --follow [file]$ git whatchanged [file]<!-- 显示指定文件相关的每一次diff -->$ git log -p [file]<!-- 显示1行日志 -n为n行 -->$ git log -5<!-- 显示过去5次提交 -->$ git log -5 --pretty --oneline<!-- 显示所有提交过的用户,按提交次数排序 -->$ git shortlog -sn<!-- 显示指定文件是什么人在什么时间修改过 -->$ git blame [file]<!-- 显示暂存区和工作区的差异 -->$ git diff<!-- 显示暂存区和上一个commit的差异 -->$ git diff --cached [file]<!-- 显示工作区与当前分支最新commit之间的差异 -->$ git diff HEAD<!-- 显示两次提交之间的差异 -->$ git diff [first-branch]...[second-branch]<!-- 显示今天你写了多少行代码 -->$ git diff --shortstat "@{0 day ago}"<!-- 显示某次提交的元数据和内容变化 -->$ git show [commit]<!-- 显示某次提交发生变化的文件 -->$ git show --name-only [commit]<!-- 显示某次提交时,某个文件的内容 -->$ git show [commit]:[filename]<!-- 显示当前分支的最近几次提交 -->$ git reflog远程同步12345678910111213141516171819202122232425<!-- 下载远程仓库的所有变动 -->$ git fetch [remote]<!-- 显示所有远程仓库 -->$ git remote -v<!-- 显示某个远程仓库的信息 -->$ git remote show [remote]<!-- 增加一个新的远程仓库,并命名 -->$ git remote add [shortname] [url]git pull <远程主机名(origin)> <远程分支名>:<本地分支名><!-- 取回远程仓库的变化,并与本地分支合并 -->$ git pull [remote] [branch]<!-- 上传本地指定分支到远程仓库 -->$ git push [remote] [branch]<!-- 强行推送当前分支到远程仓库,即使有冲突 -->$ git push [remote] --force<!-- 推送所有分支到远程仓库 -->$ git push [remote] --all撤销12345678910111213141516171819202122232425262728293031<!-- 恢复暂存区的指定文件到工作区 -->$ git checkout [file]<!-- 恢复某个commit的指定文件到暂存区和工作区 -->$ git checkout [commit] [file]<!-- 恢复暂存区的所有文件到工作区 -->$ git checkout .<!-- 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变 -->$ git reset [file]<!-- 重置暂存区与工作区,与上一次commit保持一致 -->$ git reset --hard<!-- 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变 -->$ git reset [commit]<!-- 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致 -->$ git reset --hard [commit]<!-- 重置当前HEAD为指定commit,但保持暂存区和工作区不变 -->$ git reset --keep [commit]<!-- 新建一个commit,用来撤销指定commit --><!-- 后者的所有变化都将被前者抵消,并且应用到当前分支 -->$ git revert [commit]<!-- 暂时将未提交的变化移除,稍后再移入 -->$ git stash$ git stash pop其他12<!-- 生成一个可供发布的压缩包 -->$ git archive拓展my-git廖雪峰Git教程Git-it - GitHubLearn Git Branchinggithub快速入门git - 简明指南用 Git 钩子进行简单自动部署git-recipes专为设计师而写的GitHub快速入门教程工作流Git 工作流Comparing WorkflowsGit工作流指南:Gitflow工作流A successful Git branching model改进合作 Git 工作流:自动提取、合并提交速查表Git索引Git指令速查表图解猴子都能懂的Git入门图解Git]]></content>
<categories>
<category>Tool</category>
</categories>
<tags>
<tag>Git</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue知识点总结]]></title>
<url>%2F2017%2F08%2F18%2FVueBater%2F</url>
<content type="text"><![CDATA[****文章适合有一定vue经验,只是简单介绍项目中的搭建与开发的优化之处。知识点,请自行查阅!生命周期顺序Vue 2.*beforeCreate 组件实例创建属性计算之前created 组件实例创建,属性绑定,DOM还未beforeMount 模板挂载之前mounted 模板挂载之后beforeUpdate 组件更新之前updated 组件更新之后activated 组件激活deactivated 组件移除beforeDestory 组件销毁之前destoryed 组件销毁之后组件通信父传子用props,父用子用ref 子调父用$emit,无关系用BusVuex]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[深入Sass]]></title>
<url>%2F2017%2F08%2F18%2FInduceSass%2F</url>
<content type="text"><![CDATA[SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护。你可以用它开发网页样式,但是没法用它编程。也就是说,CSS基本上是设计师的工具,不是程序员的工具。在程序员眼里,CSS是一件很麻烦的东西。它没有变量,也没有条件语句,只是一行行单纯的描述,写起来相当费事。基础变量与选择器变量变量的定义一般以$开头,某个变量的作用域仅限于他们定义的层级以及子层级。如果变量是定义在所有嵌套选择器之外的,那么他们可以在各处被调用。1234$color1: #aeaeae;.div1{ background-color: $color1;}1234.div1 { background-color: #aeaeae;}<!-- /*# sourceMappingURL=test.css.map */ -->变量的作用域如果希望某个在子选择器中定义的变量能够成为全局变量,可以使用!global关键字:12345678#main { $width: 5em !global; width: $width;}#sidebar { width: $width;}嵌套引用1234567$side: top;$radius: 10px;.round-#{$side} { border-#{$side}-radius: $radius; -moz-border-#{$side}-radius: $radius; -webkit-border-#{$side}-radiux: $radius;}12345.round-top { border-top-radius: 10px; -moz-border-top-radius: 10px; -webkit-border-top-radiux: 10px;}变量计算1234$left: 20px;.div1{ margin-left:$left+12px;}计算的类型123456789101112131415p { <!-- Plain CSS, no division --> font: 10px/8px; $width: 1000px; <!-- Uses a variable, does division --> width: $width/2; <!-- Uses a function, does division --> width: round(1.5)/2; <!-- Uses parentheses, does division --> height: (500px/2); <!-- Uses +, does division --> margin-left: 5px + 8px/2px; <!-- In a list, parentheses don't count --> font: (italic bold 10px/8px);}选择器嵌套12345678.div1{ .span1{ height: 12px; } .div2{ width: 16px; }}12345p{ border:{ color: red; }}注意: border后面必须加上冒号父元素引用允许使用&引用父元素12345.div1{ &:hover{ cursor: hand; }}代码重用继承SASS允许一个选择器,继承另一个选择器。1234567.class1{ font-size:19px;}.class2{ @extend .class1; color:black;}123456.class1, .class2 { font-size:19px;}.class2 { color:black;}注意:如果在class2后面有设置了class1的属性,那么也会影响class212345678910.class1{ font-size:19px;}.class2{ @extend .class1; color:black;}.class1{ font-weight:bold;}占位符1234567%class1{ font-size:19px;}.class2{ @extend %class1; color:black;}1234.class2{ font-size:19px; color:black;}引用外部123@import "_test1.scss";@import "_test2.scss";@import "_test3.scss";Mixin&IncludeMixin是SASS中非常强大的特性之一。定义mixin时,需要在前面加@mixin,使用时需要添加@include来引用该mixin。12345678@mixin left { float: left; margin-left: 10px;}div { @include left;}1234div { float: left; margin-left: 10px;}边距设置12345678910111213141516@mixin common($value1,$value2,$defaultValue:12px) { display:block; margin-left:$value1; margin-right:$value2; padding:$defaultValue;}.class1 { font-size:16px; @include common(12px,13px,15px);}.class2 { font-size:16px; @include common(12px,13px);}浏览器前缀设置123456789101112@mixin rounded($vert, $horz, $radius: 10px) { border-#{$vert}-#{$horz}-radius: $radius; -moz-border-radius-#{$vert}#{$horz}: $radius; -webkit-border-#{$vert}-#{$horz}-radius: $radius;}#navbar li { @include rounded(top, left);}#footer { @include rounded(top, left, 5px);}编程式方法流程控制条件语句@if12345678p { @if 1 + 1 == 2 { border: 1px solid; } @if 5 < 3 { border: 2px dotted; }}@else12345@if lightness($color) > 30% { background-color: #000;} @else { background-color: #fff;}循环语句for循环12345@for $i from 1 to 5 { .border-#{$i} { border: #{$i}px solid blue; }}12345678910111213141516171819/* line 149, ../sass/style.scss */.border-1 { border: 1px solid blue;}/* line 149, ../sass/style.scss */.border-2 { border: 2px solid blue;}/* line 149, ../sass/style.scss */.border-3 { border: 3px solid blue;}/* line 149, ../sass/style.scss */.border-4 { border: 4px solid blue;}while循环12345$i: 1;@while $i < 5 { .border-#{$i} { border: #{$i}px solid blue; } $i: $i + 1;}12345678910111213141516171819/* line 156, ../sass/style.scss */.border-1 { border: 1px solid blue;}/* line 156, ../sass/style.scss */.border-2 { border: 2px solid blue;}/* line 156, ../sass/style.scss */.border-3 { border: 3px solid blue;}/* line 156, ../sass/style.scss */.border-4 { border: 4px solid blue;}each命令,作用与for类似12345@each $item in add, update, remove, share { .icon-#{$item} { background-image: url("/image/#{$item}.jpg"); }}12345678910111213141516171819/* line 161, ../sass/style.scss */.icon-add { background-image: url("/image/add.jpg");}/* line 161, ../sass/style.scss */.icon-update { background-image: url("/image/update.jpg");}/* line 161, ../sass/style.scss */.icon-remove { background-image: url("/image/remove.jpg");}/* line 161, ../sass/style.scss */.icon-share { background-image: url("/image/share.jpg");}函数1234567@function double($n) { @return $n * 2;}#sidebar { width: double(5px);}123#navbar { width: 10px;}颜色函数SASS提供了一些内置的颜色函数,以便生成系列颜色。1234567891011lighten(#cc3, 10%)// #d6d65cdarken(#cc3, 10%)// #a3a329grayscale(#cc3)// #808080complement(#cc3)// #33c拓展Sass 与 SCSS 是什么关系sass受Haml简洁启发,Ruby的语法,没有花括号,没有分号,具有严格的缩进Sass 从来没有大写过,无论你指的是语法或者这个语言。同时, SCSS 一直是大写的。甚至有一个网站专门来提醒你这件事!.sass1234$def-color: #333body font: 100% color: $def-color.scss12345$def-color: #333body{ font: 100%; color: $def-color;}使用Sass之更高级的媒体查询1234567/ _config.scss$breakpoints: ( 'xs': 'only screen and ( min-width: 480px)', 'sm': 'only screen and ( min-width: 768px)', 'md': 'only screen and ( min-width: 992px)', 'lg': 'only screen and ( min-width: 1200px)',) !default;1234567891011// _mixins.scss@mixin respond-to($breakpoint) { $query: map-get($breakpoints, $breakpoint); @if not $query { @error 'No value found for `#{$breakpoint}`. Please make sure it is defined in `$breakpoints` map.'; } @media #{if(type-of($query) == 'string', unquote($query), inspect($query))} { @content; }}使用1234567// _component.scss.element { color: hotpink; @include respond-to(sm) { color: tomato; }}输出12345678.element { color: hotpink;}@media (min-width: 768px) { .element { color: tomato; }}巧用SASS之如何遍历n个子元素并为其设置属性1234567891011<div id="main-container"> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> </ul></div>1234567891011121314151617181920212223242526// 将背景颜色值定义成变量$red : #FF0000;$orange : #FFA500;$yellow : #FFFF00;$green : #008000;$bluegreen : #00FFFF;$blue : #0000FF;$purple : #800080;//将背景颜色以键值对的形式存在map中$bgcolorlist : ( 1: $red, 2: $orange, 3: $yellow, 4: $green, 5: $bluegreen, 6: $blue, 7: $purple);// 使用SASS each语法为每一个li设置background-color@each $i, $color in $bgcolorlist { #main-container ul li:nth-child(#{$i}) { background-color: $color; }}设置rem,控制width12345@function size($size) { $width: 375; $scale: 10; @return ($size / $width * $scale) * 1rem;}sass入门sass使用Sass之更高级的媒体查询学习SASS笔记巧用SASS之如何遍历n个子元素并为其设置属性几个实用的Sass mixinssass-svg 一个内联 SVG 的 SASS 库跟随动画的高效实现方法:GreenSock 和 Web Animations API]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>Sass</tag>
</tags>
</entry>
<entry>
<title><![CDATA[CSS低频属性]]></title>
<url>%2F2017%2F08%2F18%2FCssLowFrequency%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why概况安卓文字垂直居中由于安卓无法通过height height-line首行缩进1text-indent: 25px;字母不换行word-wrap: break-word;文字省略通过CSS判断,这个区域宽度省略1234<!-- 单行文本溢出 -->text-overflow: ellipsis;white-space: nowrap;overflow: hidden;一行省略1234567<!-- 多行文本溢出 -->display: -webkit-box !important;overflow: hidden;text-overflow: ellipsis;word-break: break-all;-webkit-box-orient: vertical;-webkit-line-clamp: 2;首字母大写1text-transform: capitalize;值描述none默认。定义带有小写字母和大写字母的标准的文本。capitalize文本中的每个单词以大写字母开头。uppercase定义仅有大写字母。lowercase定义无大写字母,仅有小写字母。inherit规定应该从父元素继承 text-transform 属性的值。will-change提高页面滚动、动画等渲染性能元素可以点透1pointer-events: none;移动端手机input输入内容自动移动该效果只限于IOS,ando1filter: blur(-3px);-webkit-text-size-adjust(失效)当样式表里font-size<12px时,中文版chrome浏览器里字体显示仍为12px,这时可以用 html{-webkit-text-size-adjust:none;}-webkit-text-size-adjust放在body上会导致页面缩放失效body会继承定义在html的样式用-webkit-text-size-adjust不要定义成可继承的或全局的1-webkit-text-size-adjust: none;以显示 10px 的字为例123456789.some-small-font { display: inline-block; /* Or block */ font-size: 12.5px; -webkit-transform: scale(0.8); transform: scale(0.8); position: relative; left: -12.5%; width: 125%;}输入框选择时无边框1outline: none;可点击的元素时,覆盖显示的高亮颜色1-webkit-tap-highlight-color: rgba(0,0,0,0);修改chrome记住密码后自动填充表单的背景颜色12345input:-webkit-autofill, textarea:-webkit-autofill, select-webkit-autofill{ background-color: #FFF; background-image: none; color: #000;}弹窗背景模糊原理:使用高斯模糊,使得页面显示元素模糊,将样式加在body上,通过body的class实现的。row为指定要模糊的内容12345678910body { -webkit-backface-visibility: hidden;}.modal-active .row { -webkit-filter: blur(3px); -moz-filter: blur(3px); -o-filter: blur(3px); -ms-filter: blur(3px); filter: blur(3px);}CSS3 filter 模糊滤镜如何将网页CSS背景图高斯模糊且全屏显示微信二维码无法识别微信内置浏览器 长按识别二维码 功能的两三个坑与解决方案前端页面中 iOS 版微信长按识别二维码的bug 与解决网页中使用fixed,ios扫描会偏移到网页下部。1234padding: size(240) 0 0 size(240) !important;margin: size(-240) 0 0 size(-240) !important;position: relative;z-index: 100;-webkit-user-select: none;背景bg设置background: linear-gradient()安卓微信overflow失效CSS clip-pathhttp://www.cnblogs.com/coco1s/p/6992177.htmlWeb移动端Fixed布局的解决方案http://efe.baidu.com/blog/mobile-fixed-layout/]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue Loading组件]]></title>
<url>%2F2017%2F08%2F18%2FvueLoading%2F</url>
<content type="text"><![CDATA[Vue组件探秘文章适合有一定vue经验,只是简单介绍项目中的搭建与开发的优化之处。知识点,请自行查阅!原理vue-loading├── vue-loading/├── loading-rotate.vue # 旋转├── loading.vue # 实体└── index.js # 初始化1234567891011121314151617181920212223242526272829import Vue from 'vue'import Loading from './loading.vue'const Indicator = Vue.extend(Loading)let instanceexport default { open (options = {}) { if (!instance) { instance = new Indicator({ el: document.createElement('div') }) } // console.log(instance) if (instance.value) return instance.text = typeof options === 'string' ? options : options.text || '' instance.spinnerType = options.spinnerType || 'snake' document.body.appendChild(instance.$el) Vue.nextTick(() => { instance.value = true }) }, close () { if (instance) { instance.value = false } }}12345678910111213141516171819202122232425262728293031323334353637<template lang="pug"> div i.loading.icon_toast</template><style lang="less" scoped> .loading { width: 10px; height: 10px; display: inline-block; vertical-align: middle; animation: weuiLoading 1s steps(12, end) infinite; background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat; background-size: 100%; &.loading_transparent { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect xmlns='http://www.w3.org/2000/svg' width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.56)' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.5)' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.43)' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.38)' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.32)' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.28)' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.25)' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.2)' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.17)' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.14)' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.1)' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.03)' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E"); } } .icon_toast { &.loading { margin: 20px 0 10px; width: 30px; height: 30px; vertical-align: baseline; display: inline-block; } } @keyframes weuiLoading { 0% { transform: rotate3d(0, 0, 1, 0deg); } 100% { transform: rotate3d(0, 0, 1, 360deg); } }</style>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384<template> <transition name="vue-loading"> <div class="loading_toast" v-show="show"> <div class="mask"></div> <div class="toast" :style="{ position: position }"> <loading-rotate></loading-rotate> <p class="content">{{text || 'loading'}}<slot></slot></p> </div> </div> </transition></template><script>import loadingRotate from './loading-rotate' export default { props: { value: { type: Boolean, default: false }, text: String, position: String }, created () { this.show = this.value }, data () { return { show: false } }, watch: { value (val) { this.show = val }, show (val) { this.$emit('input', val) } }, components: { 'loading-rotate': loadingRotate } }</script><style lang="less" scoped> @import "../../../assets/less/mixins.less"; .vue-loading-enter, .vue-loading-leave-active { opacity: 0; } .vue-loading-leave-active, .vue-loading-enter-active { transition: opacity 300ms; } .mask { position: fixed; z-index: 1000; top: 0; right: 0; left: 0; bottom: 0; /*background: rgba(0, 0, 0, .6);*/ } .toast { position: fixed; z-index: 5000; width: 100px; min-height: 100px; top: 50%; left: 50%; margin-left: -50px; margin-top: -50px; background: rgba(17,17,17,0.7); text-align: center; border-radius: 10px; color: #FFFFFF; .content { padding: 0 6px 10px; font-size: 14px; word-wrap: break-word; } }</style>全局实例化123import Loading from '~/components/common/vue-loading'Vue.prototype.$Loading = LoadingVue.use(Loading)接口封装1234import * as Tool from '~/utils/vuex'Tool.open()Tool.close()12345678910111213141516171819202122232425262728293031323334353637383940import store from '~/store/index.js'// console.log('showToast')export const toast = (str, icon) => { // console.log('showToast') store().dispatch('showToast', true) if (icon === 'success') { store().dispatch('showSuccess', true) store().dispatch('showFail', false) } else { store().dispatch('showSuccess', false) store().dispatch('showFail', true) } store().dispatch('toastMsg', str) setTimeout(() => { store().dispatch('showToast', false) }, 1500) // console.groupEnd()}export const alert = (str) => { console.log('showAlert') store().dispatch('showAlert', true) store().dispatch('alertMsg', str) setTimeout(() => { store().dispatch('showAlert', false) }, 1500) // console.groupEnd()}export const open = (text, open) => { console.log(`%cAXIOS ${text}`, 'color:blue;') if (open) { store().dispatch('openLoading', text) }}export const close = () => { store().dispatch('closeLoading') // console.groupEnd()}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118import * as types from '../mutation-types'import Loading from '~/components/common/vue-loading'const state = { loading: false, loadingList: [], loadingCounet: 0, loadingcountUp: null, showToast: false, leftNavStatus: false, showSuccess: true, showFail: false, toastMsg: '操作成功', showTimePicker: false, alertMsg: '退出登录', showAlert: false}const actions = { openLoading ({ commit }, playload) { commit(types.COM_PUSH_LOADING, playload) }, closeLoading ({ commit }) { commit(types.COM_SHIFT_LOADING) }, setLoadingState ({ commit }, status) { commit(types.COM_LOADING_STATUS, status) }, setNavState ({ commit }, status) { commit(types.COM_NAV_STATUS, status) }, showToast ({ commit }, status) { commit(types.COM_SHOW_TOAST, status) }, showSuccess ({ commit }, status) { commit(types.COM_SHOW_SUCCESS, status) }, showFail ({ commit }, status) { commit(types.COM_SHOW_FAIL, status) }, toastMsg ({ commit }, str) { commit(types.COM_TOAST_MSG, str) }, showAlert ({ commit }, status) { commit(types.COM_SHOW_ALERT, status) }, alertMsg ({ commit }, str) { commit(types.COM_ALERT_MSG, str) }, showTimePicker ({ commit }, status) { commit(types.COM_SHOW_TIME_PICKER, status) }}const getters = { loading: state => state.loading, isLoading: state => state.loadingList.length > 0, showToast: state => state.showToast, showAlert: state => state.showAlert}const mutations = { [types.COM_LOADING_STATUS] (state, status) { state.loading = status }, [types.COM_PUSH_LOADING] (state, playload) { state.loadingList.push({text: playload || '玩命加载中...'}) Loading.open('加载中……') state.count = 1 state.countUp = setInterval(() => { state.count += 1 }, 1000) }, [types.COM_SHIFT_LOADING] (state) { state.loadingList.shift() Loading.close() clearInterval(state.countUp) }, [types.COM_SHOW_TOAST] (state, status) { state.showToast = status }, [types.COM_SHOW_SUCCESS] (state, status) { state.showSuccess = status }, [types.COM_SHOW_FAIL] (state, status) { state.showFail = status }, [types.COM_TOAST_MSG] (state, str) { state.toastMsg = str }, [types.COM_NAV_STATUS] (state, status) { state.leftNavStatus = status }, [types.COM_SHOW_TIME_PICKER] (state, status) { state.showTimePicker = status }, [types.COM_SHOW_ALERT] (state, status) { state.showAlert = status }, [types.COM_ALERT_MSG] (state, str) { state.alertMsg = str }}export default { state, actions, getters, mutations}]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[keep-alive最佳实践]]></title>
<url>%2F2017%2F08%2F18%2FKeepAlive%2F</url>
<content type="text"><![CDATA[Vue 项目搭建:文章适合有一定vue经验,只是简单介绍项目中的搭建与开发的优化之处。知识点,请自行查阅!使用属性include - 字符串,或正则表达式,或数组。匹配的组件会被缓存。exclude - 字符串,或正则表达式,或数组。匹配的组件不会被缓存。生命周期当组件在内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。作用主要用于保留组件状态或避免重新渲染。1234567891011121314<!-- comma-delimited string --><keep-alive include="a,b"> <component :is="view"></component></keep-alive><!-- regex (use v-bind) --><keep-alive :include="/a|b/"> <component :is="view"></component></keep-alive><!-- Array (use v-bind) --><keep-alive :include="['a', 'b']"> <component :is="view"></component></keep-alive>误解1.直接添加在router-view上:将所有页面全部缓存,这样的内存不会卡顿?如何制定那些缓存。无法使用过滤。123<keep-alive> <router-view></router-view></keep-alive>不适用与v-for的组件上,和没有组件的内容。实例子路由的内容缓存,切换路由,将组建缓存,通过data,判断是否重新渲染页面内容。mounted => activated => deactivated => activated => deactivated12345678910mounted () { // 加载数据},activated: function () { // 是否重新加载数据 console.log('组件启动')},deactivated: function () { console.log('组件缓存')}关于router-view上使用keep-alive的问题]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue defineProperty 双向绑定详解]]></title>
<url>%2F2017%2F08%2F18%2FVueDefineProprty%2F</url>
<content type="text"><![CDATA[Vue组件探秘双向绑定的实现方法有很多,今天我们来讲基于数据劫持的双向绑定。基于数据劫持的双向绑定有两种。Object.defineProperty与proxy,而VUE 3.0中使用的proxyproxy 严格来说是代理,而非劫持。究竟什么优点让他代替了defineproperty。框架原理方法KnockoutJS基于观察者模式的双向绑定Ember基于数据模型的双向绑定Angular基于脏检查的双向绑定Vue基于数据劫持的双向绑定Object.definepropertyVue基于数据劫持的双向绑定proxyVue基于数据劫持的双向绑定Object.observe(已废弃)原理Object.definepropertyobj: 目标对象prop: 需要操作的目标对象的属性名descriptor: 描述符return value 传入对象1234567891011121314const obj = {}Object.defineProperty(obj, 'text', { get: function() { console.log('get Val') }, set: function(val) { console.log('set val:' + val) document.getElementById('p').innerHTML = val }})const input = document.getElementById('input')input.addEventListener('keyup', function (e){ obj.text = e.target.value})请输入:!function(){const e={};Object.defineProperty(e,"text",{get:function(){console.log("get Val")},set:function(e){console.log("set val:"+e),document.getElementById("p").innerHTML=e}});const t=document.getElementById("input");t.addEventListener("keyup",function(t){e.text=t.target.value})}()]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue组件探秘]]></title>
<url>%2F2017%2F08%2F18%2FVueComponents%2F</url>
<content type="text"><![CDATA[Vue组件探秘文章适合有一定vue经验,只是简单介绍项目中的搭建与开发的优化之处。知识点,请自行查阅!基础属性Props探秘Props验证12345678910111213141516171819202122232425262728293031Vue.component('example', { props: { // 基础类型检测 (`null` 意思是任何类型都可以) propA: Number, // 多种类型 propB: [String, Number], // 必传且是字符串 propC: { type: String, required: true }, // 数字,有默认值 propD: { type: Number, default: 100 }, // 数组/对象的默认值应当由一个工厂函数返回 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 自定义验证函数 propF: { validator: function (value) { return value > 10 } } }})type可以是下面原生构造器1234567StringNumberBooleanFunctionObjectArraySymbolv-on:绑定原生事件如果想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on1<my-component v-on:click.native="doTheThing"></my-component>自定义事件this.$emit分发事件1234567891011121314151617181920212223<div id="app3"> <my-component2 v-on:myclick="onClick"></my-component2></div><script> Vue.component('my-component2', { template: `<div> <button type="button" @click="childClick">点击我触发自定义事件</button> </div>`, methods: { childClick () { this.$emit('myclick', '这是我暴露出去的数据', '这是我暴露出去的数据2') } } }) new Vue({ el: '#app3', methods: { onClick () { console.log(arguments) } } })</script>组件内部方法,触发外部自定义方法123this.$emit('myclick', 'data1', 'data2')<!-- 第一个参数是自定义事件的名字 --><!-- 后面的参数是依次想要发送出去的数据 -->父组件利用v-on为事件绑定处理器1<my-component2 v-on:myclick="onClick"></my-component2>在使用v-on绑定事件处理方法时,不应该传进任何参数,而是直接写v-on:myclick=”onClick”,不然,子组件暴露出来的数据就无法获取到了v-modelv-model是一个十分强大的指令,它可以自动让原生表单组件的值自动和你选择的值绑定12<input v-model="message" placeholder="edit me"><p>Message is: {{ message }}</p>使用自定义事件的表单输入组件12345<input v-model="something"><input v-bind:value="something" v-on:input="something = $event.target.value">非常简单的货币输入的自定义控件:123456789101112131415161718192021222324252627282930313233343536<currency-input v-model="price"></currency-input>Vue.component('currency-input', { template: '\ <span>\ $\ <input\ ref="input"\ v-bind:value="value"\ v-on:input="updateValue($event.target.value)"\ >\ </span>\ ', props: ['value'], methods: { // 不是直接更新值,而是使用此方法来对输入值进行格式化和位数限制 updateValue: function (value) { var formattedValue = value // 删除两侧的空格符 .trim() // 保留 2 小数位 .slice( 0, value.indexOf('.') === -1 ? value.length : value.indexOf('.') + 3 ) // 如果值不统一,手动覆盖以保持一致 if (formattedValue !== value) { this.$refs.input.value = formattedValue } // 通过 input 事件发出数值 this.$emit('input', Number(formattedValue)) } }})修饰符12345678<!-- 在 "change" 而不是 "input" 事件中更新 --><input v-model.lazy="msg" ><!-- 自动将用户的输入值转为 Number 类型 --><input v-model.number="age" type="number"><!-- 自动过滤用户输入的首尾空格 --><input v-model.trim="msg">1234567891011121314151617<div id="app4"> <input type="text" v-bind:value="text" v-on:input="changeValue($event.target.value)"> {{text}}</div><script> new Vue({ el: '#app4', data: { text: '444' }, methods: { changeValue (value) { this.text = value } } })</script>12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152<!DOCTYPE html><html><head> <meta charset="UTF-8" /> <title>vue.js component</title></head><body><!-- 子组件模板 --><template id="child-template"> <input v-model='msg' /> <button v-on:click="notify">Dispatch Event</button></template><!-- 父组件模板 --><div id="events-example"> <p>Messages: {{messages | json}}</p> <child></child></div><div id="example"></div><script type="text/javascript" src="../js/vue.js"></script><script type="text/javascript"> Vue.component('child', { template: '#child-template', data: function () { return { msg: 'hello' } }, methods: { notify: function () { if (this.msg.trim()) { this.$dispatch('child-msg', this.msg); this.msg = ''; } } } }); var parent = new Vue({ el: '#events-example', data: { messages: [], }, events: { 'child-msg': function (msg) { this.messages.push(msg); } } });</script></body></html>12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152<!DOCTYPE html><html><head> <meta charset="UTF-8" /> <title>vue.js component</title></head><body><!-- 子组件模板 --><template id="child-template"> <input v-model='msg' /> <button v-on:click="notify">Dispatch Event</button></template><!-- 父组件模板 --><div id="events-example"> <p>Messages: {{messages | json}}</p> <child v-on:child-msg="handleIt"></child></div><div id="example"></div><script type="text/javascript" src="../js/vue.js"></script><script type="text/javascript"> Vue.component('child', { template: '#child-template', data: function () { return { msg: 'hello' } }, methods: { notify: function () { if (this.msg.trim()) { this.$dispatch('child-msg', this.msg); this.msg = ''; } } } }); var parent = new Vue({ el: '#events-example', data: { messages: [], }, methods: { 'handleIt': function () { console.log('a'); } } });</script></body></html>深刻理解Vue中的组件表单控件绑定]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Terminal配置]]></title>
<url>%2F2017%2F08%2F02%2FTerminal%2F</url>
<content type="text"><![CDATA[vim ~/.bash_profilea :编辑模式esc :命令模式:wq :保存并退出123456# for colorexport CLICOLOR=1# \h:\W \u\$export PS1='\[\033[01;33m\]\u@\h\[\033[01;31m\] \W\$\[\033[00m\] '# grepalias grep='grep --color=always'1234567891011121314151617181920212223find_git_branch () { local dir=. head until [ "$dir" -ef / ]; do if [ -f "$dir/.git/HEAD" ]; then head=$(< "$dir/.git/HEAD") if [[ $head = ref:\ refs/heads/* ]]; then git_branch="<${head#*/*/}>" elif [[ $head != '' ]]; then git_branch="<(detached)>" else git_branch="<(unknow)>" fi return fi dir="../$dir" done git_branch=''}# for colorexport CLICOLOR=1# \h:\W \u\$PROMPT_COMMAND="find_git_branch; $PROMPT_COMMAND"export PS1='\[\033[01;33m\]\u@\[\033[01;31m\]\W\[\033[00;31m\] $git_branch\[\033[01;31m\]\$\[\033[00m\] ']]></content>
<categories>
<category>Tool</category>
</categories>
<tags>
<tag>Terminal</tag>
</tags>
</entry>
<entry>
<title><![CDATA[WeChat SDK]]></title>
<url>%2F2017%2F07%2F25%2FJS-SDK%2F</url>
<content type="text"><![CDATA[微信作为大佬,使用他的SDK有些什么需要注意的地方!有哪些容易出错的地方。微信支付H5支付微信官方体验链接通过微信H5支付可以实现在非微信浏览器(如QQ浏览器、谷歌浏览器、Safari等)中使用微信支付的场景。接口流程图获取跳转链接常见问题JSDK支付用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程。微信内H5调起支付123456789101112131415161718192021222324252627282930function onBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest', { // 公众号名称,由商户传入 "appId":"wx2421b1c4370ec43b", // 时间戳,自1970年以来的秒数 "timeStamp":"1395712654", // 随机串 "nonceStr":"e61463f8efa94090b1f366cccfbbb444", "package":"prepay_id=u802345jgfjsdfgsdg888", // 微信签名方式: "signType":"MD5", // 微信签名 "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 } );}if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); }}else{ onBridgeReady();}123456789101112131415wx.chooseWXPay({ // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 timestamp: 0, // 支付签名随机串,不长于 32 位 nonceStr: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***) package: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' signType: '', // 支付签名 paySign: '', // 支付成功后的回调函数 success: function (res) { }});小程序支付注意事项微信分享出去的链接被,打开后自动添加参数使用微信出去的页面,在微信中打开时就会显示。出文章在什么终端中打开的参数,添加在链接上。朋友圈 from=timeline&isappinstalled=0微信群 from=groupmessage&isappinstalled=0好友分享 from=singlemessage&isappinstalled=0解决办法:在链接上添加?分享后打开后,微信会将?去除。url => url? => urlvue:/#/ => /?*/ => /#/]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>WeChatSDK</tag>
</tags>
</entry>
<entry>
<title><![CDATA[浏览器常见Bug——Canvas]]></title>
<url>%2F2017%2F07%2F12%2FCanvas%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why生成图片CanvastoDataURLUncaught (in promise) DOMException: Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported.问题原因:Canvas为了安全性考虑,当绘制了外部图片后它会变成只可写不可读的状态,getImageData、toDataURL之类的试图读取数据的方法全都无法使用。理论上开启了CORS的资源应该被允许读取,只是IMG元素发起的请求默认并不带Origin字段,没能应用上CORS。request Headers请求头Origin:origin主要是用来说明最初请求是从哪里发起的;origin只用于Post请求,而Referer则用于所有类型的请求;origin的方式比Referer更安全点吧。基于 canvas 实现的一个截图小 demoCORS与Canvas图片toDataURLAccess-Control-Allow-OriginAccess to Image at ‘http://wx4.sinaimg.cn/mw690/4b4d632fgy1fieo66xwy4j20io0goq46.jpg' from origin ‘http://172.16.20.115:8780' has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://172.16.20.115:8780' is therefore not allowed access.CORS解决前端实现’截图’效果的几种方式html2canvas html截图插件图片放大清晰度解决方案,支持任意放大倍数,解决原插件图片偏移问题html2canvas 将代码转为图片]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>Hack</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vuex]]></title>
<url>%2F2017%2F04%2F25%2FVuex%2F</url>
<content type="text"><![CDATA[Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。TODO[ ] 严格模式[ ] 测试[ ] 插件[ ] 热重载[ ][x]开始简单实用1234567891011import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)const state = { count: 'jljdfdf'}export default new Vuex.Store({ state})全局注入12345678910npm install vuex --saveimport store from './vuex/store'new Vue({ el: '#app', router, store, template: '<App/>', components: { App }})仓库管理123456789import Vue from 'vue'import Vuex from 'vuex'import modules from './modules'Vue.use(Vuex)export default new Vuex.Store({ modules})模块化123456789101112131415161718192021import api from 'API';import * as types from 'VUEX/mutation-types';const state = {}const getters = {}const actions = {}const mutations = {}export default { state, getters, actions, mutations}状态管理123export const COM_NAV_STATUS = 'COM_NAV_STATUS'export const COM_HEADER_STATUS = 'COM_HEADER_STATUS'export const COM_LOADING_STATUS = 'COM_LOADING_STATUS'流程通过Getters映射,控制Actions改变状态,从而控制mutations状态控制数据变化。概念状态自管理应用包含以下几个部分:state,驱动应用的数据源;view,以声明方式将state映射到视图;actions,响应在view上的用户输入导致的状态变化。store 仓库“store”基本上就是一个容器,它包含着你的应用中大部分的状态(state)。Vuex和单纯的全局对象有以下两点不同:Vuex的状态存储是响应式的。当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会相应地得到高效更新。你不能直接改变store中的状态。改变store 中的状态的唯一途径就是显式地提交(commit) mutations。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。数据传输方式“单向数据流”理念的极简示意多个组件共享状态的缺点:传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。组件仍然保有局部状态使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。this.$store.statethis.$store.commit(‘mutationName’)Getters有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:12345computed: { doneTodosCount () { return this.$store.state.todos.filter(todo => todo.done).length }}Vuex 允许我们在 store 中定义『getters』(可以认为是 store 的计算属性)。Getters 接受 state 作为其第一个参数:12345678910111213const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } }})Getters 也可以接受其他 getters 作为第二个参数:123456getters: { // ... doneTodosCount: (state, getters) => { return getters.doneTodos.length }}mapGetters 辅助函数mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性:12345678computed: {// 使用对象展开运算符将 getters 混入 computed 对象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // ... ])}如果你想将一个 getter 属性另取一个名字,使用对象形式:1234mapGetters({ // 映射 this.doneCount 为 store.getters.doneTodosCount doneCount: 'doneTodosCount'})Mutations更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutations 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:1234567891011const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } }})提交 mutationAction1store.commit('increment')提交载荷(Payload)你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)12345678910store.commit('increment', 10)store.commit('increment', { amount: 10})store.commit({ type: 'increment', amount: 10})mapMutations 组件中提交1234567891011121314import { mapMutations } from 'vuex'export default { methods: { ...mapMutations([ 'increment' // 映射 this.increment() 为 this.$store.commit('increment') ]), ...mapMutations({ add: 'increment' // 映射 this.add() 为 this.$store.commit('increment') }) }}状态操作12345678const mutations = { [types.Increment] (state, params) { state.searchKey = params }, increment (state, params) { state.searchKey = params }}现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用 —— 实质上任何在回调函数中进行的的状态的改变都是不可追踪的。下一步:Actions在 mutation 中混合异步调用会导致你的程序很难调试。例如,当你能调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?这就是为什么我们要区分这两个概念。在 Vuex 中,mutation 都是同步事务:12store.commit('increment')// 任何由 "increment" 导致的状态变更都应该在此刻完成。ActionsAction 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。1234567891011actions: { increment (context) { context.commit('increment') }}actions: { increment ({ commit }) { commit('increment') }}dispatch 分发 Action1this.$store.dispatch('getTravelsList')载荷分发 Action12345678910// 以载荷形式分发store.dispatch('incrementAsync', { amount: 10})// 以对象形式分发store.dispatch({ type: 'incrementAsync', amount: 10})mapActions 组件分发12345678methods: { ...mapActions([ 'increment' // 映射 this.increment() 为 this.$store.dispatch('increment') ]), ...mapActions({ add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment') })}组合 Actions一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。123456789101112131415161718192021222324actions: { actionA ({ commit }) { return new Promise((resolve, reject) => { setTimeout(() => { commit('someMutation') resolve() }, 1000) }) }}store.dispatch('actionA').then(() => { // ...})actions: { // ... actionB ({ dispatch, commit }) { return dispatch('actionA').then(() => { commit('someOtherMutation') }) }}最后,如果我们利用 async / await 这个 JavaScript 即将到来的新特性,我们可以像这样组合 action:12345678910actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { // 等待 actionA 完成 await dispatch('actionA') commit('gotOtherData', await getOtherData()) }}Modules使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。为了解决以上问题,Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:12345678910111213141516171819202122const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... }}const moduleB = { state: { ... }, mutations: { ... }, actions: { ... }}const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB }})store.state.a // -> moduleA 的状态store.state.b // -> moduleB 的状态模块的局部状态对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态。1234567891011121314const moduleA = { state: { count: 0 }, mutations: { increment (state) { // state 模块的局部状态 state.count++ } }, getters: { doubleCount (state) { return state.count * 2 } }}同样,对于模块内部的 action,context.state 是局部状态,根节点的状态是 context.rootState:12345678910const moduleA = { // ... actions: { incrementIfOddOnRootSum ({ state, commit, rootState }) { if ((state.count + rootState.count) % 2 === 1) { commit('increment') } } }}对于模块内部的 getter,根节点状态会作为第三个参数:12345678const moduleA = { // ... getters: { sumWithRootCount (state, getters, rootState) { return state.count + rootState.count } }}命名空间模块内部的 action、mutation、和 getter 现在仍然注册在全局命名空间——这样保证了多个模块能够响应同一 mutation 或 action。你可以通过添加前缀或后缀的方式隔离各模块,以避免名称冲突。你也可能希望写出一个可复用的模块,其使用环境不可控。例如,我们想创建一个 todos 模块:12345678910111213141516171819202122232425262728// types.js// 定义 getter、action、和 mutation 的名称为常量,以模块名 `todos` 为前缀export const DONE_COUNT = 'todos/DONE_COUNT'export const FETCH_ALL = 'todos/FETCH_ALL'export const TOGGLE_DONE = 'todos/TOGGLE_DONE'// modules/todos.jsimport * as types from '../types'// 使用添加了前缀的名称定义 getter、action 和 mutationconst todosModule = { state: { todos: [] }, getters: { [types.DONE_COUNT] (state) { // ... } }, actions: { [types.FETCH_ALL] (context, payload) { // ... } }, mutations: { [types.TOGGLE_DONE] (state, payload) { // ... } }}模块动态注册在 store 创建之后,你可以使用 store.registerModule 方法注册模块123store.registerModule('myModule', { // ...})模块化问题问题:loading加载最近浏览到篇文章,普通loading只能通过控制单一的显示,而且多次条用很容易报错。vue-vuex-loading案例shopping-cartCounterCounter with Hot ReloadTodoMVCFlux Chat浅谈VuexVuex下Store的模块化拆分实践Vuex 通俗版教程Vuex框架原理与源码分析]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[移动端真机调试实战经验]]></title>
<url>%2F2017%2F04%2F19%2FFEDebug%2F</url>
<content type="text"><![CDATA[** Git的使用技巧:**前言在开发中前端免不了要进行移动端的开发,然而在电脑上看的样式和手机上还是有一定的差距的,因为手机上有顶部的状态栏和底部的菜单栏,特别是在qq内置浏览器中打开,差距还是蛮大的,所以在chrom中模拟手机显示的情况虽然有一定的效果,但是还是不能完全模拟,我们还需要在真机环境下测试。本文介绍的调试方法有一下几种:iphone+safariandroid手机+pc微信开发者工具weinre使用webstorm使用Fiddle抓包这几种方法基本说涵盖了我们平时开发中所遇到的各种情况,各种主流设备都可以覆盖。其中最方便快捷的是使用webstorm自带的服务器,只需要一键就可以,但是这样只能预览,不能调试。我个人比较推荐的方法是iphone+safari或者安卓手机+pc的这种方式,比较简单方便快捷,然后根据具体的环境再选择更为合适的调试方法。目前我认为使用weinre+fiddle是万能的,没有什么调试不了了但是需要学习的成本也是最高的希望大家都能够写出漂亮的页面,不需要为调试发愁哈iphone+safari之前使用的是mac,所以一直都是用的iphone+safari模拟真机环境,这种方法简单明了,只需要简单的设置一下以后都不要设置,插上数据线,打开mac上的safari就可以了,(๑•̀ㅂ•́)و,✧,但是对设备有要求,必须是iphone+mac的组合iphone上设置设置 → Safari → 高级 → Web 检查器 → 开。这里写图片描述pc端safari设置Safari → 偏好设置 → 高级 → 在菜单栏中显示“开发”菜单这里写图片描述设置完之后用数据线连接电脑,然后在iphone上用打开safari需要调试的网址,然后在pc端打开safari,最上面的菜单栏中的“开发”然后就可以看到有iphone设备的名称显示然后就可以看见你在iphone中的safari中打开了哪些网址,之后就和调试网页版的一样了android手机+pc安卓手机只需要下载chrom浏览器,就可以再电脑上用chrom调试了,是不是很赞(づ ̄3 ̄)づ╭首先需要装chrom浏览器打开手机的开发者模式,一般是:设置->关于手机->版本号连按5次,之后设置菜单中会多出一个开发人员选项,进入将其中的“usb调试”打开将手机与电脑通过usb连接,弹出对话框“是否允许usb调试”,选择确定在手机chrom上打开要调试的页面在电脑上打开chrom,新开一地址栏为chrome://inspect/的页面,然后就可以调试了点击inspect弹出chrom调试工具微信开发者工具由于不可描述原因,有些页面只在微信里面出错,并且好多涉及到了微信相关的接口必须要使用微信环境的,比如自定义分享前期准备这个使用起来很方便。(我记得之前使用的时候(2016年),你要调试的页面必须是你是管理员的微信公众号下面的js安全域名下的地址),但是刚刚下载一个新版本的开发者工具(v0.7.0),现在的时间是2017年3月28日,发现好像没有这个限制了。所以这样开发起来就方便多了。官方文档&下载地址官方文档其中有下载地址模拟微信环境调试直接在地址栏输入地址就可以模拟微信环境调试,是不是很方便~这种方式可以满足大部分的需求真机调试在开发者工具中的移动调试中可以有详细的ios和安卓的调试方式,主要是使用代理,这里我没有调试成功,在手机微信中一直打不开网页,所以就不详细写了╥﹏╥…—————3.29更———————我找到设置代理之后打不开网页的原因了,在使用fiddler抓包的时候也遇到了同样的问题,原来这里需要下载认证在设置完当前网络的代理之后,在浏览器输入本机的ip地址和ip号,下载fiddler的证书然后根据提示一步一步安装就可以了。安装完证书就可以打开网页了weinre跟着我念三遍weinre大法好,weinre大法好,weinre大法好之前介绍的几种方式或多或少都有一些条件限制,但是weinre没有啊喂!就比如我是ios+windows的组合,就不能使用iphone+safari和安卓+pc的方式调试,所以使用weinre就可以!!缺点就是配置起来有削微的麻烦什么是weinreweinre是web inspector remote(远程web检查器)的缩写安装weinre目前安装weinre我了解到有两种方式:node和java两种方式node方式安装weinre首先确保你的电脑上有node环境,然后使用npm来安装windows下npm install weinre -g –registry=https://registry.npm.taobao.orgmac下sudo npm install weinre -g –registry=https://registry.npm.taobao.orgjava环境下安装weinre首先确认你电脑上装好的java环境,然后下载weinre的jar包,上百度云盘的链接:链接: https://pan.baidu.com/s/1slRiOl3 密码: dsmp运行weinrenode环境下weinre –httpPort 8081 –boundHost -all-8081是调试服务器运行的端口号,boundHost是调试服务器绑定的ip地址或域名,默认是localhost,设置为-all-是为了在本地能使用localhost打开,在移动设备或本地环境用ip地址打开weinre调试工具java环境下在weinre所在文件夹的地址栏输入代码:java -jar weinre.jar –httpPort 8081 –boundHost -all-开始调试设置好端口之后我们在本地打开http://192.168.0.126:8081然后就可以看见weinre的基本信息之后我们需要在需要调试的页面上加上一段script标签需要改为你自己的ip地址ip的查询方式在cmd输入ipconfig,然后ipv4中后面跟的就是本机的ip地址手机打开需要调试的链接在staticWebDir目录下本地的源文件貌似只能在staticWebDir目录下才可以访问到(这是因为在没有使用任何服务器的情况下,weinre自带有服务器,所以只能放在默认的根目录下),将你的源文件放在staticWebDir目录下,staticWebDir的目录是你安装weinre的根目录,我的是:C:\Users\supfn\AppData\Roaming\npm\node_modules\weinre\web,然后手机访问:http://192.168.0.126/contact_page/index.html,然后在电脑上打开刚刚的页面http://196.168.0.126:8081点击debug client user interface之后出现,点击蓝色的链接,变为绿色的之后就说明链接成功了。在后面的elements和其他的tag就可以进行调试在xampp下因为公司的项目是在xampp下的,已经配置好了apache,可以直接在平时的项目前加上本地的ip,在手机上访问就好。项目存放的地址是xampp\htdocs\app修改配置:C:\Windows\System32\drivers\etc\hosts文件下最后一行127.0.0.1 localhost ltrip.com fzc.com m.fzc.com m.ltrip.com然后在C:\xampp\apache\conf\extra文件里面修改<VirtualHost *:80> DocumentRoot “C:\xampp\htdocs\ltrip” ServerName ltrip.com ServerAlias <Directory “C:\xampp\htdocs\ltrip”> Options FollowSymLinks ExecCGI AllowOverride All Order allow,deny Allow from all Require all granted其中的ServerName ltrip.com中的ltrip.com就代替了”C:\xampp\htdocs\ltrip”这个路径,所以就不需要放在staticWebDir目录下了,这样手机打开的地址就变成了:http://192.168.0.168/ltrip.com使用webstorm在最先开始使用weinre的时候,一直卡在一个地方,就是手机访问的地址问题,在看教程的时候我就卡在不知道怎么输入手机打开的网址,因为我是自己写的一个简单的html的demo,在本地打开的地址是使用本地的绝对路径比如file:///C:/Users/supfn/Desktop/contact_page/index.html这样子的,在手机肯定访问不到我的电脑上的路径。这里是需要在本地搭建一个服务器,这样才能在手机访问到你电脑上的资源,通过服务器其他人也可以访问你电脑上的资源,常见的服务器有apache,使用Java的还可以用tomcat。这些使用起来都比较麻烦,这里推荐一个简单的方式,使用webstorm。webstorm集成了debugger服务器,所以可以直接在你项目html页面的右上角点击浏览器的图标,在对应浏览器打开项目,然后将地址栏上的localhost改为你的ip地址,手机访问这个地址就可以了简直不要太方便!!所以webstorm真的是web开发利器,而不止是一个编辑器使用Fiddle抓包如果是要调试线上代码的话经常是无法再页面中直接加入script标签的,然后我们可以利用fiddler为页面设置断点,然后注入js代码,在run就可以了fiddler是用过改写http代理,让数据从它这通过,来监控截取到的数据。在打开fiddler的时候,就已经自动设置好了浏览器的代理了,关闭的时候,它又把代理还原了下载fiddlerFiddler 下载地址 :https://www.telerik.com/download/fiddlerFiddler 离线下载地址:http://pan.baidu.com/s/1i3NvE8P 密码:ozem使用fiddler抓取数据包在手机上设置同一个局域网上的代理,代理服务器设置为电脑的ip地址,端口为8888在fiddler上,点击菜单栏中的 [Tools] –> [Fiddler Options]点击 [Connections] ,设置代理端口是8888, 勾选 Allow remote computers to connect, 点击OK使用weinre与fiddler组合我们要实现的目标就是要调试线上的代码,使用fiddler在代码中注入weinre需要加上的script标签在完成配置之后打开要调试的链接,然后在fiddler中设置断点我们在fiddler中打下页面断点,bpafter + 想要打断点的网址再次访问该网站,发现本条请求被block住了这里写图片描述然后在右边加上weinre需要的script标签然后点击右边代码上面绿色的run to completion就可以看到注入js的效果了,之后我们就可以在weinre中调试了~参考文章Fiddler 抓包工具总结移动端调试工具weinre安装教程(java版)聊一聊移动调试那些事儿]]></content>
<categories>
<category>Tool</category>
</categories>
<tags>
<tag>Git</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue Router]]></title>
<url>%2F2017%2F03%2F25%2FVueRouter%2F</url>
<content type="text"><![CDATA[自用笔记:Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统。最近在Github上看到了不少Vue的项目,很好奇,决定尝试尝试。TODO[ ] history的后退配置[ ] 路由懒加载[ ] 滚动行为[ ] router.beforeEach基础路由使用12345678910111213<div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 组件来导航. --> <!-- 通过传入 `to` 属性指定链接. --> <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <!-- 路由出口 --> <!-- 路由匹配到的组件将渲染在这里 --> <router-view></router-view></div>配置12345678910111213141516171819202122232425262728293031import Vue from 'vue'import Router from 'vue-router'import Active from 'VIEW/active/active'Vue.use(Router)// 通过这个这个属性(是个函数),可以让应用像浏览器的原生表现那样,在按下 后退/前进 按钮时,简单地让页面滚动到顶部或原来的位置。const scrollBehavior = (to, from, savedPosition) => { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } }}export default new Router({ mode: 'history', // history: 依赖 HTML5 History API 和服务器配置。 base: __dirname, // 默认值: “/”,应用的基路径,一般就是项目的根目录,webpack中有配置好。 linkActiveClass:'link-active', scrollBehavior, routes: [ { path: '/', name: 'Active', component: Active } ]})123456new Vue({ el: '#app', router, template: '<App/>', components: { App }})动态路由匹配在 vue-router 的路由路径中使用『动态路径参数』(dynamic segment)来达到这个效果:路径参数123456{ path: '/user/:username', component: User }/user/evan{ path: '/user/:username', component: User }/user/evan/post/123参数不能不传响应路由参数的变化例如从 /user/foo 导航到 user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。1234watch: { '$route' (to, form) { }},高级匹配模式vue-router 使用 path-to-regexp 作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。查看它的 文档 学习高阶的路径匹配,还有 这个例子 展示 vue-router 怎么使用这类匹配1234567891011121314151617181920212223{ path: '/' },// 参数前面使用“:”表示{ path: '/params/:foo/:bar' },// 添加“?”使参数作为可选择{ path: '/optional-params/:foo?' },// 匹配id为数字的链接{ path: '/params-with-regex/:id(\\d+)' },// * 可以匹配任何东西{ path: '/asterisk/*' },// 使用括号包裹,用?让其可选择make part of th path optional by wrapping with parens and add "?"{ path: '/optional-group/(foo/)?bar' }<li><router-link to="/">/</router-link></li><li><router-link to="/params/foo/bar">/params/foo/bar</router-link></li><li><router-link to="/optional-params">/optional-params</router-link></li><li><router-link to="/optional-params/foo">/optional-params/foo</router-link></li><li><router-link to="/params-with-regex/123">/params-with-regex/123</router-link></li><li><router-link to="/params-with-regex/abc">/params-with-regex/abc</router-link></li><li><router-link to="/asterisk/foo">/asterisk/foo</router-link></li><li><router-link to="/asterisk/foo/bar">/asterisk/foo/bar</router-link></li><li><router-link to="/optional-group/bar">/optional-group/bar</router-link></li><li><router-link to="/optional-group/foo/bar">/optional-group/foo/bar</router-link></li>匹配优先级有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。嵌套路由这里的是最顶层的出口,渲染最高级路由匹配到的组件。同样地,一个被渲染组件同样可以包含自己的嵌套。例如,在 User 组件的模板添加一个:children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。123456789101112131415161718{ path: '/user/:id', component: User, children: [ // 空的 子路由 { path: '', component: UserHome }, { // 当 /user/:id/profile 匹配成功, // UserProfile 会被渲染在 User 的 <router-view> 中 path: 'profile', component: UserProfile }, { // 当 /user/:id/posts 匹配成功 // UserPosts 会被渲染在 User 的 <router-view> 中 path: 'posts', component: UserPosts } ]}注意:以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。编程式的导航router.push(location)router.push(location, onComplete?, onAbort?)想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。声明式编程式<router-link :to="...">router.push(…)12345678910111213// 字符串this.$router.push('home')// 对象this.$router.push({ path: 'home' })// 命名的路由this.$router.push({ name: 'user', params: { userId: 123 }})this.$route.params.userId// 带查询参数,变成 /register?plan=privatethis.$router.push({ path: 'register', query: { plan: 'private' }})this.$route.query.planrouter.replace(location)router.replace(location, onComplete?, onAbort?)跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。声明式编程式<router-link :to="..." replace>router.replace(…)router.go(n)这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。123456789101112// 在浏览器记录中前进一步,等同于 history.forward()this.$router.go(1)// 后退一步记录,等同于 history.back()this.$router.go(-1)// 前进 3 步记录this.$router.go(3)// 如果 history 记录不够用,那就默默地失败呗this.$router.go(-100)this.$router.go(100)命名路由通过一个名称来标识一个路由显得更方便一些1234/user/123<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link><router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>this.$router.push({ name: 'user', params: { userId: 123 }})命名视图有时候想同时(同级)展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar(侧导航) 和 main(主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。12345678910111213141516<router-view class="view one"></router-view><router-view class="view two" name="a"></router-view><router-view class="view three" name="b"></router-view>const router = new VueRouter({ routes: [ { path: '/', components: { default: Foo, a: Bar, b: Baz } } ]})重定向 和 别名重定向路径1{ path: '/a', redirect: '/b' }命名1{ path: '/a', redirect: { name: 'foo' }}动态返回重定向1234{ path: '/a', redirect: to => { // 方法接收 目标路由 作为参数 // return 重定向的 字符串路径/路径对象}}别名别名:的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。1{ path: '/a', component: A, alias: '/b' }HTML5 History 模式vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。http://localhost:8680/#/Tap/btn/Github1234const router = new VueRouter({ mode: 'history', routes: [...]})/user/:id不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。进阶正如其名,vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消。有多种方式可以在路由导航发生时执行钩子:全局的, 单个路由独享的, 或者组件级的。导航钩子router.beforeEach1234to: Route, from: Route, next: Functionrouter.beforeEach((to, from, next) => { // to 和 from 都是 路由信息对象})to: Route:即将要进入的目标 路由对象from: Route:当前导航正要离开的路由next: Function:一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。next(‘/‘) 或者 next({ path: ‘/‘ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。router.afterEach1234after 钩子没有 next 方法,不能改变导航:router.afterEach(route => { // ...})某个路由独享的钩子这些钩子与全局 before 钩子的方法参数是一样的。1234567891011const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ]})组件内的钩子123456789101112131415161718const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当钩子执行前,组件实例还没被创建 }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` }}数据获取导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示『加载中』之类的指示。导航完成之前获取:导航完成前,在路由的 enter 钩子中获取数据,在数据获取成功后执行导航。导航完成后获取数据12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849<template> <div class="post"> <div class="loading" v-if="loading"> Loading... </div> <div v-if="error" class="error"> </div> <div v-if="post" class="content"> <h2></h2> <p></p> </div> </div></template>export default { data () { return { loading: false, post: null, error: null } }, created () { // 组件创建完后获取数据, // 此时 data 已经被 observed 了 this.fetchData() }, watch: { // 如果路由有变化,会再次执行该方法 '$route': 'fetchData' }, methods: { fetchData () { this.error = this.post = null this.loading = true // replace getPost with your data fetching util / API wrapper getPost(this.$route.params.id, (err, post) => { this.loading = false if (err) { this.error = err.toString() } else { this.post = post } }) } }}在导航完成前获取数据我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 钩子中获取数据,当数据获取成功后只调用 next 方法。12345678910111213141516171819202122232425262728293031323334353637383940414243export default { data () { return { post: null, error: null } }, beforeRouteEnter (to, from, next) { getPost(to.params.id, (err, post) => if (err) { // display some global error message next(false) } else { next(vm => { vm.post = post }) } }) axios.get(api).then((response) => { next(vm => { vm.votes = response.data.items vm.jsons = 1 }) }, (response) => { next(false) }) }, // 路由改变前,组件就已经渲染完了 // 逻辑稍稍不同 watch: { $route () {} '$route': () { this.post = null getPost(this.$route.params.id, (err, post) => { if (err) { this.error = err.toString() } else { this.post = post } }) } }}滚动行为注意: 这个功能只在 HTML5 history 模式下可用。使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。123456const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { // return 期望滚动到哪个的位置 }})路由懒加载为了提高页面首屏加载时间,将相关的路由结合分割,提高页面效率。结合Vue的异步组件和Webpack的code splitting feature,轻松实现路由组件的懒加载。1234567const Foo = resolve => { // require.ensure 是 Webpack 的特殊语法,用来设置 code-split point // (代码分块) require.ensure(['./Foo.vue'], () => { resolve(require('./Foo.vue')) })}AMD 风格的 require1const Foo = resolve => require(['./Foo.vue'], resolve)把组件按组分块有时候我们想把某个路由下的所有组件都打包在同个异步 chunk 中。只需要 给 chunk 命名,提供 require.ensure 第三个参数作为 chunk 的名称:123const Foo = r => require.ensure([], () => r(require('./Foo.vue')), 'group-foo')const Bar = r => require.ensure([], () => r(require('./Bar.vue')), 'group-foo')const Baz = r => require.ensure([], () => r(require('./Baz.vue')), 'group-foo')Webpack 将相同 chunk 下的所有异步模块打包到一个异步块里面 —— 这也意味着我们无须明确列出 require.ensure 的依赖(传空数组就行)。webpack.config.js1234567891011121314var webpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) }, // devtool: config.build.productionSourceMap ? '#source-map' : false, output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), // chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') chunkFilename: utils.assetsPath('js/[name].[chunkhash].min.js') },API文档router-link<router-link> 组件支持用户在具有路由功能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有正确链接的 <a> 标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。也可以使用:<a v-link="{name: 'user', params: {userId: 1}">This is a user whose id is 1</a>Props参数to表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到 router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。字符串1234<!-- 字符串 --><router-link to="home">Home</router-link><!-- 渲染结果 --><a href="home">Home</a>表达式1234567891011121314<!-- 使用 v-bind 的 JS 表达式'home' --><router-link v-bind:to="'home'">Home</router-link><!-- 不写 v-bind 也可以,就像绑定别的属性一样 --><router-link :to="'home'">Home</router-link><!-- 同上 --><router-link :to="{ path: 'home' }">Home</router-link><!-- 命名的路由 --><router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link><!-- 带查询参数,下面的结果为 /register?plan=private --><router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>replace设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。1<router-link :to="{ path: '/abc'}" replace></router-link>append 相对路径设置 append 属性后,则在当前(相对)路径前添加基路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b1<router-link :to="{ path: 'relative/path'}" append></router-link>tag 渲染标签有时候想要渲染成某种标签,例如。 于是我们使用 tag prop 类指定何种标签,同样它还是会监听点击,触发导航。123<router-link to="/foo" tag="li">foo</router-link><!-- 渲染结果 --><li>foo</li>active-class设置链接激活时使用的 CSS 类名。默认值可以通过路由的构造选项 linkActiveClass 来全局配置。123456789<router-link active-class replace to="/Tap/btn">proImg</router-link>const router = new VueRouter({ mode: 'history', linkActiveClass:'link-active', routes: []});.link-active{}exact“是否激活”默认类名的依据是inclusive match (全包含匹配)。 举个例子,如果当前的路径是 /a 开头的,那么 <router-link to="/a"> 也会被设置 CSS 类名。Active Linksevents声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。默认值: ‘click’router-view<router-view> 组件是一个 functional 组件,渲染路径匹配到的视图组件。<router-view> 渲染的组件还可以内嵌自己的 <router-view>,根据嵌套路径,渲染嵌套组件。name123<router-view class="view one"></router-view><router-view class="view two" name="a"></router-view><router-view class="view three" name="b"></router-view>keep-alive12345<transition> <keep-alive> <router-view></router-view> </keep-alive></transition>路由信息对象一个 route object(路由信息对象) 表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的 route records(路由记录)。$route Watcher123456789101112131415watch: { '$route' (to, from) { const toDepth = to.path.split('/') const fromDepth = from.path.split('/') if (toDepth.length === fromDepth.length) { if (toDepth[toDepth.length - 1] === '') { this.transitionName = 'vux-pop-in' } else { this.transitionName = 'vux-pop-out' } } else { this.transitionName = toDepth < fromDepth ? 'vux-pop-in' : 'vux-pop-out' } }}123router.beforeEach((to, from, next) => { // to 和 from 都是 路由信息对象})this.$route$route.path 绝对路径$route.params 路由参数关于动态片段(如/user/:username)的键值对信息,如{username: ‘paolino’}$route.query URL查询参数请求参数,如/foo?user=1获取到query.user = 1$route.hash当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。$route.fullPath完成解析后的 URL,包含查询参数和 hash 的完整路径。$route.matched数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。1234567891011const router = new VueRouter({ routes: [ // 下面的对象就是 route record { path: '/foo', component: Foo, children: [ // 这也是个 route record { path: 'bar', component: Bar } ] } ]})当 URL 为 /foo/bar,$route.matched 将会是一个包含从上到下的所有对象(副本)。$route.name当前路由的名称,如果有的话12345{ path: '/user/:userId', name: 'user', component: User}Router 构造配置routes12345678910111213141516171819202122232425{ <!-- 路径 --> path: string; path: '', <!-- 组件 --> component?: Component, <!-- 命名路由 --> name?: string; name?: '', <!-- 命名视图组件 --> components?: { [name: string]: Component }, redirect?: string | Location | Function, alias?: string | Array<string>, <!-- 组件 --> children?: Array<RouteConfig>; children?: [], <!-- 某个路由独享的钩子 --> beforeEnter?: (to: Route, from: Route, next: Function) => void, beforeEnter: (to, from, next) => { // ... } <!-- 路由元信息 --> meta?: any meta: { requiresAuth: true }}mode1mode: 'history',hash:使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。history:依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式.abstract:支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。base应用的基路径。例如,如果整个单页应用服务在 /app/ 下,然后 base 就应该设为 “/app/“。linkActiveClass1linkActiveClass:'link-active',scrollBehavior12345const router = new VueRouter({ scrollBehavior (to, from, savedPosition) { // to 和 from 都是 路由信息对象 }})1234567891011121314151617181920212223const scrollBehavior = (to, from, savedPosition) => { if (savedPosition) { // savedPosition is only available for popstate navigations. return savedPosition } else { const position = {} // new navigation. // scroll to anchor by returning the selector if (to.hash) { position.selector = to.hash } // check if any matched route config has meta that requires scrolling to top if (to.matched.some(m => m.meta.scrollToTop)) { // cords will be used if no selector is provided, // or if the selector didn't match any element. position.x = 0 position.y = 0 } // if the returned position is falsy or an empty object, // will retain current scroll position. return position }}方法导航钩子增加全局的导航钩子router.beforeEach(guard)router.afterEach(hook)编程式导航动态的导航到一个新 urlrouter.push(location)router.replace(location)router.go(n) 到达router.back() 后退router.forward() 前进1234567891011121314151617181920212223242526router.getMatchedComponents(location?)返回目标位置或是当前路由匹配的组件数组(是数组的定义/构造类,不是实例)。通常在服务端渲染的数据预加载时时候。router.resolve(location, current?, append?)2.1.0+解析目标位置(格式和 <router-link> 的 to prop 一样),返回包含如下属性的对象:{ location: Location; route: Route; href: string;}router.addRoutes(routes)2.2.0+动态添加更多的路由规则。参数必须是一个符合 routes 选项要求的数组。router.onReady(callback)2.2.0+添加一个会在第一次路由跳转完成时被调用的回调函数。此方法通常用于等待异步的导航钩子完成,比如在进行服务端渲染的时候。参考资料routervue-router总结]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Mobile Video]]></title>
<url>%2F2017%2F03%2F25%2FVideo%2F</url>
<content type="text"><![CDATA[自用笔记:今天我们就来说一说,移动端视频Video的使用兼容问题。略测试了一下,移动端是个重灾区。基础知识属性描述autoplay自动开始播放,不会停下来等着数据载入结束。preload视频预加载controls出现控制条loop循环播放src视频URLposter用于在用户播放或者跳帧之前展示width指定视频宽度(通常在css中指定)height指定视频高度(通常在css中指定)buffered读取到哪段时间范围内的媒体被缓存了height属性描述play视频开始播放触发的事件(触发此事件,但是视频不一定可以播放)playing视频可以播放触发的事件timeupdate音频/视频(audio/video)的播放位置发生改变时触发pause视频停止播放触发的事件ended视频播放结束或中断触发的事件durationchangeprogress监听事件ended123this.$refs.video.addEventListener('ended', () => { console.log('ended')})兼容问题视频截图没有设置poster时,由于移动端设备多样,部分浏览器不支持是否显示播放按钮移动端Android微信端使用的是微信自带的播放器插件x5-video-player-type=”h5”,播放时不适用微信的播放器。iOS全屏播放没有添加playsinline【webkit-playsinline】,点击播放会弹出iphone自带的播放器,全屏播放。扩展阅读mozillaHTML的媒体支持:audio和video元素html5–移动端视频video的android兼容,去除播放控件、全屏等]]></content>
<categories>
<category>HTML</category>
</categories>
<tags>
<tag>Video</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Sublime Mac 快捷键]]></title>
<url>%2F2017%2F03%2F21%2FsublimeMac%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why符号说明⌘:command⌃:control⌥:option⇧:shift↩:enter⌫:delete全局⌃ + ⇧ + T:打开文件夹控制台 ⌘ + ⌥ + ⌃ + ->:网易云下一曲 ⌘ + ⌥ + ⌃ + <-:网易云上一曲 ⌘ + ⌥ + P:网易云暂停k通用(General)↑↓←→:上下左右移动光标,注意不是不是KJHL! Alt:调出菜单整理(clear)Tab:缩进:自动完成 Shift+Tab:去除缩进 Ctrl+KT:折叠属性 Ctrl+K0:展开所有窗口(Window)⌘ + 1、2、3:切换文件移动(Move)⌘ + <-:行首 ⌘ + ->:行尾 ⌘ + ↑:头部 ⌘ + ↓:尾部 ⌘ + ⇧ + ↑:向上全选 ⌘ + ⇧ + ↓:向下全选 ⌘ + ⌃ + ↑/↓:移动当前行 Ctrl+←/→:进行逐词移动]]></content>
<categories>
<category>Tool</category>
</categories>
<tags>
<tag>Sublime</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React初探]]></title>
<url>%2F2017%2F02%2F14%2FReact%2F</url>
<content type="text"><![CDATA[概况React 起源于 Facebook 的内部F8项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。E6语法。React 特点声明式设计 −React采用声明范式,可以轻松描述应用。高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。灵活 −React可以与已知的库或框架很好地配合。JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。官网地址简单Demo12345678910111213141516171819<!DOCTYPE html><html><head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script></head><body> <div id="example"></div> <script type="text/babel"> ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') ); </script></body></html>引入依赖实例中我们引入了三个库: react.min.js 、react-dom.min.js 和 browser.min.js:react.min.js - React 的核心库react-dom.min.js - 提供与 DOM 相关的功能browser.min.js - 用于将 JSX 语法转为 JavaScript 语法React代码1<script type="text/babel"></script>React JSX语法React 使用 JSX 来替代常规的 JavaScript。JSX 是一个看起来很像 XML 的 JavaScript 语法扩展。我们不需要一定使用 JSX,但它有以下优点:JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。它是类型安全的,在编译过程中就能发现错误。使用 JSX 编写模板更加简单快速。简单嵌套元素JSX 看起来类似 HTML ,我们可以看下实例:ReactDOM.render方法接受两个参数:一个虚拟 DOM 节点和一个真实 DOM 节点,作用是将虚拟 DOM 挂载到真实 DOM。实例:Hello, world!123ReactDOM.render(content,element);ReactDOM.render(<h1>Hello, world!</h1>,document.getElementById('example'));index1复杂嵌套元素我们可以在以上代码中嵌套多个 HTML 标签,需要使用一个 div 元素包裹它,实例中的 p 元素添加了自定义属性 data-myattribute,添加自定义属性需要使用 data- 前缀。实例:文字12345678ReactDOM.render( <div> <h1>菜鸟教程</h1> <h2>欢迎学习 React</h2> <p data-myattribute = "somevalue">这是一个很不错的 JavaScript 库!</p> </div>, mountNode);index2JavaScript 表达式我们可以在 JSX 中使用 JavaScript 表达式。表达式写在花括号 {} 中。实例如下:实例:计算123ReactDOM.render( <div><h1>{1+1}</h1></div>,mountNode);index3判断语句在 JSX 中不能使用 if else 语句,但可以使用 conditional (三元运算) 表达式来替代。以下实例中如果变量 i 等于 1 浏览器将输出 true, 如果修改 i 的值,则会输出 false.实例:判断1234567const i = 1;ReactDOM.render( <div> <h1>{i == 1 ? 'True!' : 'False'}</h1> </div>, mountNode);index4样式React 推荐使用内联样式。我们可以使用 camelCase 语法来设置内联样式. React 会在指定元素数字后自动添加 px 。以下实例演示了为 h1 元素添加 myStyle 内联样式:实例:CSS样式12345678910111213const myStyle = { fontSize: 100, lineHeight: '30px', color: '#FF0000'};ReactDOM.render( <h1 style = {myStyle}>菜鸟教程</h1>,mountNode);ReactDOM.render(<h1 style = {{fontSize: 100,lineHeight: '30px',color: '#FF0000'}}>菜鸟教程</h1>,mountNode);ReactDOM.render(<h1 className = 'class_name'>菜鸟教程</h1>,mountNode);index5注释注释需要写在花括号中,实例如下:实例:注释123456ReactDOM.render( <div> <h1>菜鸟教程</h1> {/*注释...*/} </div>,mountNode);React.Component组件基础语法HTML 标签 vs. React 组件React 可以渲染 HTML 标签 (strings) 或 React 组件 (classes)。要渲染 HTML 标签,只需在 JSX 里使用小写字母的标签名。要渲染 React 组件,只需创建一个大写字母开头的本地变量。实例:创建组件12345678class DivElement extends React.Component{ render() { return ( <div className="foo">arr</div> ); }}ReactDOM.render(<DivElement />, mountNode);实例:组件嵌套1234567891011class MyComponent extends React.Component{ render() { return <div className="MyComponent">arr</div>; }}class DivElement extends React.Component{ render() { return <MyComponent />; }}ReactDOM.render(<DivElement />, mountNode);React 的 JSX 使用大、小写的约定来区分本地组件的类和 HTML 标签。注意:由于 JSX 就是 JavaScript,一些标识符像 class 和 for 不建议作为 XML 属性名。作为替代,React DOM 使用 className 和 htmlFor 来做对应的属性。实例:组件语法12345678910111213class HelloMessage extends React.Component{ render() { return <div className="HelloMessage">arr</div>; }}class HelloMessage extends React.Component{ render() { return ( <div className="HelloMessage">arr</div> ); }}React.Component方法用于生成一个组件类 HelloMessage。实例组件类并输出信息。注意:原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头,比如 HelloMessage 不能写成 helloMessage。除此之外还需要注意组件类只能包含一个顶层标签,否则也会报错。如果我们需要向组件传递参数,可以使用 this.props 对象,实例如下:实例:获取父元素的值12345678class DivElement extends React.Component{ render() { return ( <div className="foo">{this.props.name}</div> ); }}ReactDOM.render(<DivElement name="Runoob" />, mountNode);以上实例中 name 属性通过 this.props.name 来获取(自身的数字)。注意,在添加属性时, class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。复合组件通过创建多个组件来合成一个组件,即把组件的不同功能点进行分离。以下实例我们实现了输出网站名字和网址的组件:实例:链接12345678910111213141516171819202122class WebSite extends React.Component{ render() { return ( <div className={this.props.name}><Name name={this.props.name} /><Link site={this.props.site} /></div> ); }}class Name extends React.Component{ render() { return ( <h1>{this.props.name}</h1> ); }}class Link extends React.Component{ render() { return ( <a href={this.props.site}>{this.props.site}</a> ); }}ReactDOM.render(<WebSite name="菜鸟教程" site=" http://www.runoob.com" />, mountNode);React State(状态)把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。constructor()初始状态实例:点击喜欢&不喜欢123456789101112131415161718class LikeButton extends React.Component{ constructor() { super(); this.state ={liked: false}; } handleClick() { this.setState({ liked: !this.state.liked }); } render() { let text = this.state.liked ? '喜欢' : '不喜欢'; return ( <p onClick={this.handleClick.bind(this)}>你<b>{text}</b>我。点我切换状态。</p> ); }};ReactDOM.render(<LikeButton />, mountNode);12345handleClick = ()=>{ this.setState({ liked: !this.state.liked });}constructor是组件的构造函数,会在创建实例时自动调用。…args表示组件参数,super(…args)是 ES6 规定的写法。this.state对象用来存放内部状态,这里是定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。onClick={this.handleClick.bind(this)}绑定事件,返回参数。e.target.value绑定事件后的返回值。实例:输入文字实时显示123456789101112131415161718192021class MyTitle extends React.Component{ constructor() { super(); this.state ={name: 'can you speek English!'}; } handleChange(e) { let name = e.target.value; this.setState({ name: name }); } render() { return ( <div> <input type="text" onChange={this.handleChange.bind(this)} /> <p>luuman,{this.state.name}</p> </div> ); }}ReactDOM.render(<MyTitle />, mountNode);React Propsprops通过组件获取数据基础语法实例:数据传递123456789class HelloMessage extends React.Component{ render(){ return <h1>Hello {this.props.name}</h1>; }}ReactDOM.render( <HelloMessage name="Runoob" />,mountNode);实例中 name 属性通过 this.props.name 来获取。defaultProps默认值默认Props:你可以通过defaultProps()方法为props设置默认值,实例如下:123456789class HelloMessage extends React.Component{ render(){ return <h1>Hello {this.props.name}</h1>; }}HelloMessage.defaultProps = { name: 'Runoob'}ReactDOM.render(<HelloMessage />,mountNode);1234567891011121314151617181920212223242526class WebSite extends React.Component{ render() { return ( <div className={this.props.name}><Name name={this.props.name} /><Link site={this.props.site} /></div> ); }}WebSite.defaultProps ={ name: "菜鸟教程", site: "http://www.runoob.com"}class Name extends React.Component{ render() { return ( <h1>{this.props.name}</h1> ); }}class Link extends React.Component{ render() { return ( <a href={this.props.site}>{this.props.site}</a> ); }}ReactDOM.render(<WebSite />, mountNode);this.props.children实例:点击次数12345678910111213141516171819202122class NotesList extends React.Component{ render(){ return( <ol>{ React.Children.map(this.props.children,function(child){ console.log(child); return <li>{child}</li> }) }</ol> ); }}ReactDOM.render( <NotesList> <span>hello</span> <span>world</span> <span>world</span> <span>world</span> </NotesList>, mountNode);PropTypes验证Props 使用propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。实例:判断组件属性title是否为字符串:1234567891011const name = 123;console.log(name);class HelloMessage extends React.Component{ render(){ return <h1>Hello {this.props.title}</h1>; }}HelloMessage.propTypes = { title: React.PropTypes.string}ReactDOM.render(<HelloMessage title={name} />,mountNode);如果 title 使用数字变量,控制台会出现以下错误信息:1Warning: Failed prop type: Invalid prop `title` of type `number` supplied to `HelloMessage`, expected `string`.PropTypes属性值12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667.propTypes = { // 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的 optionalArray: React.PropTypes.array, optionalBool: React.PropTypes.bool, optionalFunc: React.PropTypes.func, optionalNumber: React.PropTypes.number, optionalObject: React.PropTypes.object, optionalString: React.PropTypes.string, optionalSymbol: React.PropTypes.symbol, // 可以被渲染的对象 numbers, strings, elements 或 array optionalNode: React.PropTypes.node, // React 元素 optionalElement: React.PropTypes.element, // 用 JS 的 instanceof 操作符声明 prop 为类的实例。 optionalMessage: React.PropTypes.instanceOf(Message), // 用 enum 来限制 prop 只接受指定的值。 optionalEnum: React.PropTypes.oneOf(['News', 'Photos']), // 可以是多个对象类型中的一个 optionalUnion: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.number, React.PropTypes.instanceOf(Message) ]), // 指定类型组成的数组 optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), // 指定类型的属性构成的对象 optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), // 特定 shape 参数的对象 optionalObjectWithShape: React.PropTypes.shape({ color: React.PropTypes.string, fontSize: React.PropTypes.number }), // 任意类型加上 `isRequired` 来使 prop 不可空。 requiredFunc: React.PropTypes.func.isRequired, // 不可空的任意类型 requiredAny: React.PropTypes.any.isRequired, // 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。 customProp(props, propName, componentName) { if (!/matchme/.test(props[propName])) { return new Error( 'Invalid prop `' + propName + '` supplied to' + ' `' + componentName + '`. Validation failed.' ); } }, customArrayProp: React.PropTypes.arrayOf( function(propValue, key, componentName, location, propFullName) { if (!/matchme/.test(propValue[key])) { return new Error( 'Invalid prop `' + propFullName + '` supplied to' + ' `' + componentName + '`. Validation failed.' ); } } )}state和props区别在于props是不可变的,而子组件只能通过props来获取数据。而state可以根据与用户交互来改变。这就是为什么有些容器组件需要定义state来更新和修改数据。以下实例演示了如何在应用中组合使用state和props。我们可以在父组件中设置state,并通过在子组件上使用props将其传递到子组件上。在render函数中,我们设置name和site来获取父组件传递过来的数据。实例:链接123456789101112131415161718192021222324class WebSite extends React.Component{ constructor(props) { super(props); this.state = { name: "菜鸟教程", site: "http://www.runoob.com" }; } render(){ return <div><Name name={this.state.name} /><Link site={this.state.site} /></div> }}class Name extends React.Component{ render(){ return <h1>{this.props.name}</h1> }}class Link extends React.Component{ render(){ return <a href={this.props.site}>{this.props.site}</a> }}ReactDOM.render(<WebSite />,mountNode);React 组件 API在本章节中我们将讨论 React 组件 API。基础语法mixins去重12345678910111213141516const ExampleMixin = { componentDidMount(){ // bind some event listeners here } componentWillUnmount(){ // unbind those events here! }}class ExampleComponent extends React.Component{ mixins: [ExampleMixin]; render(){}}class AnotherComponent extends React.Component{ mixins: [ExampleMixin]; render(){}}实例:点击次数1234567891011121314151617class Counter extends React.Component{ constructor(){ super(); this.state = { clickCount: 0 }; } handleClick(){ this.setState({ clickCount: this.state.clickCount +1 }); } render(){ return <h2 onClick={this.handleClick.bind(this)}>点我!点击次数为: {this.state.clickCount}</h2>; }}ReactDOM.render(<Counter />,mountNode);React 组件生命周期组件的生命周期可分成三个状态:Mounting、Updating、UnmountingMounting:已插入真实 DOMconstructor()componentWillMount()在渲染前调用,在客户端也在服务端。render()在渲染时调用componentDidMount()在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异部操作阻塞UI)。Updating:正在被重新渲染componentWillReceiveProps()在组件接收到一个新的prop时被调用。这个方法在初始化render时不会被调用。shouldComponentUpdate()返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。可以在你确认不需要更新组件时使用。componentWillUpdate()在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。render()componentDidUpdate()在组件完成更新后立即调用。在初始化时不会被调用。Unmounting:已移出真实 DOMcomponentWillUnmount()在组件从 DOM 中移除的时候立刻被调用。实例:定时器,每隔100毫秒重新设置组件的透明度,并重新渲染123456789101112131415161718192021222324252627282930class Hello extends React.Component{ constructor() { super(); this.state = { opacity: 1.0 } } componentDidMount(){ this.timer = setInterval(function(){ let opacity = this.state.opacity; opacity -= .05; if(opacity < .1){ opacity = 1.0; } this.setState({ opacity: opacity }) }.bind(this),100) } render(){ return( <div style={{opacity: this.state.opacity}}> Hello {this.props.name} </div> ) }}ReactDOM.render(<Hello name="world" />,mountNode);实例:点击效果以下实例初始化 state , setNewnumber 用于更新 state。所有生命周期在 Content 组件中。1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253class Button extends React.Component{ constructor() { super(); this.state = { data:0 } } setNewNumber(){ this.setState({ data: this.state.data + 1 }) } render(){ return( <div> <button onClick={this.setNewNumber.bind(this)}>INCREMENT</button> <Content myNumber={this.state.data}></Content> </div> ) }}class Content extends React.Component{ componentWillMount(){ console.log('Component WILL MOUNT!') } componentDidMount(){ console.log('Component DID MOUNT!') } componentWillReceiveProps(newProps) { console.log('Component WILL RECEIVE PROPS!') } shouldComponentUpdate(newProps, newState) { return true; } componentWillUpdate(nextProps, nextState) { console.log('Component WILL UPDATE!'); } componentDidUpdate(prevProps, prevState) { console.log('Component DID UPDATE!') } componentWillUnmount(){ console.log('Component WILL UNMOUNT!') } render(){ return( <div> <h3>{this.props.myNumber}</h3> </div> ) }}ReactDOM.render(<Button />,mountNode);实例:统计时间123456789101112131415161718192021222324class Timer extends React.Component{ constructor(props) { super(props); this.state = {secondsElapsed: 0}; } tick(){ this.setState((prevState) => ({ secondsElapsed: prevState.secondsElapsed + 1 })); } componentDidMount(){ this.interval = setInterval(() => this.tick(), 1000); } componentWillUnmount(){ clearInterval(this.interval); } render(){ return ( <div>Seconds Elapsed: {this.state.secondsElapsed}</div> ); }}ReactDOM.render(<Timer />, mountNode);Lists and Keys列表遍历JSX 允许在模板中插入数组,数组会自动展开所有成员:1234567const arr = [ <h1>菜鸟教程</h1>, <h2>学的不仅是技术,更是梦想!</h2>,];ReactDOM.render( <div>{arr}</div>,mountNode);index6Array.map123const numbers = [1, 2, 3, 4, 5];const doubled = numbers.map((number) => number * 2);console.log(doubled);1234567891011121314const numbers = [1, 2, 3, 4, 5];const listItems = numbers.map((number,key) => <li key={key}>{number}</li>);console.log(listItems);ReactDOM.render(<ul>{listItems}</ul>,mountNode);const listItems = numbers.map(function(number,keys){ return( <li key={keys}> {number} </li> )});Array.forEach 遍历1234567Array.forEach((e) => { alert(e);})Array.forEach(function(e){ alert(e);})12345678910111213141516let repos = this.state.data.items;let repoList = [];repos.forEach((p,keys) => { let item = <li key={keys}><a href={p.html_url}>{p.name}</a>({p.stargazers_count} stars)<br />{p.description}</li>; repoList.push(item);})let repos = this.state.data.items;let repoList = repos.map(function(repo,index){ return( <li key={index}> <a href={repo.html_url}>{repo.name}</a>({repo.stargazers_count} stars)<br /> {repo.description} </li> );});Array.splice 删除Array.filter方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素Array.everyArray.pushHandling Events绑定事件Forms表单基础语法实例:输入文字实时显示1234567891011121314151617181920212223class HelloMessage extends React.Component{ constructor(){ super(); this.state = { value: 'Hello World!' }; } handleChange(even){ this.setState({ value: even.target.value }) } render(){ let value = this.state.value; return( <div> <input type='text' value={value} onChange={this.handleChange.bind(this)} /> <h4>{value}</h4> </div> ); }}ReactDOM.render(<HelloMessage />,mountNode);实例:输入文字实时显示你需要在父组件通过创建事件句柄 (handleChange) ,并作为 prop (updateStateProp) 传递到你的子组件上。1234567891011121314151617181920212223242526272829303132class Content extends React.Component{ render(){ return( <div> <input type='text' value={this.props.myDataProp} onChange={this.props.updataStateProp} /> <h4>{this.props.myDataProp}</h4> </div> ) }}class HelloMessage extends React.Component{ constructor(){ super(); this.state = { value: 'Hello World!' }; } handleChange(even){ this.setState({ value: even.target.value }) } render(){ let value = this.state.value; return( <div> <Content myDataProp={value} updataStateProp={this.handleChange.bind(this)} /> </div> ); }}ReactDOM.render(<HelloMessage />,mountNode);实例:点我1234567891011121314151617181920212223class HelloMessage extends React.Component{ constructor(){ super(); this.state={ value: 'Hello World!' } } handleChange(event){ this.setState({ value: 'luuman is good man!' }) } render(){ let value = this.state.value; return( <div> <button onClick={this.handleChange.bind(this)}>点我</button> <h4>{value}</h4> </div> ) }}ReactDOM.render(<HelloMessage />,mountNode);当你需要从子组件中更新父组件的 state 时,你需要在父组件通过创建事件句柄 (handleChange) ,并作为 prop (updateStateProp) 传递到你的子组件上。实例如下:实例:点我12345678910111213141516171819202122232425262728class Content extends React.Component{ render(){ return( <div> <button onClick={this.props.updateStateProp}>点我</button> <h4>{this.props.myDataProp}</h4> </div> ) }}class HelloMessage extends React.Component{ constructor(){ super(); this.state = { value: 'Hello World!' } } handleChange(event){ this.setState({ value: 'luuman is good man!' }) } render(){ let value = this.state.value; return <div><Content myDataProp={value} updateStateProp={this.handleChange.bind(this)}></Content></div> }}ReactDOM.render(<HelloMessage />,mountNode);Refs and the DOMReact RefsReact 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保在任何时间总是拿到正确的实例。使用方法:绑定一个 ref 属性到 render 的返回值上:在其它代码中,通过 this.refs 获取支撑实例:12345<input ref="myInput" />var input = this.refs.myInput;var inputValue = input.value;var inputRect = input.getBoundingClientRect();实例:点我输入框获取焦点1234567891011121314class MyComponent extends React.Component{ handleClick(){ this.refs.myInput.focus(); } render(){ return( <div> <input type='text' ref='myInput' /> <input type='button' value='点我输入框获取焦点' onClick={this.handleClick.bind(this)} /> </div> ); }}ReactDOM.render(<MyComponent />,mountNode);当组件插入到 DOM 后,ref属性添加一个组件的引用于到this.refs.name获取。实例中,我们获取了输入框的支撑实例的引用,子点击按钮后输入框获取焦点。我们也可以使用 getDOMNode()方法获取DOM元素React AJAXReact 组件的数据可以通过 componentDidMount 方法中的 Ajax 来获取,当从服务端获取数据库可以将数据存储在 state 中,再用 this.setState 方法重新渲染 UI。当使用异步加载数据时,在组件卸载前使用 componentWillUnmount 来取消未完成的请求。实例1$.get(URL,function(data){})实例:获取 Github 用户最新 gist 共享描述:12345678910111213141516171819202122232425262728293031class UserGist extends React.Component{ constructor() { super(); this.state = { username: '', lastGistUrl: '' } } componentDidMount(){ this.serverRequest = $.get(this.props.source,function(result){ let lastGist = result[0]; this.setState({ username: lastGist.owner.login, lastGistUrl: lastGist.html_url }) }.bind(this)) } componentWillUnmount(){ this.serverRequest.abort(); } render(){ return( <div> {this.state.username} <a href={this.state.lastGistUrl}>{this.state.lastGistUrl}</a> </div> ) }}ReactDOM.render(<UserGist source="https://api.github.com/users/octocat/gists" />,mountNode);实例:拉取数据123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051import $ from 'jquery';import React from 'react';import ReactDOM from 'react-dom';const mountNode = document.getElementById('root');class RipoList extends React.Component{ constructor(){ super(); this.state = { loading: true, error: null, data: null }; } componentDidMount(){ this.props.promise.then( value => this.setState({ loading: false, data: value }), error => this.setState({ loading: false, error: error }) ); } render(){ if(this.state.loading){ return <span>Loading...</span>; }else if(this.state.error != null){ return <span>Error: {this.state.error.message}</span>; }else{ let repos = this.state.data.items; let repoList = repos.map(function(repo,index){ return( <li key={index}> <a href={repo.html_url}>{repo.name}</a>({repo.stargazers_count} stars)<br /> {repo.description} </li> ); }); return( <main> <h1>Most Popular JavaScript Projects in Github</h1> <ol>{repoList}</ol> </main> ) } }}ReactDOM.render(<RipoList promise={$.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')} />,mountNode);Add-Ons 添加插件jquery12345678910111213import $ from 'jquery';import React from 'react';import ReactDOM from 'react-dom';class HelloWorld extends React.Component{ render(){ return( <div>HelloWorld</div> ); }}ReactDOM.render(<HelloWorld />,$('#example')[0]);rechartsReact图表组件库bootstrapReact组件库MarkdownEditorMarkDownReactDOMrender()12345ReactDOM.render( element, container, [callback])unmountComponentAtNode()1ReactDOM.unmountComponentAtNode(container)findDOMNode()1ReactDOM.findDOMNode(component)###onkeypress/* 在实例中,我们使用了支持多浏览器的方法,因为 keyCode 属性无法再 Firefox 浏览器中工作。但是 which 属性可以。如果浏览器支持 event.which 则使用 event.which,否则使用 event.keyCode */ES6ECMAScript 6 入门let用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。for循环的计数器1234for (let i = 0; i < 10; i++) {}console.log(i);//ReferenceError: i is not defined下面的代码如果使用var,最后输出的是101234567var a = [];for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a[6](); // 10如果使用let,声明的变量仅在块级作用域内有效,最后输出的是61234567var a = [];for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a[6](); // 6]]></content>
<categories>
<category>React</category>
</categories>
<tags>
<tag>React</tag>
</tags>
</entry>
<entry>
<title><![CDATA[用CSS实现元素垂直居中方案]]></title>
<url>%2F2017%2F01%2F02%2FCSSElementAlign%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why浮动垂直水平居中固定长度margin反向移动使用position:absolute,设置left、top、margin-left、margin-top的属性这种方法基本浏览器都能够兼容,不足之处就是需要固定宽高。12345678910.one{ position:absolute; width:200px; height:200px; top:50%; left:50%; margin-top:-100px; margin-left:-100px; background:red; }.one{position:absolute;width:200px;height:200px;top:50%;left:50%;margin-top:-100px;margin-left:-100px;background:red}fixed12345678910.two{ position:fixed; width:180px; height:180px; top:50%; left:50%; margin-top:-90px; margin-left:-90px; background:orange;}大家都知道的position:fixed,IE是不支持这个属性的.two{position:fixed;width:180px;height:180px;top:50%;left:50%;margin-top:-90px;margin-left:-90px;background:orange}宽度自动自动加清零1234567891011.three{ position:fixed; width:160px; height:160px; top:0; right:0; bottom:0; left:0; margin:auto; background:pink;}.three{position:fixed;width:160px;height:160px;top:0;right:0;bottom:0;left:0;margin:auto;background:pink}1234567891011.four{ position:absolute; width:140px; height:140px; top:0; right:0; bottom:0; left:0; margin:auto; background:black;}.four{position:absolute;width:140px;height:140px;top:0;right:0;bottom:0;left:0;margin:auto;background:#000}偏移使用css3的新属性transform:translate(x,y)属性这个方法可以不需要设定固定的宽高,在移动端用的会比较多,在移动端css3兼容的比较好123456789101112.eight{ position:absolute; width:80px; height:80px; top:50%; left:50%; transform:translate(-50%,-50%); -webkit-transform:translate(-50%,-50%); -moz-transform:translate(-50%,-50%); -ms-transform:translate(-50%,-50%); background:green;}.eight{position:absolute;width:80px;height:80px;top:50%;left:50%;transform:translate(-50%,-50%);-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);background:green}before元素最高大上的一种,使用:before元素12345678910111213141516171819202122232425.nine{ position:fixed; display:block; top:0; right:0; bottom:0; left:0; text-align:center; background:rgba(0,0,0,.5);}.nine:before{ content:''; display:inline-block; vertical-align:middle; height:100%;}.nine .content{ display:inline-block; vertical-align:middle; width:60px; height:60px; line-height:60px; color:red; background:yellow;}.nine{position:fixed;display:block;top:0;right:0;bottom:0;left:0;text-align:center;background:rgba(0,0,0,.1)}.nine:before{content:'';display:inline-block;vertical-align:middle;height:100%}.nine .content{display:inline-block;vertical-align:middle;width:60px;height:60px;line-height:60px;color:red;background:#ff0}flex文字居中文字垂直水平居中利用display:table-cell属性使内容垂直居中12345678.five{ display:table-cell; vertical-align:middle; text-align:center; width:120px; height:120px; background:purple;}.five{display:table-cell;vertical-align:middle;text-align:center;width:120px;height:120px;background:purple}文字垂直水平居中最简单的一种使行内元素居中的方法,使用line-height属性这种方法也很实用,比如使文字垂直居中对齐1234567.six{ width:100px; height:100px; line-height:100px; text-align:center; background:gray;}six.six{width:100px;height:100px;line-height:100px;text-align:center;background:gray}文字垂直水平居中使用css3的display:-webkit-box属性,再设置-webkit-box-pack:center/-webkit-box-align:center123456789.seven{ width:90px; height:90px; display:-webkit-box; -webkit-box-pack:center; -webkit-box-align:center; background:yellow; color:black;}.seven{width:90px;height:90px;display:-webkit-box;-webkit-box-pack:center;-webkit-box-align:center;background:#ff0;color:#000}]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[前端开发代码规范]]></title>
<url>%2F2016%2F12%2F31%2Fnormdev%2F</url>
<content type="text"><![CDATA[规范:你是否常常碰到以下问题:你总是看不懂他写的代码,或者读起来很吃力;你需要改他的代码却无从下手,或总是要去问他这里是什么改了会不会影响其他代码;你和他一起开发一个产品,你总是怕代码和他有冲突或互相影响;你的代码在多次维护任务之后变得越来越臃肿,越来越难以维护。解决以上问题只需一种方法——读我们的规范!开发准备了解产品和设计参加需求、交互、视觉会议,了解产品设计和项目成员。了解产品面向的设备和平台。了解产品对兼容性的要求以及是否采用响应式设计等。了解产品要使用的技术(WEB技术、桌面技术、APP技术、模板语言、混合模式等)。提出疑问和见解在交互或视觉会议中结合技术要求,提出疑问和见解。提出可能存在的问题(技术实现问题、性能问题等),协商解决方案(如优雅退化)并达成共识。提出已有新技术可能在产品中的应用场景,协助产品创新。技术调研和培训是否需要技术调研,提出可能存在的风险。进行技术调研,产出技术demo,展示demo,反馈调研结果。技术调研的内容可以先咨询经验丰富的前端工程师或前端技术组。经验不足或新入职员工,可提出培训申请。你可以把难以解决的技术问题提交给NEC,NEC将帮助你解决问题。了解NEC,特别是代码规范和技术demo。预算人力和时间根据项目时间要求及工作量,预算人力和时间。预算开发周期和阶段性产出。提醒需求方在项目管理平台中创建项目并加入项目成员,创建SVN并设置成员权限。开发准备CSS文件的分类]]></content>
<categories>
<category>Norm</category>
</categories>
<tags>
<tag>Development</tag>
</tags>
</entry>
<entry>
<title><![CDATA[CSS前端代码规范]]></title>
<url>%2F2016%2F12%2F31%2FnormCSS%2F</url>
<content type="text"><![CDATA[规范:你是否常常碰到以下问题:你总是看不懂他写的代码,或者读起来很吃力;你需要改他的代码却无从下手,或总是要去问他这里是什么改了会不会影响其他代码;你和他一起开发一个产品,你总是怕代码和他有冲突或互相影响;你的代码在多次维护任务之后变得越来越臃肿,越来越难以维护。解决以上问题只需一种方法——读我们的规范!分类方法CSS文件的分类公共型样式:global“标签的重置和设置默认值”、“统一调用背景图和清除浮动或其他需统一处理的长样式”、“网站通用布局”、“通用模块和其扩展”、“元件和其扩展”、“功能类样式”、“皮肤类样式”。特殊型样式:index当某个栏目或页面的样式与网站整体差异较大或者维护率较高时,可以独立引用一个样式“特殊的布局、模块和元件及扩展”、“特殊的功能、颜色和背景”,也可以是某个大型控件或模块的独立样式。皮肤型样式:skin如果产品需要换肤功能,那么我们需要将颜色、背景等抽离出来放在这里。CSS内部的分类及其顺序重置(reset)和默认(base)(tags):消除默认样式和浏览器差异,并设置部分标签的初始样式,以减少后面的重复劳动!你可以根据你的网站需求设置!统一处理:建议在这个位置统一调用背景图(这里指多个布局或模块或元件共用的图)和清除浮动(这里指通用性较高的布局、模块、元件内的清除)等统一设置处理的样式!布局(grid)(.g-):将页面分割为几个大块,通常有头部、主体、主栏、侧栏、尾部等!模块(module)(.m-):通常是一个语义化的可以重复使用的较大的整体!比如导航、登录、注册、各种列表、评论、搜索等!元件(unit)(.u-):通常是一个不可再分的较为小巧的个体,通常被重复用于各种模块中!比如按钮、输入框、loading、图标等!功能(function)(.f-):为方便一些常用样式的使用,我们将这些使用率较高的样式剥离出来,按需使用,通常这些选择器具有固定样式表现,比如清除浮动等!不可滥用!皮肤(skin)(.s-):如果你需要把皮肤型的样式抽离出来,通常为文字色、背景色(图)、边框色等,非换肤型网站通常只提取文字色!非换肤型网站不可滥用此类!状态(.z-):为状态类样式加入前缀,统一标识,方便识别,她只能组合使用或作为后代出现(.u-ipt.z-dis{},.m-list li.z-sel{}),具体详见命名规则的扩展相关项。12345678910111213141516171819/* 重置 */div,p,ul,ol,li{margin:0;padding:0;}/* 默认 */strong,em{font-style:normal;font-weight:bold;}/* 统一调用背景图 */.m-logo a,.m-nav a,.m-nav em{background:url(images/sprite.png) no-repeat 9999px 9999px;}/* 统一清除浮动 */.g-bdc:after,.m-dimg ul:after,.u-tab:after{display:block;visibility:hidden;clear:both;height:0;overflow:hidden;content:'.';}.g-bdc,.m-dimg ul,.u-tab{zoom:1;}/* 布局 */.g-sd{float:left;width:300px;}/* 模块 */.m-logo{width:200px;height:50px;}/* 元件 */.u-btn{height:20px;border:1px solid #333;}/* 功能 */.f-tac{text-align:center;}/* 皮肤 */.s-fc,a.s-fc:hover{color:#fff;}命名规则使用类选择器,放弃ID选择器ID在一个页面中的唯一性导致了如果以ID为选择器来写CSS,就无法重用。NEC特殊字符:”-“连字符“-“在本规范中并不表示连字符的含义。她只表示两种含义:分类前缀分隔符、扩展分隔符,详见以下具体规则。分类的命名方法:使用单个字母+”-“为前缀布局(grid)(.g-);模块(module)(.m-);元件(unit)(.u-);功能(function)(.f-);皮肤(skin)(.s-);状态(.z-)。对以上的解释详情参见:分类方法中的“CSS内部的分类及其顺序”。注:在你样式中的选择器总是要以上面前五类开头,然后在里面使用后代选择器。如果这五类不能满足你的需求,你可以另外定义一个或多个大类,但必须符合单个字母+”-“为前缀的命名规则,即 .x- 的格式。特殊:.j-将被专用于JS获取节点,请勿使用.j-定义样式。后代选择器命名约定不以单个字母+”-“为前缀且长度大于等于2的类选择器为后代选择器,如:.item为m-list模块里的每一个项,.text为m-list模块里的文本部分:.m-list .item{}.m-list .text{}。一个语义化的标签也可以是后代选择器,比如:.m-list li{}。不允许单个字母的类选择器出现,原因详见下面的“模块和元件的后代选择器的扩展类”。通过使用后代选择器的方法,你不需要考虑他的命名是否已被使用,因为他只在当前模块或元件中生效,同样的样式名可以在不同的模块或元件中重复使用,互不干扰;在多人协作或者分模块协作的时候效果尤为明显!后代选择器不需要完整表现结构树层级,尽量能短则短。注:后代选择器不要在页面布局中使用,因为污染的可能性较大;/* 这里的.itm和.cnt只在.m-list中有效 */ .m-list{margin:0;padding:0;} .m-list .itm{margin:1px;padding:1px;} .m-list .cnt{margin-left:100px;} /* 这里的.cnt和.num只在.m-page中有效 */ .m-page{height:20px;} .m-page .cnt{text-align:center;} .m-page .num{border:1px solid #ddd;}命名应简约而不失语义/* 反对:表现化的或没有语义的命名 */ .m-abc .green2{} .g-left2{} /* 推荐:使用有语义的简短的命名 */ .m-list .wrap2{} .g-side2{}相同语义的不同类命名方法:直接加数字或字母区分即可(如:.m-list、.m-list2、.m-list3等,都是列表模块,但是是完全不一样的模块)。其他举例:.f-fw0、.f-fw1、.s-fc0、.s-fc1、.m-logo2、.m-logo3、u-btn、u-btn2等等。模块和元件的扩展类的命名方法当A、B、C、…它们类型相同且外形相似区别不大,那么就以它们中出现率最高的做成基类,其他做成基类的扩展。方法:+“-”+数字或字母(如:.m-list的扩展类为.m-list-1、.m-list-2等)。补充:基类自身可以独立使用(如:class=”m-list”即可),扩展类必须基于基类使用(如:class=”m-list m-list-2”)。如果你的扩展类是表示不同状态,那么你可以这样命名:u-btn-dis,u-btn-hov,m-box-sel,m-box-hov等等,然后像这样使用:class=”u-btn u-btn-dis”。如果你的网站可以不兼容IE6等浏览器,那么你标识状态的方法也可以采取独立状态分类(.z-)方法:.u-btn.z-dis,.m-box.z-sel,然后像这样使用:class=”u-btn z-dis”。模块和元件的后代选择器的扩展类有时候模块内会有些类似的东西,如果你没有把它们做成元件和扩展,那么也可以使用后代选择器和扩展。后代选择器:.m-login .btn{}。后代选择器扩展:.m-login .btn-1{},.m-login .btn-dis{}。同样也可以采取独立状态分类(.z-)方法:.m-login .btn.z-dis{},然后像这样使用:class=”btn z-dis”。注:此方法用于类选择器,直接使用标签做为选择器的则不需要使用此命名方法。注:为防止后代选择器的扩展类和大类命名规范冲突,后代选择器不允许使用单个字母。比如:.m-list .a{}是不允许的,因为当这个.a需要扩展的时候就会变成.a-bb,这样就和大类的命名规范冲突。分组选择器有时可以代替扩展方法有时候虽然两个同类型的模块很相似,但是你希望他们之间不要有依赖关系,也就是说你不希望使用扩展的方法,那么你可以通过合并选择器来设置共性的样式。使用本方法的前提是:相同类型、功能和外观都相似,写在同一片代码区域方便维护。/* 两个元件共性的样式 */ .u-tip1,.u-tip2{} .u-tip1 .itm,.u-tip2 .itm{} /* 在分别是两个元件各自的样式 */ /* tip1 */ .u-tip1{} .u-tip1 .itm{} /* tip2 */ .u-tip2{} .u-tip2 .itm{}防止污染和被污染当模块或元件之间互相嵌套,且使用了相同的标签选择器或其他后代选择器,那么里面的选择器就会被外面相同的选择器所影响。所以,如果你的模块或元件可能嵌套或被嵌套于其他模块或元件,那么要慎用标签选择器,必要时采用类选择器,并注意命名方式,可以采用.m-layer .layerxxx、.m-list2 .list2xxx的形式来降低后代选择器的污染性。代码格式选择器、属性和值都使用小写在xhtml标准中规定了所有标签、属性和值都小写,CSS也是如此。单行写完一个选择器定义便于选择器的寻找和阅读,也便于插入新选择器和编辑,便于模块等的识别。去除多余空格,使代码紧凑减少换行。如果有嵌套定义,可以采取内部单行的形式。/* 单行定义一个选择器 */ .m-list li,.m-list h3{width:100px;padding:10px;border:1px solid #ddd;} /* 这是一个有嵌套定义的选择器 */ @media all and (max-width:600px){ .m-class1 .itm{height:17px;line-height:17px;font-size:12px;} .m-class2 .itm{width:100px;overflow:hidden;} } @-webkit-keyframes showitm{ 0%{height:0;opacity:0;} 100%{height:100px;opacity:1;} }最后一个值也以分号结尾通常在大括号结束前的值可以省略分号,但是这样做会对修改、添加和维护工作带来不必要的失误和麻烦。省略值为0时的单位为节省不必要的字节同时也使阅读方便,我们将0px、0em、0%等值缩写为0。.m-box{margin:0 10px;background-position:50% 0;}使用单引号省略url引用中的引号,其他需要引号的地方使用单引号。.m-box{background:url(bg.png);} .m-box:after{content:'.';}使用16进制表示颜色值除非你需要透明度而使用rgba,否则都使用#f0f0f0这样的表示方法,并尽量缩写。.m-box{color:#f00;background:rgba(0,0,0,0.5);}根据属性的重要性按顺序书写只遵循横向顺序即可,先显示定位布局类属性,后盒模型等自身属性,最后是文本类及修饰类属性。| → | 显示属性 | 自身属性 | 文本属性和其他修饰 || | —– |:—-:| —– |:—-:|| | display | width | font || | visibility | height | text-align || | position | margin | text-decoration || | float | padding | vertical-align || | clear | border | white-space || | list-style | overflow | color || | top | min-width | background |.m-box{position:relative;width:600px;margin:0 auto 10px;text-align:center;color:#000;}如果属性间存在关联性,则不要隔开写。/* 这里的height和line-height有关联性 */ .m-box{position:relative;height:20px;line-height:20px;padding:5px;color:#000;}私有在前,标准在后先写带有浏览器私有标志的,后写W3C标准的。.m-box{-webkit-box-shadow:0 0 0 #000;-moz-box-shadow:0 0 0 #000;box-shadow:0 0 0 #000;}注释格式:/* 注释文字 */对选择器的注释统一写在被注释对象的上一行,对属性及值的注释写于分号后。注释内容两端需空格,已确保即使在编码错误的情况下也可以正确解析样式。在必要的情况下,可以使用块状注释,块状注释保持统一的缩进对齐。原则上每个系列的样式都需要有一个注释,言简意赅的表明名称、用途、注意事项等。/* 块状注释文字 * 块状注释文字 * 块状注释文字 */ .m-list{width:500px;} .m-list li{height:20px;line-height:20px;/* 这里是对line-height的一个注释 */overflow:hidden;} .m-list li a{color:#333;} /* 单行注释文字 */ .m-list li em{color:#666;}原则上不允许使用Hack很多不兼容问题可以通过改变方法和思路来解决,并非一定需要Hack,根据经验你完全可以绕过某些兼容问题。一种合理的结构和合理的样式,是极少会碰到兼容问题的。由于浏览器自身缺陷,我们无法避开的时候,可以允许使用适当的Hack。统一Hack方法统一使用“*”和“_”分别对IE7和6进行Hack。如下代码所示:/* IE7会显示灰色#888,IE6会显示白色#fff,其他浏览器显示黑色#000 */ .m-list{color:#000;*color:#888;_color:#fff;}建议并适当缩写值“建议并适当”是因为缩写总是会包含一系列的值,而有时候我们并不希望设置某一值,反而造成了麻烦,那么这时候你可以不缩写,而是分开写。当然,在一切可以缩写的情况下,请务必缩写,它最大的好处就是节省了字节,便于维护,并使阅读更加一目了然。缩写方法请查阅css手册。选择器顺序请综合考虑以下顺序依据:从大到小(以选择器的范围为准)从低到高(以等级上的高低为准)从先到后(以结构上的先后为准)从父到子(以结构上的嵌套为准)1234567891011121314以下仅为简单示范:/* 从大到小 */.m-list p{margin:0;padding:0;}.m-list p.part{margin:1px;padding:1px;}/* 从低到高 */.m-logo a{color:#f00;}.m-logo a:hover{color:#fff;}/* 从先到后 */.g-hd{height:60px;}.g-bd{height:60px;}.g-ft{height:60px;}/* 从父到子 */.m-list{width:300px;}.m-list .itm{float:left;}选择器等级a = 行内样式style。b = ID选择器的数量。c = 类、伪类和属性选择器的数量。d = 类型选择器和伪元素选择器的数量。选择器等级(a,b,c,d)style=””1,0,0,0#wrapper #content {}0,2,0,0#content .dateposted {}0,1,1,0div#content {}0,1,0,1#content p {}0,1,0,1#content {}0,1,0,0p.comment .dateposted {}0,0,2,1div.comment p {}0,0,1,2.comment p {}0,0,1,1p.comment {}0,0,1,1.comment {}0,0,1,0div p {}0,0,0,2p {}0,0,0,1优化方案值缩写缩写值可以减少CSS文件大小,并增加可读性和可维护性。但并非所有的值都必须缩写,因为当一个属性的值缩写时,总是会将所有项都设置一遍,而有时候我们不希望设置值里的某些项。/* 比如我们用下面这个样式来让某个定宽的容器水平居中,我们要的只是left和right, * 而top和bottom不是这个样式要关心的(如果设置了反倒会影响其他样式在这个容器上的使用), * 所以这时我们就不需要缩写 */ .f-mgha{margin-left:auto;margin-right:auto;} /* 比如下面这个模块的样式设置,我们确实需要设置padding的所有项,于是我们就可以采用缩写 */ .m-link{padding:6px 12px;} 常用的缩写方法请参见代码格式。避免耗性能的属性以下所举列的属性可能造成渲染性能问题。不过有时候需求大于一切……/* expression */ .class{width:expression(this.width>100?'100px':'auto');} /* filter */ .class{filter:alpha(opacity=50);}选择器合并即CSS选择器组合,可以一次定义多个选择器,为你节省很多字节和宝贵时间。通常我们会将定义相同的或者有大部分属性值相同(确实是因为相关而相同)的一系列选择器组合到一起(采用逗号的方法)来统一定义。/* 以下对布局类选择器统一做了清除浮动的操作 */ .g-hd:after,.g-bd:after,.g-ft:after{display:block;visibility:hidden;clear:both;height:0;content:".";} .g-hd,.g-bd,.g-ft{zoom:1;} /* 通常background总是会占用很多字节,所以一般情况下,我们都会这样统一调用 */ .m-logo,.m-help,.m-list li,.u-tab li,.u-tab li a{background:url(../images/sprite.png) no-repeat 9999px 9999px;} .m-logo{background-position:0 0;} /* 以下是某个元件的写法,因为确实很多元素是联动的或相关的,所以采用了组合写法,可以方便理解和修改 */ .u-tab li,.u-tab li a{display:inline;float:left;height:30px;line-height:30px;} .u-tab li{margin:0 3px;} .u-tab li a{padding:0 6px;}背景图优化合并图片本身的优化:图像质量要求和图像文件大小决定你用什么格式的图片,用较小的图片文件呈现较好的图像质量。当图片色彩过于丰富且无透明要求时,建议采用jpg格式并保存为较高质量。当图片色彩过于丰富又有透明或半透明要求或阴影效果时,建议采用png24格式,并对IE6进行png8退化(或在不得已情况下使用滤镜)。当图片色彩不太丰富时无论有无透明要求,请采用png8格式,大多数情况下建议采用这种格式。当图片有动画时,只能使用gif格式。你可以使用工具对图片进行再次压缩,但前提是不会影响色彩和透明。多张图片的合并:单个图标之间必须保留空隙,空隙大小由容器大小及显示方式决定。这样做的好处是既考虑了“容错性”又提高了图片的可维护性。图标的排列方式,也由容器大小及显示方式决定。排列方式分为以下几种:横向排列(容器宽度有限)、纵向排列(容器高度有限)、斜线排列(容器宽高不限),靠左排列(容器背景居左)、靠右排列(容器背景居右)、水平居中排列(容器背景水平居中)、垂直居中排列(容器背景垂直居中)。合并后图片大小不宜超过50K,建议大小在20K-50K之间。为保证多次修改后的图片质量,请保留一份PSD原始图,修改和添加都在PSD中进行,最后导出png。分类合并:并不是把所有的图标都合并在一张图片里就是最好的,除了要控制图片大小之外还要注意以下方法。按照图片排列方式,把排列方式一样的图片进行合并,便于样式控制。按照模块或元件,把同属于一个模块或元件的图片进行合并,方便模块或元件的维护。按照图片大小,把大小一致或差不多的图片进行合并,可充分利用图片空间。按照图片色彩,把色彩一致或差不多的图片进行合并,保证合并后图片的色彩不过于丰富,可防止色彩失真。综合以上方法进行合并。Hack的避免当避免的代价较大时,可以使用Hack而不避免,比如你需要增加很多HTML或多写很多CSS时会得不偿失。丰富的实战经验可以帮助你了解那些常见问题并用多种不同的思路来避免它,所以经验和思维方法在这里显得很重要。根据你自己的能力来解决Hack的问题,我们不建议你用一个自己都没有把握的方法来避免Hack,因为也许你这个方法本身存在你没有发现的问题。如果CSS可以做到,就不要使用JS让CSS做更多的事,减轻JS开发量。用CSS控制交互或视觉的变化,JS只需要更改className。利用CSS一次性更改多个节点样式,避免多次渲染,提高渲染效率。如果你的产品允许不兼容低版本浏览器,那么动画实现可以交给CSS。便于阅读修改如果你做到了“CSS规范”的所有要求,自然你也就写出了一个便于阅读和修改的漂亮的CSS。当然,代码格式和命名规则是相对重要一些的。清晰的CSS模块如果你做到了命名规则的要求,你的CSS模块也就清晰可见了。用“注释”来说明每一个模块对于较大的CSS文件来说显得尤为重要。文件压缩合理的书写CSS能很大程度上减少文件大小,完成后,在不损坏文件内容的情况下,想尽一切办法压缩你的CSS,你可以借助压缩工具把注释和多余的空格、换行去掉。压缩工具详见:“HTML/CSS工具”部分。其他格式优化优化方法请参见代码格式。最佳实践最佳选择器写法(模块)/* 这是某个模块 */ .m-nav{}/* 模块容器 */ .m-nav li,.m-nav a{}/* 先共性 优化组合 */ .m-nav li{}/* 后个性 语义化标签选择器 */ .m-nav a{}/* 后个性中的共性 按结构顺序 */ .m-nav a.a1{}/* 后个性中的个性 */ .m-nav a.a2{}/* 后个性中的个性 */ .m-nav .z-crt a{}/* 交互状态变化 */ .m-nav .z-crt a.a1{} .m-nav .z-crt a.a2{} .m-nav .btn{}/* 典型后代选择器 */ .m-nav .btn-1{}/* 典型后代选择器扩展 */ .m-nav .btn-dis{}/* 典型后代选择器扩展(状态) */ .m-nav .btn.z-dis{}/* 作用同上,请二选一(如果可以不兼容IE6时使用) */ .m-nav .m-sch{}/* 控制内部其他模块位置 */ .m-nav .u-sel{}/* 控制内部其他元件位置 */ .m-nav-1{}/* 模块扩展 */ .m-nav-1 li{} .m-nav-dis{}/* 模块扩展(状态) */ .m-nav.z-dis{}/* 作用同上,请二选一(如果可以不兼容IE6时使用) */统一语义理解和命名布局(.g-)语义命名简写文档docdoc头部headhd主体bodybd尾部footft主栏mainmn主栏子容器maincmnc侧栏sidesd侧栏子容器sidecsdc盒容器wrap/boxwrap/box模块(.m-)、元件(.u-)语义命名简写导航navnav子导航subnavsnav面包屑crumbcrm菜单menumenu选项卡tabtab标题区headtitle hd/tt内容区bodycontent bd/ct列表listlst表格tabletb表单formfm热点hothot排行toptop登录loginlog标志logologo广告advertisead搜索searchsch幻灯slidesld提示tipstips帮助helphelp新闻newsnews下载downloaddld注册registreg投票votevote版权copyrightcprt结果resultrst标题titlett按钮buttonbtn输入inputipt功能(.f-)语义命名简写浮动清除clearbothcb向左浮动floatleftfl向右浮动floatrightfr内联块级inlineblockib文本居中textaligncentertac文本居右textalignrighttar文本居左textalignlefttal垂直居中verticalalignmiddlevam溢出隐藏overflowhiddenoh完全消失displaynonedn字体大小fontsizefs字体粗细fontweightfw皮肤(.s-)语义命名简写字体颜色fontcolorfc背景backgroundbg背景颜色backgroundcolorbgc背景图片backgroundimagebgi背景定位backgroundpositionbgp边框颜色bordercolorbdc状态(.z-)语义命名简写选中selectedsel当前currentcrt显示showshow隐藏hidehide打开openopen关闭closeclose出错errorerr不可用disableddis典型错误不符合NEC规范的选择器用法.class{}不要以一个没有类别的样式作为主选择器,这样的选择器只能作为后代选择器使用,比如.m-xxx .class{}。.m-xxx div{}不要以没有语义的标签作为选择器,这会造成大面积污染,除非你可以断定现在或将来你的这个选择器不会污染其他同类。.g-xxx .class{}不要在页面布局中使用后代选择器,因为这个后代选择器可能会污染里面的元素。.g-xxx .m-yyy{}.g-xxx .u-yyy{}不要用布局去控制模块或元件,模块和元件应与布局分离独立。.m-xxx .f-xxx{}.m-xxx .s-xxx{}不要通过模块或其他类来重定义或修改或添加已经定义好的功能类选择器和皮肤类选择器。.m-xxx .class .class .class .class{}不要将选择器写的过于冗长,这会额外增加文件大小并且限制了太小范围的选择器,使树形结构过于严格应用范围过于局限,建议3-4个长度之内写完。选择器并不需要完整反映结构嵌套顺序,相反,能简则简。.m-xxx .m-yyy .zzz{}不要越级控制,如果.zzz是.m-yyy的后代选择器,那么不允许.m-yyy之外的选择器控制或修改.zzz。此时可以使用.m-yyy的扩展来修改.zzz,比如.m-yyy-1 .zzz{}。扩展类使用错误扩展类必须和其基类同时使用于同一个节点。错误: class="g-xxx g-yyy-1" class="m-xxx-1" class="u-xxx u-yyy-1" class="xxx-yyy"。 正确: class="g-xxx g-xxx-1" class="m-xxx m-xxx-1" class="u-yyy u-yyy-1" class="xxx xxx-yyy"。参考资料:编写出色CSS代码的13个建议]]></content>
<categories>
<category>Norm</category>
</categories>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[HTML前端代码规范]]></title>
<url>%2F2016%2F12%2F31%2Fnormhtml%2F</url>
<content type="text"><![CDATA[规范:你是否常常碰到以下问题:你总是看不懂他写的代码,或者读起来很吃力;你需要改他的代码却无从下手,或总是要去问他这里是什么改了会不会影响其他代码;你和他一起开发一个产品,你总是怕代码和他有冲突或互相影响;你的代码在多次维护任务之后变得越来越臃肿,越来越难以维护。解决以上问题只需一种方法——读我们的规范!整体结构HTML基础设施文件应以“”首行顶格开始,推荐使用“”。必须申明文档的编码charset,且与文件本身编码保持一致,推荐使用UTF-8编码。根据页面内容和需求填写适当的keywords和description。页面title是极为重要的不可缺少的一项。123456789101112131415<!DOCTYPE html><html><head><meta charset="utf-8"/><title>NEC:更好的CSS方案</title><meta name="keywords" content=""/><meta name="description" content=""/><meta name="viewport" content="width=device-width"/><link rel="stylesheet" href="css/style.css"/><link rel="shortcut icon" href="img/favicon.ico"/><link rel="apple-touch-icon" href="img/touchicon.png"/></head><body></body></html>结构顺序和视觉顺序基本保持一致按照从上至下、从左到右的视觉顺序书写HTML结构。有时候为了便于搜索引擎抓取,我们也会将重要内容在HTML结构顺序上提前。用div代替table布局,可以使HTML更具灵活性,也方便利用CSS控制。table不建议用于布局,但表现具有明显表格形式的数据,table还是首选。结构、表现、行为三者分离,避免内联使用link将css文件引入,并置于head中。使用script将js文件引入,并置于body底部。保持良好的简洁的树形结构每一个块级元素都另起一行,每一行都使用Tab缩进对齐(head和body的子元素不需要缩进)。删除冗余的行尾的空格。使用4个空格代替1个Tab(大多数编辑器中可设置)。对于内容较为简单的表格,建议将tr写成单行。你也可以在大的模块之间用空行隔开,使模块更清晰。1234567891011121314151617181920<body><!-- 侧栏内容区 --><div class="m-side"> <div class="side"> <div class="sidein"> <!-- 热门标签 --> <div class="sideblk"> <div class="m-hd3"><h3 class="tit">热门标签</h3> </div> ... </div> <!-- 最热TOP5 --> <div class="sideblk"> <div class="m-hd3"><h3 class="tit">最热TOP5</h3> <a href="#" class="s-fc02 f-fr">更多»</a></div> ... </div> </div> </div></div><!-- /侧栏内容区 --></body>另外,请做到以下几点结构上如果可以并列书写,就不要嵌套。如果可以写成<div></div><div></div>那么就不要写成<div><div></div></div>如果结构已经可以满足视觉和语义的要求,那么就不要有额外的冗余的结构。比如<div><h2></h2></div>已经能满足要求,那么就不要再写成<div><div><h2></h2></div></div>一个标签上引用的className不要过多,越少越好。比如不要出现这种情况:<div class="class1 class2 class3 class4"></div>对于一个语义化的内部标签,应尽量避免使用className。比如在这样一个列表中,li标签中的itm应去除:<ul class="m-help"><li class="itm"></li><li class="itm"></li></ul>代码格式说明文案的注释方法采用类似标签闭合的写法,与HTML统一格式;注释文案两头空格,与CSS注释统一格式。开始注释:(文案两头空格)。结束注释:(文案前加“/”符号,类似标签的闭合)。允许只有开始注释!1234567891011121314<!-- 头部 --><div class="g-hd"> <!-- LOGO --> <h1 class="m-logo"><a href="#">LOGO</a></h1> <!-- /LOGO --> <!-- 导航 --> <ul class="m-nav"> <li><a href="#">NAV1</a></li> <li><a href="#">NAV2</a></li> <!-- 更多导航项 --> </ul> <!-- /导航 --></div><!-- /头部 -->代码本身的注释方法单行代码的注释也保持同行,两端空格;多行代码的注释起始和结尾都另起一行并左缩进对齐。1234567<!-- <h1 class="m-logo"><a href="#">LOGO</a></h1> --><!--<ul class="m-nav"> <li><a href="#">NAV1</a></li> <li><a href="#">NAV2</a></li></ul>-->HTML注释在IE6中的BUG如果两个浮动元素之间存在注释,那么可能导致布局错位或文字的BUG。所以,这种情况下,我们通常将注释去掉,或者索性采用模板语言(ftl、vm)的注释。严格的嵌套尽可能以最严格的xhtml strict标准来嵌套,比如内联元素不能包含块级元素等等。正确闭合标签且必须闭合。严格的属性属性和值全部小写,每个属性都必须有一个值,每个值必须加双引号。没有值的属性必须使用自己的名称做为值(checked、disabled、readonly、selected等等)。可以省略style标签和script标签的type属性。常用的标签| 标签 | 语义 | 嵌套常见错误 | 常用属性(加粗的为不可缺少的或建议的) || —– | —– |:—-:| —– |:—-:|| a | 超链接/锚 | a不可嵌套a | href,name,title,rel,target || br | 换行 | | || button | 按钮 | 不可嵌套表单元素 | type,disabled || dd | 定义列表中的定义(描述内容) | 只能以dl为父容器,对应一个dt | || del | 文本删除 | | || div | 块级容器 | | || dl | 定义列表 | 只能嵌套dt和dd | || dt | 定义列表中的定义术语 | 只能以dl为父容器,对应多个dd | || em | 强调文本 | | || form | 表单 | action |,target,method,name || h1 | 标题 | 从h1到h6,不可嵌套块级元素 | || iframe | 内嵌一个网页 | frameborder |,width,height,src,scrolling,name || img | 图像 | alt |,src,width,height || input | 各种表单控件 | type |,name,value,checked,disabled,maxlength,readonly,accesskey || label | 标签为input元素定义标注 | for | || li | 列表项 | 只能以ul或ol为父容器 | || link | 引用样式或icon | 不可嵌套任何元素 | type,rel,href || meta | 文档信息 | 只用于head | content,http-equiv,name || ol | 有序列表 | 只能嵌套li | || option | select中的一个选项 | 仅用于select | value,selected,disabled || p | 段落 | 不能嵌套块级元素 | || script | 引用脚本 | 不可嵌套任何元素 | type,src || select | 列表框或下拉框 | 只能嵌套option或optgroup | name,disabled,multiple || span | 内联容器 | | || strong | 强调文本 | | || style | 引用样式 | 不可嵌套任何元素 | type,media || sub | 下标 | | || sup | 上标 | | || table | 表格 | 只可嵌套表格元素 | width,align,background,cellpadding,cellspacing,summary,border || tbody | 表格主体 | 只用于table | || td | 表格中的单元格 | 只用于tr | colspan,rowspan || textarea | 多行文本输入控件 | name |,accesskey,disabled,readonly,rows,cols || tfoot | 表格表尾 | 只用于table | || th | 表格中的标题单元格 | 只用于tr | colspan,rowspan || thead | 表格表头 | 只用于table | || title | 文档标题 | 只用于head | || tr | 表格行 | 嵌套于table或thead、tbody、tfoot | || ul | 无序列表 | 只能嵌套li | |内容语义CSS文件的分类内容类型决定使用的语义标签在网页中某种类型的内容必定需要某种特定的HTML标签来承载,也就是我们常常提到的根据你的内容语义化HTML结构。加强“资源型”内容的可访问性和可用性在资源型的内容上加入描述文案,比如给img添加alt属性,在audio内加入文案和链接等等。加强“不可见”内容的可访问性背景图上的文字应该同时写在html中,并使用css使其不可见,有利于搜索引擎抓取你的内容,也可以在css失效的情况下看到内容。适当使用实体以实体代替与HTML语法相同的字符,避免浏览解析错误。常用HTML字符实体(建议使用实体):字符名称实体名实体数“双引号""&&符&&<左尖括号(小于号)<<>右尖括号(大于号)>>空格  中文全角空格 常用特殊字符实体(不建议使用实体):字符名称实体名实体数¥元¥¥¦断竖线¦¦©版权©©®注册商标R®®™商标TM™™·间隔符··«左双尖括号««»右双尖括号»»°度°°×乘××÷除÷÷‰千分比‰‰邮件内容邮件环境邮件内容所在上下文或者说所在外部容器(以下简称环境)都是由邮箱服务商决定的,这就要求邮件内容需要在任何一种情况下都要正确显示。这些环境可能是以下某几种情况:可能是个iframe,你的内容是被放在body里面的;可能只是个div,你的内容就被放在这个div里面。可能邮箱自身设置了些css,他可能对你产生未知的影响。可能根本没有申明doctype,即使申明了,也不是你想要的doctype。避免被嵌套在不正确的容器里惑:因为容器可能是body或div,所以,我们邮件内容不应该是一个完整的html。解:所以邮件内容应该是以div为根节点的html片段。避免css冲突或被覆盖惑:因为环境中可能已经设置了css,比如一些reset、一些.class。解:所以我们只能使用行内style来确保我们的效果,并且在内容根节点上设置基础style,并且尽量使用div、span等无语义标签。1234567891011121314<!-- 根节点 --><div style="width:600px;text-align:left;color:#000;font:normal 12px/15px arial,simsun;background:#fff;"> 内容区域</div><!-- 根节点-邮件内容居中 --><div style="text-align:center;"> <div style="width:600px;margin:0 auto;text-align:left;color:#000;font:normal 12px/15px arial,simsun;background:#fff;"> 内容区域 </div></div><!-- 如果使用语义化标签,那么需要多写一些style,以避免被环境中的css覆盖 --><h2 style="width:100px;height:100px;margin:0;padding:0;fong-weight:normal;font-size:12px;"></h2><!-- 而使用无语义标签,就可以省下很多style --><div style="width:100px;height:100px;"></div>避免盒模型错误惑:因为doctype的不确定性,我们在写style的时候,应该考虑无论doctype是什么情况,都可以正常显示,doctype影响最大的就是盒模型的解析。解:所以我们要将盒模型拆分开来写,比如我们将原本要定义在某个div上的height和padding分别写到这个div和他的父元素或子元素上。123<div style="height:100px;padding:20px 0;">内容</div><!-- 上面的写法应该改成以下写法 --><div style="padding:20px 0;"><div style="height:100px;">内容</div></div>其他注意事项因为只能使用行内style,所以清除浮动需要使用额外标签。避免使用绝对定位,可能会被过滤。避免使用js,可能会被过滤。避免使用table布局,不易于修改维护。背景图片或内容图片上的文字信息,必须在代码中可见。如果没有特殊要求,所有a链接都要从新窗口打开,即target=”_blank”,且a标签内容不能为空。所有链接必须设置使用颜色、是否下划线,即style=”text-decoration:;color:;”。重点检查ie!!!1234567891011<div style="width:600px;text-align:left;color:#000;font:normal 12px/15px simsun;background:#d9d9d9;"> <div style="height:268px;background:url(images/bg1.jpg) no-repeat;"> <div style="height:228px;"> <div style="padding:21px 0 0 21px;"> <a href="http://yuedu.163.com/" target="_blank" style="display:block;width:111px;height:28px;overflow:hidden;text-indent:-2000px;text-decoration:none;" title="网易阅读-随时随地品质阅读">网易阅读-随时随地品质阅读</a> </div> <h2 style="margin:0;padding:0;width:0;height:0;overflow:hidden;text-indent:-2000px;">你的iPad够有料吗?iPad不等于愤怒的小鸟!不等于切水果!下载网易阅读,给你的iPad添点料,打造你独一无二的iPad!</h2> </div> <div style="padding:0 0 0 35px;"><a href="http://itunes.apple.com/cn/app/id421092396?mt=8" target="_blank" style="color:#f00;text-decoration:none;" title="下载网易阅读">下载网易阅读</a></div> </div></div>发现的问题及解决方案问题:部分智能手机的邮件客户端可能会有只显示部分的bug(宽度被截)。解决:在外面套一个同宽的table即可。12345<table width="600" cellpadding="0" cellspacing="0" border="0"><tr><td> <div style="width:600px;text-align:left;color:#000;font:normal 12px/15px simsun;background:#d9d9d9;"> ...... </div></td></tr></table>使用框架推荐使用 email框架 来创建邮件内容。123456789101112<table width="600" cellpadding="0" cellspacing="0" border="0"><tbody><tr><td> <div style="width:600px;text-align:left;font:12px/15px simsun;color:#000;background:#fff;"> <!-- 水平居左的邮件 --> </div></td></tr></tbody></table><div style="text-align:center;"> <table width="600" cellpadding="0" cellspacing="0" border="0" style="margin:0 auto;"><tbody><tr><td> <div style="width:600px;text-align:left;font:12px/15px simsun;color:#000;background:#fff;"> <!-- 水平居中的邮件 --> </div> </td></tr></tbody></table></div>web前端规范新公司的前端开发规范(初稿) #125]]></content>
<categories>
<category>Norm</category>
</categories>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[前端代码规范Javascript]]></title>
<url>%2F2016%2F12%2F31%2Fnormjs%2F</url>
<content type="text"><![CDATA[规范:你是否常常碰到以下问题:你总是看不懂他写的代码,或者读起来很吃力;你需要改他的代码却无从下手,或总是要去问他这里是什么改了会不会影响其他代码;你和他一起开发一个产品,你总是怕代码和他有冲突或互相影响;你的代码在多次维护任务之后变得越来越臃肿,越来越难以维护。解决以上问题只需一种方法——读我们的规范!命名规则JavaScript支持大小写统一使用单引号命名使用驼峰法则开头字母大写,表示对象。变量命名变量命名匈牙利命名:开头字母用变量类型的缩写,其余部分用变量的英文或英文的缩写,要求单词第一个字母大写。For example: long lsum = 0;"l"是类型的缩写; s:表示字符串。例如:sName,sHtml; n:表示数字。例如:nPage,nTotal; b:表示逻辑。例如:bChecked,bHasLogin; a:表示数组。例如:aList,aGroup; r:表示正则表达式。例如:rDomain,rEmail; f:表示函数。例如:fGetHtml,fInit; o:表示以上未涉及到的其他对象,例如:oButton,oDate; g:表示全局变量,例如:gUserName,gLoginTime;驼峰式:第一个单词首字母小写,后面其他单词首字母大写。For example: firstName 函数命名函数命名:统一使用动词或者动词+名词形式 —- fnInit()对象方法命名使用fn+对象类名+动词+名词形式 fnAnimateDoRun()某事件响应函数命名方式为fn+触发事件对象名+事件名或者模块名 fnDivClick()附常用的动词列表:名称含义名称含义get获取set设置add增加remove删除create创建destory移除start启动stop停止open打开close关闭read读取write写入load载入save保存create创建destroy销毁begin开始end结束backup备份restore恢复import导入export导出split分割merge合并inject注入extract提取attach附着detach脱离bind绑定separate分离view查看browse浏览edit编辑modify修改select选取mark标记copy复制paste粘贴undo撤销redo重做insert插入delete移除add加入append添加clean清理clear清除index索引sort排序find查找search搜索increase增加decrease减少play播放pause暂停launch启动run运行compile编译execute执行debug调试trace跟踪observe观察listen监听build构建publish发布input输入output输出encode编码decode解码encrypt加密decrypt解密compress压缩decompress解压缩pack打包unpack解包parse解析emit生成connect连接disconnect断开send发送receive接收download下载upload上传refresh刷新synchronize同步update更新revert复原lock锁定unlock解锁checkout签出/check in 签入submit提交commit交付push推pull拉expand展开collapse折叠begin起始end结束start开始finish完成enter进入exit退出abort放弃quit离开obsolete废弃depreciate废旧collect收集aggregate聚集附上一段代码细细品味123456789101112131415161718192021222324252627282930313233343536//类名var ClassName = function(){ //私有变量 var _FieldName = "Test Field"; //属性 this.PropertyName = "Test Property Name"; //私有方法 var functionName = function(){ return "";}A:加 _ 下划线前缀 this.PublicFunctionName = function(pTestName){//公有方法 pTestName:参数 //局部变量 var condition = "condition"; //判断 if(condition){ return functionName(); }else{} B:小写开头 //数组 var nameCol = ["a","b"]; //数组项 var nameItem = nameCol[0]; //循环 for(var i = 0; i < nameCol.length; i++){ } C:大写开头 var selectName = "item"; //选择 switch(selectName){ case "item": break; } D:加小写p前缀}匿名函数要避免全局变量泛滥, 可以考虑使用匿名函数, 把不需要在外部访问的变量或者函数限制在一个比较小的范围内。12345678910例如以下代码:<script> function func1(){ var list = ["a", "b", "c"]; for(var i = 0; i < list.length; i++){ //.. }; } func1(); // 自动运行</script>这段代码的作用是在页面加载的时候自动执行某些操作, 并不需要被外部调用, 但是它执行过后却留下了一个全局的函数。123456789像这种情况, 非常有必要使用匿名函数:<script> (function func1(){ var list = ["a", "b", "c"]; for(var i = 0; i < list.length; i++){ //.. }; })(); // 自动运行</script>匿名函数的格式:1234567(function(){ // 代码块})();如果要带参数的话:(function(arg1, arg2, argN){ //..})(arg1, arg2, argN);命名空间还有另外一个方法可以减少全局变量, 那就是命名空间, 在JS中可以用”对象-属性”来模拟命名空间;12345window.com = {}window.com.bytter = {}window.com.bytter.hello = function(){ alert("hello");}如果你要给某个已经存在的页面增加功能, 可能要增加十多个函数, 而那个页面已经存在大量的全局变量和函数, 甚至还有函数跟你新增的函数同名, 怎么办?命名空间是比较好的选择, 你可以创建一个命名空间, 把你的新函数都放在那个命名空间之下, 例如:123456789101112131415<button type="button" onclick="pg.check.userAcc()">检查用户名</button><button type="button" onclick="pg.check.userAcc()">检查帐号</button><script> window.pg = {} window.pg.check = { // 检查用户名 userName: function(){ //.. }, // 检查帐号 userAcc: function(){ //.. } };</script>互不干扰结合上述的匿名函数和命名空间的使用, 可以把一个页面中自己维护的代码与其它的代码分隔开来, 将与外部代码的耦合降低到最小。1234567891011121314151617181920212223242526272829303132333435363738<script> // 页面命名空间 window.pg = {} // 检查用户信息 // 作者:张三 // 最后更新: 2012.12.31 (function(){ // 私有变量 var a, b, c; // 检查用户信息的相关方法 window.pg.check = { // 检查用户名 userName: function(){ //.. }, // 检查帐号 userAcc: function(){ //.. } }; })(); // end 张三的代码 // xxx功能 // 作者:李四 // 最后更新: 2012.1.1 (function(){ window.pg.xxx = { //.. } })(); // end 李四的代码</script>变量声明变量必须在使用前用var进行声明;变量的声明应该放在代码块或者函数的头部;可在一行内声明多个变量, 但要考虑美观易读;1234567891011121314151617181920212223242526272829303132333435363738394041424344454647// 银行名称, 银行帐号 var type, acc;// 银行名称, 银行帐号var type = "中国银行", acc = "xxxxxx";var type = "中国银行", // 银行名称 acc = "xxxxxx"; // 银行帐号尽量使用易于理解的变量名,如:var bankType = "中国银行", bankAccount = "xxxxxx"; ### 命名普通变量名和函数名采用"小驼峰式命名法", 如:firstName、lastName作为构造函数的函数采用"大驼峰式命名法", 如:var Person = function(){ //..}var me = new Person();常量用大写和下划线表示,如:var ROOT_PATH = "/v10/";分号每条语句必须使用分号结尾(特别是需要压缩的js,省略分号常常会导致压缩失败);大括号if语句、函数定义、try语句等带大括号的结构, 左大括号应紧跟前面的部分:// goodvar Person = function(){ //..}// badvar Person = function(){ //..}使用复合语句时不要省略大括号{}// goodfor(var i = 0; i < ary.length; i++){ list.push(ary[i]);}// badfor(var i = 0; i < ary.length; i++) list.push(ary[i]);以提高代码可读性为前提,允许例外:if(!data) return;if(row) list.push(row);空格数值操作符(如, +/-/*/% 等)、比较符(大于、小于、等于)两边留空格;逗号、冒号、分号后要留一个空格(如果后面还有内容的话);行尾不要有空格;点号前后不要出现空格;函数名末尾和左括号之间不要出现空格;字符串表示字符串用单引号或双引号均可, 建议统一使用双引号,123456789101112但表示html标签时一律使用单引号, 如:var html = '<div class="msg" ></div>';数组使用简便的方式定义数组:// goodvar list = [1, 2, 3];// badvar list = new Array();list[0] = 1;list[1] = 2;list[2] = 3;注释规范单行注释语法: // 这是单行注释使用方式:单独一行://(双斜线)与注释文字之间保留一个空格。在代码后面添加注释://(双斜线)与代码之间保留一个空格,并且//(双斜线)与注释文字之间保留一个空格。注释代码://(双斜线)与代码之间保留一个空格。示例:1234// 调用了一个函数;1)单独在一行setTitle();var maxCount = 10; // 设置最大量;2)在代码后面注释// setName(); // 3)注释代码多行注释语法:/* 注释说明 */使用方法:若开始(/)和结束(/)都在一行,推荐采用单行注释。若至少三行注释时,第一行为/,最后行为/,其他行以开始,并且注释文字与保留一个空格。示例:12345/** 代码执行到这里后会调用setTitle()函数* setTitle():设置title的值*/setTitle();函数(方法)注释说明:函数(方法)注释也是多行注释的一种,但是包含了特殊的注释要求,参照 javadoc(百度百科)。语法:/** * 函数说明 * @关键字 */常用注释关键字:(只列出一部分,并不是全部)示例:注释名语法示例@name@name 名称@name WacthClock@author@author 作者 邮箱@author Luuman luumans@qq.com@brief@brief 描述@brief this is watch for clock in canvas.@dateTime@dateTime 时间@dateTime 2016-11-27@moreInfo@moreInfo 链接@moreInfo luuman.github.io/[link]@version@version XX.XX.XX@version 1.0.3@param@param 名 {[type]} 描述信息@param name {String} 传入名称@return@return {[type]} 描述信息@return {Boolean} true:可执行;false:不可执行@example@example 示例代码@example WacthClock({});12345678910111213/** * @name WacthClock watch clock js * @author Luuman <[email protected]> * @brief this is watch for clock in canvas. * @dateTime 2016-11-27 * @moreInfo luuman.github.io/[link] * @version 1.0.0 * @param {[type]} * @param {[type]} * @param {[type]} * @return {[type]} * @example WacthClock({}); */12345678910111213141516171819/*** 合并Grid的行* @param grid {Ext.Grid.Panel} 需要合并的Grid* @param cols {Array} 需要合并列的Index(序号)数组;从0开始计数,序号也包含。* @param isAllSome {Boolean} :是否2个tr的cols必须完成一样才能进行合并。true:完成一样;false(默认):不完全一样* @return void* @author polk6 2015/07/21 * @example* _________________ _________________* | 年龄 | 姓名 | | 年龄 | 姓名 |* ----------------- mergeCells(grid,[0]) -----------------* | 18 | 张三 | => | | 张三 |* ----------------- - 18 ---------* | 18 | 王五 | | | 王五 |* ----------------- -----------------*/function mergeCells(grid, cols, isAllSome) { // Do Something}JavaScript 开发规范javascript学习笔记(一)基础知识]]></content>
<categories>
<category>Norm</category>
</categories>
<tags>
<tag>Javascript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native TextInput]]></title>
<url>%2F2016%2F12%2F27%2FRNCTextInput%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyTextInput 是一个允许用户输入文本的基础组件。1234567891011121314151617181920212223import React, { Component } from 'react';import { AppRegistry, Text, TextInput, View } from 'react-native';class PizzaTranslator extends Component { constructor(props) { super(props); this.state = {text: ''}; } render() { return ( <View style={{padding: 10}}> <TextInput style={{height: 40}} placeholder="Type here to translate!" onChangeText={(text) => this.setState({text})} /> <Text style={{padding: 10, fontSize: 42}}> {this.state.text.split(' ').map((word) => word && '🍕').join(' ')} </Text> </View> ); }}AppRegistry.registerComponent('PizzaTranslator', () => PizzaTranslator);123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, View, TextInput} from 'react-native';class TextInputDemo extends Component { render() { return ( <View style={styles.container}> <View style={styles.top_half_view}> <View style={styles.title_view}> <Text style={styles.title_text}> 邮箱登录 </Text> </View> <TextInput style={styles.textinput} placeholder='邮箱' numberOfLines={1} autoFocus={true} underlineColorAndroid={'#e1e1e1'} /> <TextInput style={styles.textinput} placeholder='密码' numberOfLines={1} secureTextEntry={true} underlineColorAndroid={'#e1e1e1'} /> <View style={{backgroundColor:'#ffffff',flexDirection:'row',alignItems:'center',justifyContent:'center'}}> <View style={styles.style_view_register}> <Text style={{color:'#5ac4ef'}}> 注册 </Text> </View> <View style={styles.style_view_login}> <Text style={{color:'white'}}> 登录 </Text> </View> </View> <Text style={styles.bottom_text}> 忘了密码?点此找回 </Text> </View> <View style={styles.bottom_half_view}> </View> </View> ); }}const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'white', }, title_view:{ flexDirection:'row', height:50, alignItems: 'center', backgroundColor:'#27b5ee', }, title_text:{ color:'white', fontSize:22, marginLeft:20, textAlign:'center' }, top_half_view:{ flex: 1.3, backgroundColor: 'white', }, bottom_half_view:{ flex: 1, backgroundColor: '#eeeeee', }, textinput: { backgroundColor:'#fff', marginTop:5, marginLeft:20, marginRight:20, textAlign:'left', }, style_view_login:{ flex:1, marginTop:20, marginLeft:20, marginRight:20, backgroundColor:'#27b5ee', height:35, borderRadius:5, justifyContent: 'center', alignItems: 'center', }, style_view_register:{ flex:1, marginTop:20, marginLeft:20, marginRight:20, borderColor:'#5ac4ef', borderWidth: 1, height:35, borderRadius:5, justifyContent: 'center', alignItems: 'center', }, bottom_text:{ color:'#27b5ee', fontSize:14, marginTop:10, marginLeft:20, textAlign:'left', fontWeight:'bold' },});AppRegistry.registerComponent('TextInputDemo', () => TextInputDemo);]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native Image]]></title>
<url>%2F2016%2F12%2F27%2FRNCImage%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why看看官网的案例,提供两种来源的图片:本地、服务器。123456789101112131415161718192021import React, { Component } from 'react';import { AppRegistry, View, Image } from 'react-native';class DisplayAnImage extends Component { render() { return ( <View> <Image source={require('./img/favicon.png')} /> <Image style={{width: 50, height: 50}} source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}} /> </View> ); }}// App registration and renderingAppRegistry.registerComponent('DisplayAnImage', () => DisplayAnImage);图片样式关于图片样式的设计,介于前端开发我们会考虑适配问题,通过flex-rem来进行适配。但是做了demo发现以下特点:Image组件必须设置图片高度,否则不会显示。本地图片可以不设置尺寸,会按照图片的大小显示,服务器上的图片必须设置图片高度。通过在两台Android手机测试发现,宽度可以不设置。高度不够,图片不会压扁,系统将截取中间部分,多余的图片将不会显示。(但是,官网提供的demo却不尽人意,原理是什么)想要通过PixelRatio来控制显示的大小,但是同样的屏幕设备设备像素相同,但是分辨率却不同1.5/3React Native 布局样式的单位是不是 pt、px,而是 dp。12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849'use strict';import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, PixelRatio, Image, ScrollView, View,} from 'react-native';class StyleImg extends Component { render(){ var url = ({ uri: 'http://7u2psp.com2.z0.glb.qiniucdn.com/576d0f99f1f58390384.jpg?imageView2/1/w/'+ 1000 * PixelRatio.get() +'/h/' + 1000 * PixelRatio.get() +'/q/100' }); var image = ({ uri: 'http://7u2psp.com2.z0.glb.qiniucdn.com/576d0f99f1f58390384.jpg?imageView2/1/w/'+ 1000 * PixelRatio.get() +'/h/' + 1000 * PixelRatio.get() +'/q/100' }); return ( <ScrollView> <View style = {styles.pad}> <Text style = {styles.pad}>图片裁剪是否压扁(同一片源)</Text> <Image source={url} style={{width: 180,height: 240}} /> <Image source={url} style={{width: 180,height: 180}} /> </View> <Text style = {styles.pad}>设备适配</Text> <Text>PixelRatio:{PixelRatio.get()}</Text> <Text style = {styles.pad}>高度{300 * PixelRatio.get()}</Text> <Text>想用服务器的截图功能,但是好像rn实现了这样的功能。</Text> <Image source={image} style={{height: 300 * PixelRatio.get()}} /> <Text style = {styles.pad}>PixelRatio 设备适配</Text> <Text>width: 160 * {PixelRatio.get()} , height: 213 * {PixelRatio.get()}</Text> <Image source={url} style={{width: 160 * PixelRatio.get(),height: 213 * PixelRatio.get()}} /> </ScrollView> ); }}const styles = StyleSheet.create({ pad:{ padding: 10, },});AppRegistry.registerComponent('StyleImg', () => StyleImg);]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native Text]]></title>
<url>%2F2016%2F12%2F27%2FRNCText%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyText按官方文档的话来说,Text它也支持嵌套,样式和触摸处理。Props属性accessible bool文本可以显示的行数clip is working only for iOS1accessible={true}numberOfLines number文本可以显示的行数1numberOfLines={1}onLayout function布局发生变化时调用1{nativeEvent: {layout: {x, y, width, height}}}onLongPress function长按事件1onLongPress={this.increaseSize}>onPress function按下或者点击事件1onPress={() => console.log('1st')}案例嵌套:1234567891011121314151617181920import React, { Component } from 'react';import { AppRegistry, Text } from 'react-native';class TitleNested extends Component { render() { return ( <Text> TitleNested地方 <Text style={{fontWeight: 'bold', fontSize: 20}}> I am bold地方 <Text style={{color: 'red'}}> and red地方 </Text> </Text> </Text> ); }}AppRegistry.registerComponent('TitleNested', () => TitleNested);简书:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677'use strict';import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, View} from 'react-native';class TitleStyle extends Component { render() { return ( <View style={styles.container}> <View style={styles.title_view}> <Text style={styles.title_text}>简书</Text> </View> <Text numberOfLines={1} style={styles.content_title_text}>不想过低配的人生,请先看看这本书</Text> <View style={styles.source_view}> <Text style={styles.source_text}>余小鱼MsYu</Text> <Text style={styles.source_text}>阅读7975</Text> </View> <Text accessibilityLabel={'Tap me!'} accessible={true} numberOfLines={2} style={styles.content_title_text}>我们熟悉的两种人生姿势:“飞黄腾达”和“赖在地上”。雾满拦江告诉你第三种:两脚不离大地,拼命向上生长。 ——《我不过低配的人生》</Text> <Text style={styles.content_text}>作者是雾满拦江。乍一看,这名字很熟,似乎在哪里见过或听过,但具体不太了解。随即翻开简介,了解到:著名作家,“心学讲武堂”创始人,幽默写史领军人物。他写历史、职场,也写百态人情。其人特立独行、学识颇丰,其文辛辣生猛、犀利幽默,读之可以下酒。代表作有《神奇圣人王阳明》《别笑,这是大清正史》《民国就是这么生猛》《推背图中的历史》等。</Text> </View> ); }}const styles = StyleSheet.create({ container: { flex: 1, backgroundColor:'#FFF', }, title_view:{ flexDirection:'row', height:50, justifyContent: 'center', alignItems: 'center', backgroundColor: '#E45E46', }, title_text:{ color:'#FFF', fontSize:20, textAlign:'center' }, source_view:{ flexDirection:'row', height:20, marginTop:10, justifyContent: 'space-between', alignItems: 'center', backgroundColor:'#FFF', }, source_text:{ color:'#b1b1b1', fontSize:14, marginLeft:25, marginRight:25, textAlign:'center' }, content_title_text:{ color:'#343434', fontSize:20, marginTop:8, marginLeft:25, marginRight:25, textAlign:'left' }, content_text:{ color:'#b2b2b2', fontSize:14, lineHeight: 22, marginTop:12, marginLeft:25, marginRight:25, textAlign:'left' },});AppRegistry.registerComponent('TitleStyle', () => TitleStyle);新浪:header.js1234567891011121314151617181920212223242526272829303132333435363738394041424344454647'use strict';import React, { Component } from 'react';import { AppRegistry, StyleSheet, PixelRatio, Text, View,} from 'react-native';class Header extends Component { render(){ return ( <View style={styles.flexs}> <Text style={styles.title}> <Text style={styles.wangyi}>网易</Text> <Text style={styles.xinwen}>新闻</Text> <Text>有态度"</Text> </Text> </View> ) }}const styles = StyleSheet.create({ flexs:{ marginTop: 25, height: 50, borderBottomWidth: 3/PixelRatio.get(), borderBottomColor: '#EF2D36', alignItems: 'center', }, title:{ fontSize: 25, fontWeight: 'bold', alignItems: 'center', }, wangyi:{ color: '#CD1D1C', }, xinwen:{ color: '#FFF', backgroundColor: '#CD1D1C', },});module.exports = Header;index.android.js123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104'use strict';import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, PixelRatio, View,} from 'react-native';// const Header = require('./header');import Header from './header';class List extends Component { render(){ return( <View style={styles.listItem}> <Text style={styles.listItemFont}>{this.props.title}</Text> </View> ); }}class ImportantNews extends Component { show(title){ alert(title); console.log(title); } render(){ var news = []; for(var i in this.props.news){ var text=( <Text onPress={this.show.bind(this,this.props.news[i])} numberOfLines={1} style={styles.newsItem} key={i} >{this.props.news[i]}</Text> ); news.push(text); } return( <View style={styles.flexs}> <Text style={styles.newsTitle}>今日要闻</Text> {news} </View> ); }}class luumans extends Component { render(){ return( <View style={styles.flexs}> <Header></Header> <List title='这些 Android 技术会很火'></List> <List title='为什么整个互联网行业都缺前端工程师?'></List> <List title='Android 开发中的日常积累'></List> <List title='一个神奇的控件'></List> <ImportantNews news={[ '找到问题了 注解框架没有获取到控件id :sweat:', '我之前也遇到过,可能是一个bug吧,不知道怎么解决', '非常喜欢。准备看着你的打一遍,能看懂,但是自己就敲不出来了,谢谢分享', '不知道怎么上的首页', ]}> </ImportantNews> </View> ); }}const styles = StyleSheet.create({ flexs:{ flex: 1, }, listItem:{ height: 40, marginLeft: 10, marginRight: 10, borderBottomWidth: 3/PixelRatio.get(), borderBottomColor: '#DDD', justifyContent: 'center', }, listItemFont:{ fontSize: 16, }, newsTitle:{ fontSize: 20, fontWeight: 'bold', color: '#CD1D1C', marginLeft: 10, marginTop: 10, }, newsItem:{ fontSize: 15, lineHeight: 40, marginLeft: 10, marginRight: 10, },});AppRegistry.registerComponent('luumans', () => luumans);]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native 组件]]></title>
<url>%2F2016%2F12%2F27%2FRNComponents%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why我们要想理解React Native应用的基本结构,我们首先需要先了解一些基本的React的概念,比如JSX语法、组件、state状态以及props属性。所以这篇我们重点讲讲Props,state和style样式。今天讲解的内容,都是根据React Native官方文档上的内容来的。组件化开发:组件的颗粒度设计主要取决于应用的结构设计。将公共部分拆分复用,提供公共组件。导出组件Header:1module.exports = Header;引入组件Header:12345678910const Header = require('./header');import Header from './header';class luumans extends Component { render(){ return ( <Header></Header> ) }}ViewAppRegistry模式是React Native中最基本的模块,也是最常用的模块。123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869'use strict';import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, PixelRatio, View,} from 'react-native';class luumans extends Component { render(){ return ( <View style={styles.flexs}> <View style={styles.container}> <View style = {[styles.item,styles.center]}><Text style={styles.title}>酒店</Text> </View> <View style = {[styles.item,styles.lineLeftRight]}> <View style={[styles.flexs,styles.center,styles.lineCenter]}><Text style={styles.title}>海外酒店</Text></View> <View style={[styles.flexs,styles.center]}><Text style={styles.title}>特色酒店</Text></View> </View> <View style = {styles.item}> <View style={[styles.flexs,styles.center,styles.lineCenter]}><Text style={styles.title}>团购</Text></View> <View style={[styles.flexs,styles.center]}><Text style={styles.title}>客栈、公寓</Text></View> </View> </View> </View> ) }}const styles = StyleSheet.create({ container:{ flexDirection: 'row', height: 80, borderRadius: 5, marginTop: 200, marginLeft: 5, marginRight: 5, backgroundColor: '#FF0067', }, item:{ flex: 1, height: 80, }, title:{ fontSize: 16, fontWeight: 'bold', color: '#FFF', }, center:{ justifyContent: 'center', alignItems: 'center', }, flexs:{ flex: 1, }, lineCenter: { borderBottomWidth: 1/PixelRatio.get(), borderColor: '#FFF', }, lineLeftRight: { borderLeftWidth: 1/PixelRatio.get(), borderRightWidth: 1/PixelRatio.get(), borderColor: '#FFF', },});AppRegistry.registerComponent('luumans', () => luumans);Navigator属性configureScene可选的函数,用来配置场景动画和手势。会带有两个参数调用,一个是当前的路由,一个是当前的路由栈。然后它应当返回一个场景配置对象1(route, routeStack) => Navigator.SceneConfigs.FloatFromRight环境依赖:PushFromRight (默认)FloatFromRightFloatFromLeftFloatFromBottomFloatFromBottomAndroidFadeAndroidHorizontalSwipeJumpHorizontalSwipeJumpFromRightVerticalUpSwipeJumpVerticalDownSwipeJump123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104'use strict';import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, PixelRatio, Navigator, Image, View, ScrollView,} from 'react-native';import Xinlang from './app/page/xinlang';class List extends Component { constructor(props) { super(props); this.state = {}; } _pressButton(){ const {navigator} = this.props; //为什么这里可以取得 props.navigator?请看上文: //<Component {...route.params} navigator={navigator} /> //这里传递了navigator作为props if(navigator){ navigator.push({ name: 'Xinlang', component: Xinlang, }) } } render(){ return( <ScrollView style={styles.flex}> <Text style={styles.listItem} onPress={this._pressButton.bind(this)}>这些Android技术会很火</Text> <Text style={styles.listItem} onPress={this._pressButton.bind(this)}>为什么整个互联网行业都缺前端工程师?</Text> <Text style={styles.listItem} onPress={this._pressButton.bind(this)}>一个神奇的控件</Text> </ScrollView> ); }}class Detail extends Component { constructor(props) { super(props); this.state = {}; } _pressButton(){ const {navigator} = this.props; if(navigator){ //很熟悉吧,入栈出栈~ 把当前的页面pop掉,这里就返回到了上一个页面:List了 navigator.pop(); } } render(){ return( <ScrollView style={styles.flex}> <Text style={styles.listItem} onPress={this._pressButton.bind(this)}>name</Text> </ScrollView> ); }}class luumans extends Component { render(){ let defaultName = 'List'; let defaultComponent = List; return ( <Navigator initialRoute = {{name: defaultName, component: defaultComponent}} //配置场景 configureScene = { (route) => { //这个是页面之间跳转时候的动画,具体有哪些?可以看这个目录下,有源代码的: node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js return Navigator.SceneConfigs.PushFromRight; } } renderScene = { (route,navigator) => { let Component = route.component; return <Component {...route.params} navigator = {navigator} /> } } /> ); }}const styles = StyleSheet.create({ flexs:{ flex: 1, }, listItem:{ height: 40, marginLeft: 10, marginRight: 10, borderBottomWidth: 3/PixelRatio.get(), borderBottomColor: '#DDD', justifyContent: 'center', lineHeight: 30, fontSize: 16, },});AppRegistry.registerComponent('luumans', () => luumans);NavigatorIOSTextInput属性placeholder1placeholder="Red placeholder text color"placeholderTextColor1placeholderTextColor="red"defaultValue1defaultValue="Same BackgroundColor as View "12```#####12#####123#####123#####```ActivityIndicatorActivityIndicatorIOSDatePickerIOSDrawerLayoutAndroidImageKeyboardAvoidingViewListViewMapViewModalNavigatorNavigatorIOSPickerPickerIOSProgressBarAndroidProgressViewIOSRefreshControlScrollViewSegmentedControlIOSSliderSliderIOSStatusBarSnapshotViewIOSSwitchSwitchAndroidSwitchIOSTabBarIOSTabBarIOS.ItemTextTextInputToolbarAndroidTouchableHighlightTouchableNativeFeedbackTouchableOpacityTouchableWithoutFeedbackViewViewPagerAndroidWebView]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native 实战封装组件]]></title>
<url>%2F2016%2F12%2F26%2FRNTest%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyJSX实战Reactnative中没有DOM的概念,只有组件的概念,所以我们HTML标签、DOM操作是无效的。但是组件的生命周期、JSX语法、事件绑定、自定义属性等,ReactNative与React.js是一样的。封装Box组件123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223'use strict';import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, View} from 'react-native';class Box extends Component{ render(){ return ( <View style={[BoxStyles.box,BoxStyles[this.props.width],BoxStyles[this.props.height]]}> <View style={[BoxStyles.top,BoxStyles.height50,BoxStyles[this.props.classBg]]}><Text>top</Text></View> <View style={[BoxStyles[this.props.childName]]}> <View style={[BoxStyles.left,BoxStyles[this.props.classBg]]}><Text>left</Text></View> {this.props.children} <View style={[BoxStyles.right,BoxStyles[this.props.classBg]]}><Text>right</Text></View> </View> <View style={[BoxStyles.bottom,BoxStyles.height50,BoxStyles[this.props.classBg]]}><Text>bottom</Text></View> <View style={[BoxStyles.label]}><Text>{this.props.boxName}</Text></View> </View> ) }}class MargginBox extends Component{ render(){ return ( <View style={[BoxStyles.margginBox]}> <Box childName="borderBox" height="height400" width="width400" boxName="margin" classBg="bgred">{this.props.children}</Box> </View> ) }}class BorderBox extends Component{ render(){ return ( <Box childName="paddingBox" height="height300" width="width300" boxName="border" classBg="bggreen" >{this.props.children}</Box> ) }}class PaddingBox extends Component{ render(){ return ( <Box childName="elementBox" height="height200" width="width200" boxName="padding" classBg="bgyellow" >{this.props.children}</Box> ) }}class ElementBox extends Component{ render(){ return ( <View style={[BoxStyles.box,BoxStyles.height100]}> <View style={[BoxStyles.measureBox]}> <View style={[BoxStyles.right]}><Text>height</Text></View> </View> <View style={[BoxStyles.bottom,BoxStyles.height50]} ><Text>width</Text></View> <View style={[BoxStyles.label]}><Text>element</Text></View> <View style={[BoxStyles.widthdashed]}></View> <View style={[BoxStyles.heightdashed]}></View> </View> ) }}class luumans extends Component { render(){ return ( <MargginBox> <BorderBox> <PaddingBox> <ElementBox> </ElementBox> </PaddingBox> </BorderBox> </MargginBox> ) }}const BoxStyles = StyleSheet.create({ height50:{ height: 50, }, height400:{ height: 400, }, height300:{ height: 300, }, height200:{ height: 200, }, height100:{ height: 100, }, width400:{ width: 400, }, width300:{ width: 300, }, width200:{ width: 200, }, width100:{ width: 100, }, bgred: { backgroundColor:'#6AC5AC', }, bggreen: { backgroundColor: '#414142', }, bgyellow: { backgroundColor: '#D64078', }, box: { flexDirection: 'column', flex: 1, position: 'relative', }, label: { top: 0, left: 0, paddingTop: 0, paddingRight: 3, paddingBottom: 3, paddingLeft: 0, position: 'absolute', backgroundColor: '#FDC72F', }, top: { justifyContent: 'center', alignItems: 'center', }, bottom: { justifyContent: 'center', alignItems: 'center', }, right: { width: 50, justifyContent: 'space-around', alignItems: 'center', }, left: { width: 50, justifyContent: 'space-around', alignItems: 'center', }, heightdashed: { bottom: 0, top: 0, right: 20, borderLeftWidth: 1, position: 'absolute', borderLeftColor: '#FDC72F', }, widthdashed: { bottom: 25, left: 0, right: 0, borderTopWidth: 1, position: 'absolute', borderTopColor: '#FDC72F', }, yellow: { color: '#FDC72F', fontWeight:'900', }, white: { color: 'white', fontWeight:'900', }, margginBox:{ position: 'absolute', top: 100, paddingLeft:7, paddingRight:7, }, borderBox:{ flex: 1, justifyContent: 'space-between', flexDirection: 'row', }, paddingBox:{ flex: 1, justifyContent: 'space-between', flexDirection: 'row', }, elementBox:{ flex: 1, justifyContent: 'space-between', flexDirection: 'row', }, measureBox:{ flex: 1, flexDirection: 'row', justifyContent: 'flex-end', alignItems:'flex-end', }, container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, },});AppRegistry.registerComponent('luumans', () => luumans);]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native 基础]]></title>
<url>%2F2016%2F12%2F26%2FRNBasics%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyReact Native看起来和react.js很像,最近也有不少框架开源,Weex基于Vue.js。ReactNative通过自定义组件,来实现接近原生操作,实现开平台效果。官方文档地址:Propsstatestyleprops 属性大多数组件在创建的时候就可以用各种参数来进行定制。用于定制的这些参数就称为props(属性)。所谓props,就是属性传递,而且是单向传递的。属性多的时候,可以传递一个对象,这是es6中的语法。案例12345678910111213import React, { Component } from 'react';import { AppRegistry, Image } from 'react-native';class luumans extends Component { render() { let pic = { uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg' }; return ( <Image source={pic} style={{width: 193, height: 110}}/> ); }}AppRegistry.registerComponent('luumans', () => luumans);当我们使用Image组件,可以使用source的props属性uri来控制显示什么图片。注意:注意{pic}外围有一层括号,我们需要用括号来把pic这个变量嵌入到JSX语句中。我们可以把任意合法的JavaScript表达式通过括号嵌入到JSX语句中。为了更好的说明props的用法和概念,我把上面的例子又修改了一下,我的这个例子只是为了更好的说明props属性的用法,不建议大家这么使用,毕竟image是现成的基础组件。官网自定义属性12345678910111213141516171819202122232425262728import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, Image, View} from 'react-native';class Img extends Component { render() { return ( <Image source={this.props.url} style={{width: 120, height: 80}}/> ); }}class UrlProps extends Component { render() { let pic = { uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg' }; return ( <View style={{padding: 10}}> <Img url ={pic}/> </View> ); }}AppRegistry.registerComponent('UrlProps', () => UrlProps);自己定义了个自定义组件Img,定义了个image的属性,通过单向数据传递实现。在自定义的Img组件中的,Image组件中引用了我们定义的image属性。这样一对比,可能大家就更能清楚的理解了props的用法了。说白了就是定制属性,然后传值。注意:image是小些的, 大些的Image是官方图片基础组件。自定义属性123456789101112131415161718192021import React, { Component } from 'react';import { AppRegistry, Text, View } from 'react-native';class Greeting extends Component { render() { return ( <Text>Hello {this.props.name}!</Text> ); }}class LotsOfGreetings extends Component { render() { return ( <View style={{alignItems: 'center'}}> <Greeting name='Rexxar' /> <Greeting name='Jaina' /> <Greeting name='Valeera' /> </View> ); }}AppRegistry.registerComponent('LotsOfGreetings', () => LotsOfGreetings);意思就是:自定义了一个名为Greeting的组件,然后,属性名为name,传不同的name值,在Text显示不同的名字。stateReact靠一个state来维护状态,当state发生变化则更新DOM。控制一个组件,一般有两种数据类型,一种是props,一种是state。props是在父组件中设置,一旦指定,它的生命周期是不可以改变的。对于组件中数据的变化,我们是通过state来控制的。一般情况下,我们初始化state状态,是在constructor构造函数中,然后如果需要改变时,我们可以调用setState方法。官方给的例子时一个闪烁的文字的例子,看看官网的例子是如何制作文字闪烁效果的。定时刷新1234567891011121314151617181920212223242526272829303132import React, { Component } from 'react';import { AppRegistry, Text, View } from 'react-native';class RTitle extends Component { constructor(props) { super(props); this.state = { showText: true }; // 每1000毫秒对showText状态做一次取反操作 setInterval(() => { this.setState({ showText: !this.state.showText }); }, 1000); } render() { // 根据当前showText的值决定是否显示text内容 let display = this.state.showText ? this.props.text : ' '; return ( <Text>{display}</Text> ); }}class ReloadTitle extends Component { render() { return ( <View> <RTitle text='I love to RTitle' /> <RTitle text='Yes RTitleing is so great' /> <RTitle text='Why did they ever take this out of HTML' /> <RTitle text='Look at me look at me look at me' /> </View> ); }}AppRegistry.registerComponent('ReloadTitle', () => ReloadTitle);自定义了一个RTitle组件,在构造函数中初始化了state,然后写了一个定时器,每个1秒改变一次状态,然后setState,然后在渲染render()方法中,判断状态的变化,如果是true,显示文字,false显示空。这样一闪一闪的效果就出来了。然后我们在ReloadTitle中使用RTitle组件,并传入我们需要的文字内容即可。其实在实际开发中,我们不需要设置定时器来改变状态,一般情况下,我们都是在获取到服务器的数据时或者用户输入时,更新状态去显示最新的数据。这是我们就是通过setState来做到的。StyleSheet在React Native中,你并不需要学习什么特殊的语法来定义样式。我们仍然是使用JavaScript来写样式。所有的核心组件都接受名为style的属性。这些样式名基本上是遵循了web上的CSS的命名,只是按照JS的语法要求使用了驼峰命名法,例如将background-color改为backgroundColor。1234const [name] = StyleSheet.create({ [name]: { },});样式引入外联1<View style = {styles.item}></View>内联1<View style = {{flex: 1,height: 80,borderWidth: 1,borderColor: '#000',}}></View>多个样式1<View style = {[styles.item,styles.items,{flex: 1,height: 80,borderWidth: 1,borderColor: '#000',}]}></View>TitleStyle12345678910111213141516171819202122232425262728293031import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, View } from 'react-native';class TitleStyle extends Component { render() { return ( <View> <Text style={styles.red}>just red</Text> <Text style={styles.bigblue}>just bigblue</Text> <Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text> <Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text> <Text style={{color:'red' , fontSize:30}}> Style <Text style={{color:'blue'}}> Title </Text> </Text> </View> ); }}const styles = StyleSheet.create({ bigblue: { color: 'blue', fontWeight: 'bold', fontSize: 30, }, red: { color: 'red', },});AppRegistry.registerComponent('TitleStyle', () => TitleStyle);]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native IOS环境搭建]]></title>
<url>%2F2016%2F12%2F25%2FRNSetOX%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyReact Native初探ReactNative是Facebook在2015年React开发者大会上公开的应用开发框架,一个可以用React开发原生应用的框架。技术背景FaceBook => HTML5、NativeAppHybridApp => Native + Web 混合模式特点:JSX语法(扩展的JS语法)、组件化模式、Virtual Dom、DataBinding单向数据流、可以实现Chrome的调试基本模式:每个React应用可视为组件的组合,而每个React组件由属性(Property)和状态(state)来配置,当状态发生变化时更新UI,组件的结构是由虚拟的DOM来维护,确保了实际更新的DOM只包括真正产生了状态变化的部分。同类型的代码:GoogleSky、Titanium、NativeScript(太重)、鸟巢(支付宝)、BeeFrameWork综合起来:强大的社区,简单的学习,简单的开发、简单的应用。跨平台开发框架优点;跨平台、兼容web、ios、android三大主流平台React调用原生控件,性能优于H5框架更好的手势识别实时部署更新,再也不用担心应用市场审核缓慢设计理念:既拥有Native的用户体验,又保留React的开发效率!Facebook官方使用React Native开发的应用:Groups、Ads Manager、F8、Adverts Manger、天猫IPad、Chinese FlashcardsReactNative提供了那些能力基于原生UI组件手势识别基于FlexBox的CSS布局模式跨平台开发基于React、jsx组件化开发模式IOS环境搭建环境依赖:OSXXcodeNodesublime安装Homebrew:Homebrew, Mac系统的包管理器,用于安装NodeJS和一些其他必需的工具软件。通过homebrew安装Node、watchman、flow安装Homebrew:1/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"注:在Max OS X 10.11(El Capitan)版本中,homebrew在安装软件时可能会碰到/usr/local目录不可写的权限问题。可以使用下面的命令修复:1sudo chown -R `whoami` /usr/local查看是否安装homebrew1brew -vNode1brew install nodeWatchmanWatchman是由Facebook提供的监视文件系统变更的工具。安装此工具可以提高开发时的性能(packager可以快速捕捉文件的变化从而实现实时刷新)。1brew install watchman 检测文件变化FlowFlow是一个静态的JS类型检查工具。译注:你在很多示例中看到的奇奇怪怪的冒号问号,以及方法参数中像类型一样的写法,都是属于这个flow工具的语法。这一语法并不属于ES标准,只是Facebook自家的代码规范。所以新手可以直接跳过(即不需要安装这一工具,也不建议去费力学习flow相关语法)。1brew install flow 检测js语法1clear 清理屏幕React NativeReact Native的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务1npm install -g react-native-cli 全局安装react native如果你看到EACCES: permission denied这样的权限报错,那么请参照上文的homebrew译注,修复/usr/local目录的所有权:1sudo chown -R `whoami` /usr/local]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native Android环境搭建(Window)]]></title>
<url>%2F2016%2F12%2F25%2FRNSetAndroid%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyAndroid环境搭建(Window下)环境依赖:GitNodePython 2Android Studioreact-native-cliMicrosoft C++ 环境android 6.0 真机安装java JDk从Java官网下载Java SE Development Kit 7 Downloads并安装。请注意选择x86还是x64版本。推荐将JDK的bin目录加入系统PATH环境变量。(安装JDK、JRE)配置环境变量:系统变量→新建 JAVA_HOME 变量1C:\Program Files\Java\jdk1.7.0_79系统变量→寻找 Path 变量→编辑1%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;系统变量→新建 CLASSPATH 变量→编辑1.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jarjava -version 查看Java版本安装Python 2从官网下载并安装python 2.7.x(3.x版本不行)Android StudioAndroid Studio]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native开发工具]]></title>
<url>%2F2016%2F12%2F25%2FRNTools%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhySublime 3ReactJSEmmet12345View>Text<View> <Text></Text></View>Terminal上面添加了Terminal插件,在sublime里,直接用快捷键 command+shift+T,打开终端,然后执行如下命令运行 Android 应用程序:react-native-snippetsBabelbabel插件支持ES6语法和JSX语法,要比sublime-react看起来更舒服。出现问题也会提示。安装:搜索“Babel”,安装后将jsx文件格式设置成(Syntax -> Open all with current extension as… -> Babel -> JavaScript (Babel))]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[React Native初探]]></title>
<url>%2F2016%2F12%2F25%2FRN%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyReact Native初探ReactNative是Facebook在2015年React开发者大会上公开的应用开发框架,一个可以用React开发原生应用的框架。技术背景FaceBook => HTML5、NativeAppHybridApp => Native + Web 混合模式特点:JSX语法(扩展的JS语法)、组件化模式、Virtual Dom、DataBinding单向数据流、可以实现Chrome的调试基本模式:每个React应用可视为组件的组合,而每个React组件由属性(Property)和状态(state)来配置,当状态发生变化时更新UI,组件的结构是由虚拟的DOM来维护,确保了实际更新的DOM只包括真正产生了状态变化的部分。同类型的代码:GoogleSky、Titanium、NativeScript(太重)、鸟巢(支付宝)、BeeFrameWork综合起来:强大的社区,简单的学习,简单的开发、简单的应用。跨平台开发框架优点;跨平台、兼容web、ios、android三大主流平台React调用原生控件,性能优于H5框架更好的手势识别实时部署更新,再也不用担心应用市场审核缓慢设计理念:既拥有Native的用户体验,又保留React的开发效率!Facebook官方使用React Native开发的应用:Groups、Ads Manager、F8、Adverts Manger、天猫IPad、Chinese FlashcardsReactNative提供了那些能力基于原生UI组件手势识别基于FlexBox的CSS布局模式跨平台开发基于React、jsx组件化开发模式项目结构123456789101112ReactNative (项目名称)|–node_modules node模块 |–react-native ReactNative引用工程文件|–app app页面 |–index.android.js android工程备份 |–index.ios.js ios工程备份|–index.android.js android工程(开发文件)|–index.ios.js ios工程(开发文件)|–android android项目|–ios ios项目 |–*.xcodeproj Xcode启动文件|–package.json 工程信息数据注:android与ios有什么区别?关于android与ios开发,大部分只要将开发好的文件相互拷贝,修改android与ios独有的部分控件即可。整体的逻辑思路保持一致即可。设备调试工具摇晃设备或按Menu键chance选项Reload刷新Debug Js Remotely远程调试jsEnable Live Reload启动实时刷新Enable Hot Reloading启动热刷新Toggle Inspector标签调试Show Perf Monitor显示性能监视器Capture HeapStart/Stop Sampling Profiler启动/停止检测器Dev Settings设备设置Debug Js Remotely js远程调试此时,会打开页面调试Tab页面Tab页面,可以用浏览器访问android看看是否可以看到打包后的脚本(看到很长的js代码就对了)。第一次访问通常需要十几秒,并且在packager的命令行可以看到形如[====]的进度条。如果你遇到了ERROR Watcher took too long to load的报错,请尝试修改node_modules/react-native/packager/react-packager/src/FileWatcher/index.js,将其中的MAX_WAIT_TIME 从25000改为更大的值(单位是毫秒)Enable Live Reload 启动实时刷新Enable Hot Reloading 启动热刷新React Native 热加载(Hot Reload)原理简介Toggle Inspector 标签调试Show Perf Monitor 显示性能监视器Capture HeapStart/Stop Sampling Profiler 启动/停止检测器Dev Settings 设备设置Bebugging 调试Debug server host & port for device 调试服务器主机和端口123adb devices 查询设备IDadb reverse tcp:8081 tcp:8081提示信息应用内的错误与警告提示(红屏和黄屏)#红屏或黄屏提示都只会在开发版本中显示,正式的离线包中是不会显示的。React Native调试技巧与心得简单的列表Demo1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374import React, { Component } from 'react';import { AppRegistry, StyleSheet, Text, View, ScrollView, Image,} from 'react-native';export default class luumans extends Component { render() { return ( <ScrollView style={styles.container}> <Image source={{uri: 'http://jiuye-res.jikexueyuan.com/zhiye/showcase/attach-/20161013/2a7bf0a0-d94d-40d4-a244-20e5a5e359e6.jpg'}} style={styles.images} /> <Text style={styles.title}>『微信小程序』从基础到实战</Text> <Text style={styles.teacher}>勾股</Text> <Text style={styles.time}>2013-07-11</Text> <Image source={{uri: 'http://jiuye-res.jikexueyuan.com/zhiye/showcase/attach-59b4a27d-e431-4f49-aa25-6b94cccd8229.jpg'}} style={styles.images} /> <Text style={styles.title}>基于Go语言的短链接服务实战</Text> <Text style={styles.teacher}>小鱼</Text> <Text style={styles.time}>2013-07-11</Text> <Image source={{uri: 'http://jiuye-res.jikexueyuan.com/zhiye/showcase/attach-0da69660-4fcc-45d1-9b84-88271851f57f.jpg'}} style={styles.images} /> <Text style={styles.title}>基于Python的静态爬虫实战</Text> <Text style={styles.teacher}>飞雪</Text> <Text style={styles.time}>2013-07-11</Text> </ScrollView> ); }}const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F2F2F2', margin: 5, borderWidth: 1, borderColor: '#d2d2d2', }, title: { fontSize: 15, marginLeft: 10, color: '#333333', textAlign: 'left', }, images: { height: 200, margin: 10, }, teacher: { fontSize: 13, marginLeft: 10, color: '#525252', textAlign: 'left', }, time: { fontSize: 13, marginLeft: 10, color: '#2d854a', textAlign: 'left', },});AppRegistry.registerComponent('luumans', () => luumans);列表控件Listview:Flexbox布局什么事FlexboxFlexbox是css 3中引入的布局模型“弹性盒子模型”,通过弹性的方式来对齐和分布容器中的内容空间,使其能够适应不同屏幕的宽度。React Native中Flexbox是这个规范的子集。解决问题浮动布局不同宽度屏幕的适配宽度自动分配水平垂直居中相关资料:facebook/react-nativeA Complete Guide to Flexboxreact-native 之布局篇flexbox-CSS3弹性盒模型flexbox完整版教程React-Native之flexbox布局篇React Native专题React Native专题Flexbox in the CSS specificationsFlexbox at MDNFlexbox at OperaDiving into Flexbox by BocoupMixing syntaxes for best browser support on CSS-TricksFlexbox by Raphael Goetter (FR)Flexplorer by Bennett Feelyhttp://devbryce.com/site/flexbox/http://css.doyoe.com/properties/flex/index.htmhttp://css-tricks.com/snippets/css/a-guide-to-flexbox/样式测试ES6语法问题深入浅出ES6(十四):let和const问题:首页白屏ReactNative安卓首屏白屏优化react-native学习列表收集了react-native一些学习资源,列表会继续更新,大家有好的资源欢迎Pull Requests!官方文档React NativeReact Native 中文网官方视频react-native学习列表React-Native入门指南整理了一份React-Native学习指南深入浅出 React Native:使用 JavaScript 构建原生应用React Native系列文章React Native系列文章React Native中文社区天猫前端React-native组件库React Native Modules库react-native-desktopreact-native-code-pushreact-native-invoke相关书籍ECMAScript 6入门React/React Native 的ES5 ES6写法对照表教程awesome-react-nativeAirbnb JavaScript Style Guide 中文版React 入门实例教程-阮一峰ReactJS中文文档react-native-guideReact-Native-lessonReactNativeDemonpm模块管理器快速入门-Grunt中文网Redux 中文文档reactjs.cn - Flux应用架构cnsnake11研究react-native的blogFacebook F8App-ReactNative项目源码分析系列React Native 学习笔记构建 F8 App / React Native 开发指南React Native:移动开发时代的巴别塔 - 专题分享文章一个完整的Flexbox指南组件的详细说明和生命周期(Component Specs and Lifecycle)JSX 中的 If-Else组件间的通信mozilla-闭包npm的package.json中文文档快来使用ECMAScript 2015吧React-Native学习技术的三部曲新手理解Navigator的教程React/React Native 的ES5 ES6写法对照表一个“三端”开发者眼中的React Native“指尖上的魔法” – 谈谈React-Native中的手势ReactNative的组件架构设计在react-native中使用redux怎么样桥接一个objective-c的视图组件事件安卓Back键的处理·基本+高级篇音视频相机React Native 实现二维码扫描react-native-barcodescannerreact-native-camerareact-native-image-picker图形动画视图react-native-buttonreact-native-scrollable-tab-viewlistviewreact-native-sglistviewreact-native-tableview项目DemoHTML5 CSS3 code samplereact-native-hybrid-app-examplesreact-native-redux-demoreact-native中使用reduxDesignReact-Native-Gankf8appreact-native-todonoder-react-nativeFinanceReactNativereact-native-nw-react-calculatorModereact-native-swiper工具开源的react-native IDErnpmreact-native-vector-iconsreduxreact-reduxredux-thunkredux-persistalt携程技术中心React Native Meetup活动经验分享]]></content>
<categories>
<category>FrontFrame</category>
</categories>
<tags>
<tag>ReactNative</tag>
</tags>
</entry>
<entry>
<title><![CDATA[移动Web解决方案]]></title>
<url>%2F2016%2F05%2F08%2FMobileGuide%2F</url>
<content type="text"><![CDATA[最近在系统的学习移动的坑,这里将他整理起来。前沿这里没有绝对的标准,只是介绍不同的解决方案,从而提高用户体验。组件化通用约定字体使用:使用无衬线字体123body { font-family: "Helvetica Neue", Helvetica, STHeiTi, sans-serif;}组件命名中fn,ui,text为保留字,除在指南中约定之外,建议不在其他场合进行使用,并且凡以此命名的类名,其中所有的数值的设定,皆为非important关键字【规范】1234fn_clear 清除浮动fn_left,fn_right 左右浮动fn_show,fn_hide 显示 display:block/隐藏 display:nonetext_left,text_center,text_right 文字左中右居中凡被JS使用的类名,在通常命名前加上J_或j-前缀,在同一个项目里需要保持形式的一致性特定浏览器CSS属性的前缀12345采用以下两种,-webkit-和-ms-,由于手机只有webkit的内核和微软的IE浏览器。-webkit-{prop}:{value}-ms-{prop}:{value}{prop}:{value}通用业务组件名称,建议使用如下约定:123456789button btn 按钮nav 导航list 列表paging 分页tab 标签页select 下拉框input 输入框group 特性相似的群,与list的区别在于,list有明确的列表布局的特性,group没有其特性form 表单常用模块状态名称12345678910current 当前模块状态selected 被选中状态disabled 失效状态focus 焦点集中状态blur 焦点失去状态checked 被勾选状态success 成功状态error 错误状态hover active 手指在模块上状态【讨论】命名指南组件命名是明晰的,从拼写的单词能直观的看出组件用途建议不使用缩写,除对字母长度超过6个以上的单词。如果使用缩写建议缩写后的单词在4个字母以上,谨慎使用3个字母及以下的缩写,除非该含义非常清晰可见,并没有歧义,比如说btn,不建议的缩写,例如 ui组件命名采用层次命名的方式,中间采用-为间隔符,层次方式如下[样式库名称] - [组件名称] (- [组件状态])? (- [子组件名称])? (- [子组件状态])?例如:amui库中有个list列表,里面有个按钮,当用户点击list中当前被选中的那个item中的按钮的时候,产生一个按上去的效果,这个时候的命名方式建议如下:am-list-current-btn-active样式库名称建议使用该样式库的名称简写,建议2~4个字母样式库名称不建议使用宽泛且无具体意义的命名,比如说ui等【规范】组件内部的类名需要体现上层的含义,体现的方式没有强行规定,但是可以直观看出例如:list表中嵌套一个按钮,独立系统里统一命名风格【规范】在一个完整的模块命名方式,对于相同类型的模块命名保持一致,比如说,使用了button作为模块类名之后,后面如果再需用到按钮,不再建议使用btn的方式。目录结构和文件命名规范前端有哪些大小写区分,XHTML区分大小写、HTML不区分大小写、CSS与HTML有关、Javascript区分大小写。由此可以看出,文件建议使用小写加下划线命名。我们单独一节来说明网站目录结构和命名规范的目的是让我们重视。因为无论你的XHTML、CSS、Javascript写得多熟练多好,而网站的目录结构和其命名是让人和搜索引擎读不懂的。那么网站就没有真正做到标准化,而且整个网站的后期扩展和维护的成本和代价会很大。还有一点需重视就是xhmtl、css、js的代码注意缩进。并保持格式整齐的并且提供注释,保证可阅性。同时为后期编写程序提供良好的开发条件。首先网站的目录结构和文件命名清晰、XHTML里面的元素命名清晰会给SEO带来好处。例如文件的命名,如果使用全拼,那么Google是自动识别拼音进行排名的。关于SEO相关的知识(请参阅公司SEO相关文档),就不在这里一一阐述了。接下来介绍目录结构和命名规范。目录结构主要分为四类,需要注意的是,所有命名必须为小写英文、下划线,不能大写或中文。categorys(目录)目录的命名尽可能使用英文或者全拼表达目录内的页面作用(语义化),需要注意的是不要使用中文词组简拼(eg:目录–>ml)。简拼容易出现重复、或者目录结构复杂的时候容易出现混乱,给后期维护带来很大的麻烦。css目录命名可以为style、css、skin等,如果网站的目录结构不是很复杂的,尽量把css统一放在跟目录。这样可以方便后期的维护操作。如果网站的目录结构很复杂,层次超过3层以上的,可以在对应的层设置目录页面结构的css。js目录命名一般用js或scripts,这样一看就知道里面是放js脚本。同样js的目录结构也是和css一样。images根据网站规模来调整放图片的目录,一般根目录设置的images是存放整站共用的图片(包括图片图标背景等),而各二级三级目录里面也可以设置相应的images目录存放当前级的图片。根据具体的目录规范,做到前后台协商一致!当页面在引用css或者js的时候,大型的门户站点一般会在引用加上版本号或者日期。如:这样的做法是为了维护的时候可以更清晰知道所引用的脚本或样式是什么时候什么版本的。html命名html应遵循页面的内容或用途(SEO)进行命名。不能使用中文词组的简拼进行命名。当使用英文或者中文词组全拼的时候,同样会给SEO带来好处。另外需注意的是,整个网站的html后缀要统一,避免同时出现html、htm两种不同的后缀。css命名可以按照内容和功能进行命名。css功能性质一般指:reset.css(重置默认的样式-属性选择符)、global.css(全局使用的类选择符)、common.css(部分页面可共同使用的类选择符)等各种按功能分类的css。一般还可以将连接、段落、颜色等样式分离出来。布局页面一般指:style.css(全站的整体框架布局)—–index.css(首页的布局)、reg.css(注册页面的布局)。样式命名采用小写英文字母、数字、中扛线的组合,其中不得包含汉字、空格和特殊字符;多个单词应采用中扛线分割。样式名称字符不要超过20个,少用拼音写样式,使用限定词诸如(R(ight),L(eft),T(op),B(ottom),M(iddle),要把限定词放在最后,后缀限定词建议采用缩写形式,从而减少名称长度;根据样式的性质和功能,将样式分为以下几种:reset.css(重置默认的样式-属性选择符)global.css(全局使用的类选择符) common.css等各种按功能分类的css,各个功能模块页面的样式,视具体情况添加或修改。js命名js命名规范也和css的命名规范差不多,但是分前后台两种js文件,根据前后不用,使用不用的后缀区分。功能性质js功能性质一般指:jquery.js(js库或框架)、global.js(全局使用的脚本)、common.js(部分页面需要用的脚本)针对页面针对某个目录的页面:js_toggle_reg.js,前面的js是为了统一所有针对页面而定出来的。可以根据个人的情况把js改成自己所定义的单词。实际命名规范:1、js库或框架文件,如jquery.js,就引用自身的命名。2、与后台交互功能的js文件,命名规则就是:back_+js文件名如验证js:back_submitcheck.js3、前端页面效果的js文件,命名规则就是:front_+js文件名如焦点图效果js:front_focus.js图片的命名首先我们这里需要注意的是,切图的时候,可以去参考一些大型的网站如yahoo等的切图的方法。一般熟练css布局的都会将许多的小图标,背景图片集合到一张图,通过css来控制到具体的元素使用哪个图标或背景。另外目前国外和国内高标准的网站,一般都采用png图使用,但是我们公司根据异步的要求,必须用jpg的图片。图片根据图片的所处的页面位置名称作用来命名。图片的命名规范化更有利于css的编写。可以举几个例子:index_header_navtab_bg.jpg—–字面理解到图片是index页面headher中导航TAB的背景products_content_title_icon.gif—–字面理解为products页面content中标题的iconindex_header_banner_pic.png—–字面理解为index页面header的banner图片只有当图片的名称语义化了,在你写css或者页面需用到图片的时候,可以更快速的找到所需的。如果只是随便的取01.jpg、bg.jpg这类的命名,会给前端开发带来不便,更不用说后期维护了。友情提示:本文中关于《WEB前端开发规范》给出的范例仅供您参考拓展思维使用,WEB前端开发规范:该篇文章建议您自主创作。]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>Mobile</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Input输入框的案例]]></title>
<url>%2F2016%2F04%2F02%2FJSInputSearch%2F</url>
<content type="text"><![CDATA[需求:由于注册、登陆、信息填写,都需要使用input进行获取,但是自带的样式不够好看,用户体验的需求。2.1 文件命名规则]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>HTML</tag>
</tags>
</entry>
<entry>
<title><![CDATA[OmniMarkupPreviewer]]></title>
<url>%2F2016%2F04%2F02%2FSublimeOmniMarkupPreviewer%2F</url>
<content type="text"><![CDATA[OmniMarkupPreviewer:作为 Sublime Text 的一款强大插件,支持将标记语言渲染为 HTML 并在浏览器上实时预览,同时支持导出 HTML 源码文件。MarkdownMarkdown 是一种轻量级标记语言,创始人为约翰·格鲁伯(John Gruber)。它允许人们“使用易读易写的纯文本格式编写文档,然后转换成有效的XHTML(或者HTML)文档”。 —— 来自维基百科Sublime Text 3Sublime Text 作为近些年迅速崛起的后起之秀,凭借其精美的 UI 交互、完备的特色功能俘虏了一大批忠实用户。其风靡之势刺激了一些新老文本编辑器的重新思考和开发,开源实现 Lime Text Editor 无需多说,Github 主导的 Atom 以及号称下一代 Vim 编辑器的 neovim 都明确受到 Sublime Text 的影响。OmniMarkupPreviewer作为 Sublime Text 的一款强大插件,支持将标记语言渲染为 HTML 并在浏览器上实时预览,同时支持导出 HTML 源码文件。详细设置123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354${packages} 路径为 /Users/ashfinal/Library/Application Support/Sublime Text 3/Packages/{ "server_host": "192.168.1.100", <!-- 开启预览服务的 IP 地址, 默认为 localhost. --> "browser_command": ["open", "-a", "Google Chrome", "{url}"], <!-- 你完全可以在 Mac 上编辑 Markdown 文档,而把 iPad 当作外接显示器来实时预览 --> // User public static files should be placed into // ${packages}/User/OmniMarkupPreviewer/public/ // User templates should be placed into: // ${packages}/User/OmniMarkupPreviewer/templates/ // Requires browser reload "html_template_name": "Evolution Yellow", // list of renderers to be ignored, case sensitive. // Valid renderers are: "CreoleRenderer", "MarkdownRenderer", "PodRenderer", // "RDocRenderer", "RstRenderer", "TextitleRenderer" // for example, to disable Textile and Pod renderer: // "ignored_renderers": ["TextitleRenderer", "PodRenderer"] "ignored_renderers": ["CreoleRenderer", "PodRenderer", "RDocRenderer", "TextitleRenderer", "LiterateHaskellRenderer"], "mathjax_enabled": false, // MarkdownRenderer options "renderer_options-MarkdownRenderer": { // Valid extensions: // - OFFICIAL (Python Markdown) - // "extra": Combines ["abbr", "attr_list", "def_list", "fenced_code", "footnotes", "tables", "smart_strong"] // For PHP Markdown Extra(http://michelf.ca/projects/php-markdown/extra/) // "abbr": http://packages.python.org/Markdown/extensions/abbreviations.html // "attr_list": http://packages.python.org/Markdown/extensions/attr_list.html // "def_list": http://packages.python.org/Markdown/extensions/definition_lists.html // "fenced_code": http://packages.python.org/Markdown/extensions/fenced_code_blocks.html // "footnotes": http://packages.python.org/Markdown/extensions/footnotes.html // "tables": http://packages.python.org/Markdown/extensions/tables.html // "smart_strong": http://packages.python.org/Markdown/extensions/smart_strong.html // "codehilite": http://packages.python.org/Markdown/extensions/code_hilite.html // "meta": http://packages.python.org/Markdown/extensions/meta_data.html // "toc": http://packages.python.org/Markdown/extensions/toc.html // "nl2br": http://packages.python.org/Markdown/extensions/nl2br.html // - 3RD PARTY - // "strikeout": Strikeout extension syntax - `This ~~is deleted text.~~` // "subscript": Subscript extension syntax - `This is water: H~2~O` // "superscript": Superscript extension syntax 0 `2^10^ = 1024` // "smarty" or "smartypants": Python-Markdown extension using smartypants to emit // typographically nicer ("curly") quotes, proper // ("em" and "en") dashes, etc. // See: http://daringfireball.net/projects/smartypants/ // And: https://github.com/waylan/Python-Markdown/blob/master/docs/extensions/smarty.txt "extensions": ["extra", "codehilite", "toc", "strikeout", "smarty", "subscript", "superscript"]}配色美化github.css]]></content>
<categories>
<category>Plug</category>
</categories>
<tags>
<tag>Sublime</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Gulp前端构建工具]]></title>
<url>%2F2016%2F04%2F02%2FInduceGulp%2F</url>
<content type="text"><![CDATA[Gulp前端自动化:Gulp的高度集成化开发环境,释放了前端开发中大量时间,如css压缩、js压缩、错误检查、合并js、压缩图片、压缩html、模块构造等,只要你能想到的基本都可以通过Gulp插件去实现。前端自动化的目的在一个项目过程中,重复而枯燥的工作太多了……绳命就这样浪费了。我们需要一个自动化的工作流程,让我们更专注于coding,而不是coding外的繁琐工作。于是Gulp应运而生。可以想像,如果在node环境下,一行命令搞定一个场景,So Cool…gulp是基于Nodejs的自动任务运行器, 她能自动化地完成 javascript/coffee/sass/less/html/image/css 等文件的的测试、检查、合并、压缩、格式化、浏览器自动刷新、部署文件生成,并监听文件在改动后重复指定的这些步骤。在实现上,她借鉴了Unix操作系统的管道(pipe)思想,前一级的输出,直接变成后一级的输入,使得在操作上非常简单。通过本文,我们将学习如何使用Gulp来改变开发流程,从而使开发更加快速高效。gulp 和 grunt 非常类似,但相比于 grunt 的频繁 IO 操作,gulp 的流操作,能更快地更便捷地完成构建工作。本示例以gulp-less为例(将less编译成css的gulp插件)展示gulp的常规用法,只要我们学会使用一个gulp插件后,其他插件就差看看其帮助文档了。让我们一起来学习gulp吧! ^_^功能:版本控制检查JS图片合并压缩CSS压缩JS编译SASS目前最知名的构建工具: Gulp、Grunt、NPM + Webpack;1234567grunt是前端工程化的先驱gulp更自然基于流的方式连接任务Webpack最年轻,擅长用于依赖管理,配置稍较复杂推荐使用Gulp,Gulp基于nodejs中stream,效率更好语法更自然,不需要编写复杂的配置文件安装前准备:在学习前,先谈谈大致使用gulp的步骤,给读者以初步的认识。首先当然是安装nodejs,通过nodejs的npm全局安装和项目安装gulp,其次在项目里安装所需要的gulp插件,然后新建gulp的配置文件gulpfile.js并写好配置信息(定义gulp任务),最后通过命令提示符运行gulp任务即可。安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 -> 配置gulpfile.js -> 运行任务node为了确保依赖环境正确,我们先执行几个简单的命令检查。1234567luuman@luuman-PC MINGW64 ~$ node -vv5.3.0Node是一个基于Chrome JavaScript V8引擎建立的一个解释器检测Node是否已经安装,如果正确安装的话你会看到所安装的Node的版本号npm接下来看看npm,它是 node 的包管理工具,可以利用它安装 gulp 所需的包123456luuman@luuman-PC MINGW64 ~$ npm -v3.3.12这同样能得到npm的版本号,装 Node 时已经自动安装了npmnpm Node依赖包说明:npm(node package manager)nodejs的包管理器,用于node插件管理(包括安装、卸载、管理依赖等);使用npm安装插件:命令提示符执行install[-g] [--save-dev];```11、<name>:node插件名称。例:```npm install gulp-less --save-dev2、-g:全局安装。将会安装在C:\Users\Administrator\AppData\Roaming\npm,并且写入系统环境变量; 非全局安装:将会安装在当前定位目录; 全局安装可以通过命令行在任何地方调用它,本地安装将安装在定位目录的node_modules文件夹下,通过require()调用;3、–save:将保存配置信息至package.json(package.json是nodejs项目配置文件);4、-dev:保存至package.json的devDependencies节点,不指定-dev将保存至dependencies节点;一般保存在dependencies的像这些express/ejs/body-parser等等。5、为什么要保存至package.json?因为node插件包相对来说非常庞大,所以不加入版本管理,将配置信息写入package.json并将其加入版本管理,其他开发者对应下载即可(命令提示符执行npm install,则会根据package.json下载所有需要的包,npm install –production只下载dependencies节点的包)。使用npm卸载插件:uninstall[-g] [--save-dev]``` PS:不要直接删除本地插件包123 1、删除全部插件:```npm uninstall gulp-less gulp-uglify gulp-concat``` ……???太麻烦 2、借助rimraf:```npm install rimraf -g``` 用法:rimraf node_modules4. 使用npm更新插件:```npm update <name> [-g] [--save-dev]更新全部插件:update [--save-dev]```15. 查看npm帮助:```npm help当前目录已安装插件:list```123456789PS:npm安装插件过程:从http://registry.npmjs.org下载对应的插件包(该网站服务器位于国外,所以经常下载缓慢或出现异常),解决办法往下看↓↓↓↓↓↓。### 选装cnpm因为npm安装插件是从国外服务器下载,受网络影响大,可能出现异常,如果npm的服务器在中国就好了,所以我们乐于分享的淘宝团队干了这事。来自官网:“这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。”;[官方网址:](http://npm.taobao.org "")安装:命令提示符执行```npm install cnpm -g --registry=https://registry.npm.taobao.org注意:安装完后最好查看其版本号cnpm -v或关闭命令提示符重新打开,安装完直接使用有可能会出现错误;注:cnpm跟npm用法完全一致,只是在执行命令时将npm改为cnpm(以下操作将以cnpm代替npm)。12345678910111213141516luuman@luuman-PC MINGW64 /l/自动化$ npm install cnpm -g --registry=https://registry.npm.taobao.orgnpm WARN deprecated [email protected]: Renamed to supports-color. If you're usingchalk, upgrade to the latest version. https://github.com/chalk/supports-colorC:\Users\luuman\AppData\Roaming\npm\cnpm -> C:\Users\luuman\AppData\Roaming\npm\node_modules\cnpm\bin\cnpmC:\Users\luuman\AppData\Roaming\npm\cnpm-sync -> C:\Users\luuman\AppData\Roaming\npm\node_modules\cnpm\bin\cnpm-syncC:\Users\luuman\AppData\Roaming\npm\cnpm-user -> C:\Users\luuman\AppData\Roaming\npm\node_modules\cnpm\bin\cnpm-userC:\Users\luuman\AppData\Roaming\npm\cnpm-check -> C:\Users\luuman\AppData\Roaming\npm\node_modules\cnpm\bin\cnpm-checkC:\Users\luuman\AppData\Roaming\npm\cnpm-web -> C:\Users\luuman\AppData\Roaming\npm\node_modules\cnpm\bin\cnpm-webC:\Users\luuman\AppData\Roaming\npm\cnpm-doc -> C:\Users\luuman\AppData\Roaming\npm\node_modules\cnpm\bin\cnpm-docC:\Users\luuman\AppData\Roaming\npm\cnpm-search -> C:\Users\luuman\AppData\Roaming\npm\node_modules\cnpm\bin\cnpm-searchC:\Users\luuman\AppData\Roaming\npm├── [email protected]├── [email protected]├─┬ [email protected]│ ├── [email protected]│ ├── [email protected]全局安装gulp说明:全局安装gulp目的是为了通过她执行gulp任务;安装:命令提示符执行install gulp -g```1查看是否正确安装:命令提示符执行gulp -v,出现版本号即为正确安装。luuman@luuman-PC MINGW64 /l/自动化$ cnpm -v4.3.112### 开始全局安装Gulpluuman@luuman-PC MINGW64 ~$ cnpm install -g gulpnpm WARN deprecated [email protected]: graceful-fs version 3 and before will fail on newer node releases. Please update to graceful-fs@^4.0.0 as soon as possible.npm WARN deprecated [email protected]: lodash@<3.0.0 is no longer maintained. Upgrade to lodash@^4.0.0.npm WARN deprecated [email protected]: graceful-fs version 3 and before will fail on newer node releases. Please update to graceful-fs@^4.0.0 as soon as possible.C:\Users\luuman\AppData\Roaming\npm\gulp -> C:\Users\luuman\AppData\Roaming\npm\node_modules\gulp\bin\gulp.jsC:\Users\luuman\AppData\Roaming\npm└─┬ [email protected]└─┬ [email protected]├─┬ [email protected]│ └─┬ [email protected]│ └─┬ [email protected]│ └─┬ [email protected]│ └─┬ [email protected]│ └── [email protected]└─┬ [email protected]└── [email protected]@luuman-PC MINGW64 /l/Github$ gulp -v[18:39:18] CLI version 3.9.1得到gulp的版本号,确认安装成功1234## 创建工程### 演示项目目录结构└─┬ src — 源文件:├──images├──scripts├──styles├──build — 编译后文件输出到的生产文件夹:├──images├──scripts├──stylesTestProject (项目名称)|–.git 通过git进行版本控制,项目自动生成这个文件|–node_modules 组件包目录|–dist 发布环境(编译自动生成的)|–css 样式文件(style.css style.min.css)|–images 图片文件(压缩图片\合并后的图片)|–js js文件(main.js main.min.js)|–index.html 静态页面文件(压缩html)|–src 开发环境|–sass sass文件|–images 图片文件|–js js文件|–index.html 静态文件|–gulpfile.js gulp配置文件|–package.json 依赖模块json文件,在项目目录下npm install会安装项目所有的依赖模块,简化项目的安装程序1234### 创建package.json我们先使用npm init来创建类似Nuget package的package.config一样的文件,这样我们就知道项目依赖哪些插件,而且我们不需要把插件提交到代码库,其它程序员只需要使用 npm install 就可以安装所有配置的插件$ npm initThis utility will walk you through creating a package.json file.It only covers the most common items, and tries to guess sensible defaults.See npm help json for definitive documentation on these fieldsand exactly what they do.Use npm install <pkg> --save afterwards to install a package andsave it as a dependency in the package.json file.Press ^C at any time to quit.name: (test) test //名称version: (1.0.0) 1.0.0 //版本description: test description //描述entry point: (index.js) //test command: //测试代码git repository: //Git版本库keywords: //关键词author: luuman //作者license: (ISC) //协议About to write to F:\Gulp\test\package.json:{“name”: “test”,“version”: “1.0.0”,“description”: “test description”,“main”: “index.js”,“scripts”: {“test”: “echo "Error: no test specified" && exit 1”},“author”: “luuman”,“license”: “ISC”}Is this ok? (yes)1234### 安装插件,加到项目依赖package.json中npm install gulp --save-dev //将具体的gulp功能插件局部安装项目下$ npm install gulp –save-devnpm WARN deprecated [email protected]: graceful-fs version 3 and before will fail on newer node releases. Please update to graceful-fs@^4.0.0 as soon as possible.npm WARN deprecated [email protected]: lodash@<3.0.0 is no longer maintained. Upgrade to lodash@^4.0.0.npm WARN deprecated [email protected]: graceful-fs version 3 and before will fail on newer node releases. Please update to graceful-fs@^4.0.0 as soon as possible.F:\Gulp\new└─┬ [email protected] install gulp-sass --save-dev //将具体的gulp功能插件局部安装项目下$ npm install gulp-sass –save-dev12345678### 安装gulp功能插件依赖包npm install gulp-jshint gulp-sass gulp-concat gulp-uglify gulp-rename --save-devgulp功能模块的文件会放在项目所在的目录的./node_modules 下,并在package.json中添加插件名称。### 引入插件包npm install当package.json中已经有提示插件依赖包,node.js将会直接下载所有依赖插件包。1234567891011121314151617### 简单的功能:| 插件 | 功能 || ---- | ---- || gulp-imagemin: | 压缩图片| gulp-ruby-sass: | 支持sass,安装此版本需要安装ruby| gulp-minify-css: | 压缩css| gulp-jshint: | 检查js| gulp-uglify: | 压缩js| gulp-concat: | 合并文件| gulp-rename: | 重命名文件| gulp-htmlmin: | 压缩html| gulp-clean: | 清空文件夹| gulp-livereload: | 服务器控制客户端同步刷新(需配合chrome插件LiveReload及tiny-lr)#### gulp-jshintluuman@luuman-PC MINGW64 /f/Gulp/new$ npm install gulp-jshint –save-devF:\Gulp\new├─┬ [email protected]├─┬ [email protected] WARN EPEERINVALID [email protected] requires a peer of [email protected] but none was installed.1234567891011121314### 补充:的前端开发软件环境```textNode.Js、NPM、Ruby、Java 基础环境Sublime + 插件 用于编写前端代码Chrome、Firefox + Firebug 浏览器Internet Explorer 进行兼容测试和预览页面UI、动画效果和交互功能Node.js+Gulp 进行前端自动化构建、JS语法验证、CSS压缩,图片压缩等;Koala 实时编译Less、Sass、Compass、CoffeeScript;Github 存储自己的代码库 、git或SVN用于版本控制和团队Code ReviewTomcat、DedeAMPZ、MAMP 进行简单运行环境演示Photoshop CC 切图 + Sprites 合并小图标XMind 画出清晰的工作或业务逻辑思维图123456789101112131415161718新建gulpfile.js 配置文件放在项目根目录下演示项目目录结构testProject (项目名称)|–.git 通过git进行版本控制,项目自动生成这个文件|–node_modules 组件包目录|–dist **发布环境**(编译自动生成的) |–css 样式文件(style.css style.min.css) |–images 图片文件(压缩图片\合并后的图片) |–js js文件(main.js main.min.js) |–index.html 静态页面文件(压缩html)|–src **开发环境** |–sass sass文件 |–images 图片文件 |–js js文件 |–index.html 静态文件|–gulpfile.js gulp配置文件|–package.json 依赖模块json文件,在项目目录下npm install会安装项目所有的依赖模块,简化项目的安装程序12345678910111213141516171819202122232425262728293031323334353637383940现在,项目文件夹都建好,组件也安装完毕了,我们需要编写gulpfile.js文件以指定gulp需要为我们完成什么任务。gulpfile.js内容如下:// 引入gulpvar gulp = require('gulp');// 引入组件var jshint = require('gulp-jshint');//检查jsvar sass = require('gulp-sass'); //编译Sassvar concat = require('gulp-concat');//合并var uglify = require('gulp-uglify');//uglify 组件(用于压缩 JS)var rename = require('gulp-rename');//重命名// 检查js脚本的任务gulp.task('lint', function() { gulp.src('./js/*.js') //可配置你需要检查脚本的具体名字。 .pipe(jshint()) .pipe(jshint.reporter('default'));});// 编译Sassgulp.task('sass', function() { gulp.src('./scss/*.scss') .pipe(sass()) .pipe(gulp.dest('./css'));//dest()写入文件});// 合并,压缩js文件// 找到 js/ 目录下的所有 js 文件,压缩,重命名,最后将处理完成的js存放在 dist/js/ 目录下gulp.task('scripts', function() { gulp.src('./js/*.js') .pipe(concat('all.js')) .pipe(gulp.dest('./dist')) .pipe(rename('all.min.js')) .pipe(uglify()) .pipe(gulp.dest('./dist')); console.log('gulp task is done');//自定义提醒信息});…. // 其他任务类似// 定义默认任务,执行gulp会自动执行的任务gulp.task(‘default’, function(){gulp.run(‘lint’, ‘sass’, ‘scripts’);// 监听js文件变化,当文件发生变化后会自动执行任务 gulp.watch('./js/*.js', function(){ gulp.run('lint','scripts'); });});1234567891011现在,回到命令行窗口,可以直接运行gulp任务了。gulp这将执行定义的default任务,就和以下的命令式同一个意思gulp default当然,我们可以运行在gulpfile.js中定义的任意任务,比如,现在单独运行sass任务:gulp sass编译会显示Finished,如果你的JS有什么不好的地方它会提醒,避免一些不必要的错误,十分贴心12345678910常见提醒:1.禁止在同一行声明多个变量。2.请使用 ===/!==来比较true/false或者数值3.使用对象字面量替代new Array这种形式4.不要使用全局函数。5.Switch语句必须带有default分支6.函数不应该有时候有返回值,有时候没有返回值。7.For循环必须使用大括号8.If语句必须使用大括号9.for-in循环中的变量 应该使用var关键字明确限定作用域,从而避免作用域污染。gulp的插件数量很多,后面还可以根据自己的需要进行添加任务1234567891011常用的gulp插件参考gulp-imagemin: 压缩图片gulp-ruby-sass: 支持sass,安装此版本需要安装rubygulp-minify-css: 压缩cssgulp-jshint: 检查jsgulp-uglify: 压缩jsgulp-concat: 合并文件gulp-rename: 重命名文件gulp-htmlmin: 压缩htmlgulp-clean: 清空文件夹gulp-livereload: 服务器控制客户端同步刷新(需配合chrome插件LiveReload及tiny-lr)gulp-livereloadnpm install gulp gulp-livereload –save-dev1234567891011var gulp = require('gulp'), livereload = require('gulp-livereload');gulp.task('watch', function () { // 这里的watch,是自定义的,写成live或者别的也行 var server = livereload(); // app/**/*.*的意思是 app文件夹下的 任何文件夹 的 任何文件 gulp.watch('app/**/*.*', function (file) { server.changed(file.path); });});命令行下运行1gulp watch前端自动化的目的Gulp新手入门教程基于Gulp的前端自动化工程搭建Gulp 自动化你的前端http://www.sheyilin.cn/2016/02/gulp_introduce/gulp官方网址:gulp插件地址:gulp 官方API:gulp 中文API:GruntjsGrunt安装及配合组件构建前端开发一体化grunt前端打包——css篇SourceTreeSourceTreeUED团队前端自动化构建环境的搭建前端构建大法 Gulp 系列 (四):gulp实战自动刷新建议使用browser-sync[gulp入门]gulp-connect浏览器自动刷新Gulp.js-livereload 不用F5了,实时自动刷新页面来开发1234567891011var gulp = require('gulp'), livereload = require('gulp-livereload');// 这里的f5,是自定义的,写成live或者别的也行gulp.task('f5',function(){ var server = livereload(); // app/**/*.*的意思是 app文件夹下的 任何文件夹 的 任何文件 gulp.watch('app/**/*.*',function(file){ server.changed(file.path); });})Gulp构建前端自动化工作流之:入门介绍及LiveReload的使用1234567891011121314151617181920212223242526272829303132333435363738var livereload = require('gulp-livereload'), webserver = require('gulp-webserver'); gulp.task('webserver', function() { gulp.src( './' ) // 服务器目录(./代表根目录) .pipe(webserver({ // 运行gulp-webserver livereload: true, // 启用LiveReload open: true // 服务器启动时自动打开网页 }));});gulp.task('watch',function(){ gulp.watch( '*.html', ['html']) // 监听根目录下所有.html文件});gulp.task('default',['webserver','watch']);var gulp = require('gulp'),// 网页自动刷新(服务器控制客户端同步刷新) livereload = require('gulp-livereload'),// 本地服务器 webserver = require('gulp-webserver')// 注册任务gulp.task('webserver',function(){ gulp.src('./') .pipe(webserver({ livereload: true, open: true, }))})// 监听f5任务gulp.task('f5',function(){ gulp.watch('*.html',['html'])})// web任务gulp.task('web',['webserver','f5'])报错:12345678910111213141516171819202122232425262728293031$ gulp buildfs.js:856 return binding.readdir(pathModule._makeLong(path)); ^Error: ENOENT: no such file or directory, scandir 'L:\自动化\new\node_modules\.3.8.0@node-sass\vendor' at Error (native) at Object.fs.readdirSync (fs.js:856:18) at Object.getInstalledBinaries (L:\自动化\new\node_modules\.3.8.0@node-sass\lib\extensions.js:119:13) at foundBinariesList (L:\自动化\new\node_modules\.3.8.0@node-sass\lib\errors.js:20:15) at foundBinaries (L:\自动化\new\node_modules\.3.8.0@node-sass\lib\errors.js:15:5) at Object.module.exports.missingBinary (L:\自动化\new\node_modules\.3.8.0@node-sass\lib\errors.js:45:5) at Object.<anonymous> (L:\自动化\new\node_modules\.3.8.0@node-sass\lib\index.js:15:28) at Module._compile (module.js:398:26) at Object.Module._extensions..js (module.js:405:10) at Module.load (module.js:344:32)解决方案是执行以下方法:luuman@luuman-PC MINGW64 /l/自动化/new$ cnpm rebuild node-sass> [email protected] install L:\自动化\new\node_modules\gulp-sass\node_modules\node-sass> node scripts/install.jsBinary downloaded and installed at L:\自动化\new\node_modules\.3.8.0@node-sass\vendor\win32-x64-47\binding.node> [email protected] postinstall L:\自动化\new\node_modules\gulp-sass\node_modules\node-sass> node scripts/build.js"L:\自动化\new\node_modules\.3.8.0@node-sass\vendor\win32-x64-47\binding.node" exists.testing binary.Binary is fine; [email protected] L:\自动化\new\node_modules\gulp-sass\node_modules\node-sass使用 gulp 构建一个项目安装前准备安装完成Gulp之后我就要频繁的使用它,进行代码自动化处理。由于服务来自外国,可以被墙了。淘宝 NPM 镜像新建文件package.json12345678910111213luuman@luuman-PC MINGW64 /l/自动化/Gulp$ npm init //创建package.jsonname: (Gulp) test //名称version: (1.0.0) 1.0.0 //版本description: test description //描述entry point: (index.js) //test command: //测试代码git repository: //Git版本库keywords: //关键词author: luuman //作者license: (ISC) //协议About to write to L:\自动化\Gulp\package.json:最终会在当前目录中创建 package.json 文件并生成类似如下代码:12345678910111213141516171819202122{ "name": "gulp-demo", "version": "1.0.0", "description": "gulp-demo", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "[email protected]:luuman/Game.git" }, "keywords": [ "H5" ], "author": "luuman li", "license": "MIT", "bugs": { "url": "https://github.com/luuman/Game/issues" }, "homepage": "http://luuman.github.io/Game/",}安装gulp依赖包1npm install gulp --save-dev此时打开 package.json 会发现多了如下代码123"devDependencies": { "gulp": "^3.8.11" //声明此项目的开发依赖 gulp}安装gulp功能插件依赖包未配置文档1npm install gulp-uglify gulp-watch-path stream-combiner2 gulp-sourcemaps gulp-minify-css gulp-autoprefixer gulp-less gulp-ruby-sass gulp-imagemin gulp-util --save-dev12345此时,package.json 将会更新"devDependencies": { "colors": "^1.0.3", "gulp": "^3.8.11",}已配置文档当你将这份 gulpfile.js 配置分享给你的朋友时,就不需要将 node_modules/ 发送给他,他只需在命令行输入1npm install设计目录结构我们将文件分为2类,一类是源码,一类是编译压缩后的版本。文件夹分别为 src 和 dist。(注意区分 dist 和 ·dest 的区别)123456789101112131415161718TestProject (项目名称)|– .git 通过git进行版本控制,项目自动生成这个文件|– node_modules 组件包目录|– dist **发布环境**(编译自动生成的) |– css/ 样式文件(style.css style.min.css) |– images/ 图片文件(压缩图片\合并后的图片) |– js/ js文件(main.js main.min.js) |– index.html 静态页面文件(压缩html)|– src **开发环境** |– sass/ *.scss *.sass 文件夹 |– less/ less文件夹 |– images/ 图片文件夹 |– fonts/ 字体文件夹 |– js/ js文件夹 |– index.html 静态文件|– gulpfile.js gulp配置文件|– package.json 依赖模块json文件,在项目目录下npm install会安装项目所有的依赖模块,简化项目的安装程序gulp-util12345678var gulp = require('gulp')var gutil = require('gulp-util')gulp.task('default', function () { gutil.log('message') gutil.log(gutil.colors.red('error')) gutil.log(gutil.colors.green('message:') + "some")})Browser Sync自动刷新Browser Sync 帮助我们搭建简单的本地服务器并能实时刷新浏览器,它还能 同时刷新多个设备。不只是自动刷新BrowserSync并不只是一个自动刷新工具,它还有许多其他功能。默认配置下,BrowserSync会在多个浏览器中同步滚动条位置,表单行为和点击事件。而且可以在不同设备上进行实时浏览文件效果,在局域网里面。1234567891011[11:33:17] Finished 'dev' after 6.07 μs[BS] Access URLs: ------------------------------------- Local: http://localhost:3000 External: http://192.168.1.63:3000 ------------------------------------- UI: http://localhost:3001 UI External: http://192.168.1.63:3001 -------------------------------------[BS] Serving files from: dist/[BS] Watching files...快速拷贝部署文件在已经有成熟的gulp构建文件,新建文件夹,将文件gulpfile.js、package.json、src文件夹。cnpm install gulp引入gulpgulp install安装插件gulp执行]]></content>
<categories>
<category>Plug</category>
</categories>
<tags>
<tag>Gulp</tag>
</tags>
</entry>
<entry>
<title><![CDATA[移动H5自适应布局]]></title>
<url>%2F2016%2F04%2F02%2FHtmlRem%2F</url>
<content type="text"><![CDATA[WebApp开发:随着WebApp的兴起,rem这是个低调的css单位,近一两年开始崭露头角,有许多朋友对于它的评价不一,有的在尝试使用,有的在使用过程中遇到坑就弃用了。但是我认为rem是用来做WebApp它绝对是最合适的人选之一。rem是什么?rem(font size of the root element)是指相对于根元素的字体大小的单位。em(font size of the element)是指相对于父元素的字体大小的单位。区别:它们之间其实很相似,只不过一个计算的规则是依赖根元素一个是依赖父元素计算。设置viewport进行缩放设备适配Boss直聘BossZ类似百度的自适应跳转,但是将font-size限制在40px之内。1234567891011121314151617181920(function(doc,win){ var docEl = doc.documentElement, recalc = function(){ var clientWidth = docEl.clientWidth; if(!clientWidth){return} var w = 20 * (clientWidth / 320); if(w > 40){ w = 40; } docEl.style.fontSize = w + "px"; }; if(!doc.addEventListener){return} if("orientationchange" in window){ win.addEventListener("orientationchange",recalc,false) } win.addEventListener("resize",recalc,false); win.addEventListener("load",recalc,false); doc.addEventListener("DOMContentLoaded",recalc,false); recalc();})(document,window);12345678910111213141516171819PPi 320px HMTLfont-size:20px4.5rem = 90px.kz_dflex{ display: -webkit-flex; display: -ms-flexbox; display: -webkit-box; display: -moz-box; display: flex;}.kz_flex{ -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1;}百度Bwmai123456789101112(function(doc,win){ var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function(){ var clientWidth = docEl.clientWidth; if(!clientWidth) return; docEl.style.fontSize = 20 * (clientWidth / 320) + 'px'; }; if(!doc.addEventListener) return; win.addEventListener(resizeEvt,recalc,false); doc.addEventListener('DOMContentLoaded',recalc,false);})(document,window);五谷Honey网上一个朋友公司的自适应效果,font-size效果太局限了。zepto.js12345678910111213141516$(function() { $(window).resize(infinite); function infinite() { var htmlWidth = $('html').width(); if (htmlWidth >= 1080) { $("html").css({ "font-size" : "42px" }); } else { $("html").css({ "font-size" : 42 / 1080 * htmlWidth + "px" }); } } infinite();});Js-Rem1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162console.time("test");/*# 按照宽高比例设定html字体, width=device-width initial-scale=1版# @pargam win 窗口window对象# @pargam option{designWidth: 设计稿宽度,必须designHeight: 设计稿高度,不传的话则比例按照宽度来计算,可选designFontSize: 设计稿宽高下用于计算的字体大小,默认20,可选callback: 字体计算之后的回调函数,可选}# return Boolean;# [email protected]# ps:请尽量第一时间运行此js计算字体*/!function(win, option) { var count = 0, designWidth = option.designWidth, designHeight = option.designHeight || 0, designFontSize = option.designFontSize || 20, callback = option.callback || null, root = document.documentElement, body = document.body, rootWidth, newSize, t, self; root.style.width = 100 + "%"; //返回root元素字体计算结果 function _getNewFontSize() { var scale = designHeight !== 0 ? Math.min(win.innerWidth / designWidth, win.innerHeight / designHeight) : win.innerWidth / designWidth; return parseInt( scale * 10000 * designFontSize ) / 10000; } !function () { rootWidth = root.getBoundingClientRect().width; self = self ? self : arguments.callee; //如果此时屏幕宽度不准确,就尝试再次获取分辨率,只尝试20次,否则使用win.innerWidth计算 if( rootWidth !== win.innerWidth && count < 20 ) { win.setTimeout(function () { count++; self(); }, 0); } else { newSize = _getNewFontSize(); //如果css已经兼容当前分辨率就不管了 if( newSize + 'px' !== getComputedStyle(root)['font-size'] ) { root.style.fontSize = newSize + "px"; return callback && callback(newSize); }; }; }(); //横竖屏切换的时候改变fontSize,根据需要选择使用 win.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", function() { clearTimeout(t); t = setTimeout(function () { self(); }, 300); }, false); }(window, { designWidth: 640, designHeight: 1136, designFontSize: 20, callback: function (argument) { console.timeEnd("test") }});IMax1234567891011121314151617181920212223(function(win){ var userAgent = navigator.userAgent.toLowerCase(); var isPhone=userAgent.indexOf('android') !== -1 || userAgent.indexOf('iphone') !== -1 ||userAgent.indexOf('ipod') !== -1 || userAgent.indexOf('symbian') !== -1 || (userAgent.indexOf('micromessenger') !== -1) var doc = win.document, html = doc.documentElement; var baseWidth = 720, grids = baseWidth / 100, resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize', recalc = function(){ var clientWidth = html.clientWidth || 320; if(!isPhone){ if(clientWidth > 360){clientWidth = 360}; }else{ if(clientWidth > 500){clientWidth = 500}; } html.style.fontSize = clientWidth / grids + 'px'; }; if(!doc.addEventListener) return; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded',function(){ setTimeout(recalc) }, false);})(window);移动h5自适应布局HTML5移动端手机网站开发流程WebApp开发之–”rem”单位web app变革之remIMaxIMaxIMaxIMax]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>rem</tag>
</tags>
</entry>
<entry>
<title><![CDATA[BOOS信息展示与收缩]]></title>
<url>%2F2016%2F03%2F02%2FTextShow%2F</url>
<content type="text"><![CDATA[BOOS直聘:最近在找工作,用BOOS直聘,感觉用户体验很好,看到那个显示部分信息,就想用原生写写看看。展示效果DemoHTML12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455<div class="container"> <div class="page"> <div class="con-text"> <div class="job-text"> <div class="job-top color1"> <span>职位描述</span> <i class="weui_icon_checked"></i> </div> <div id="text-mian" class="job-main"> 你好忙 </div> <div id="Btns" class="job-bot color1">显示全部</div> </div> </div> <div class="con-text"> <div class="job-text"> <div class="job-top color1"> <span>职位描述</span> <i class="weui_icon_checked"></i> </div> <div id="text-mians" class="job-main"> 1.参与产品的前端开发,与后端工程师协作,高质高效完成产品的数据交互、动态信息展现;<br /> 2.提升产品的用户体验、前端性能以及团队的开发效率;<br /> 3.研究和探索创新的开发思路和前沿的前端技术,应用到团队与产品中。<br /> 1.熟练掌握各种Web前端技术(HTML/CSS/Javascript)和跨浏览器、跨终端的开发;<br /> 2.深刻理解Web标准,对前端性能、可访问性、可维护性等相关知识有实践的了解和实践经验;<br /> 3.熟悉HTML5,前沿JS类库和MVC框架者优先;<br /> 4.熟练使用一门非前端脚本语言(如:NodeJS、Python、PHP等),并有实践项目;<br /> 5.在博客或GitHub上有技术沉淀者优先; </div> <div id="Btnss" class="job-bot color1">显示全部</div> </div> </div> <div class="Bottom"></div> </div> <div class="con-bot"> <div class="Bleft"> <a href="javascript:;"><i></i><span>+收藏</span></a> </div> <div class="Bright"> <a href="javascript:;"><i></i><span>立即沟通</span></a> </div> </div></div><div class="sidebar-section"> <div class="section-detail"> <p class="text-center shop-detail"><strong>手机扫码访问</strong></p> <p class="text-center weixin-title">微信“扫一扫”分享到朋友圈</p> <p class="text-center qr-code"> <img width="140" height="140" src="images/create.png"> </p> </div></div>JavaScript1234567891011121314151617181920212223242526272829function TextShow(ID,Btns){ var DivT = document.getElementById(ID); var Texts = DivT.innerHTML; var NewT = document.createElement("div"); var Btn = document.getElementById(Btns); // 判断页面文字 if(Texts.length < 200){ Btn.style.display = "none"; }else{ NewT.innerHTML = Texts.substring(0,200) + "……"; Btn.innerHTML = Texts.length > 200 ? "显示全部" : ""; Btn.onclick = function(){ if(Btn.innerHTML == "显示全部"){ Btn.innerHTML = "收起"; NewT.innerHTML = Texts; }else{ Btn.innerHTML = "显示全部"; NewT.innerHTML = Texts.substring(0,200) + "……"; } } DivT.innerHTML = ""; DivT.appendChild(NewT); }}//文字部分显示:文字、按钮TextShow("text-mian","Btns");TextShow("text-mians","Btnss");]]></content>
<categories>
<category>Demo</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[移动端横屏提示动画]]></title>
<url>%2F2016%2F02%2F28%2FMobileRotate%2F</url>
<content type="text"><![CDATA[移动端横屏问题:由于屏幕的问题,在特定的开发条件下,实际上要求我们必须竖屏查看H5展示。展示效果Demo强制竖屏123456789101112131415<!-- uc强制竖屏 --><meta name="screen-orientation" content="portrait"><!-- QQ强制竖屏 --><meta name="x5-orientation" content="portrait"><!-- UC强制全屏 --><meta name="full-screen" content="yes"><!-- QQ强制全屏 --><meta name="x5-fullscreen" content="true"><!-- UC应用模式 --><meta name="browsermode" content="application"><!-- QQ应用模式 --><meta name="x5-page-mode" content="app"><!-- windows phone 点击无高光 --><meta name="msapplication-tap-highlight" content="no"><!-- 适应移动端end -->HTML代码123456<div id="MoblileR" class="mob-con"> <div class="mob-cen"> <i></i> <div>为了更好的体验,请将手机/平板竖过来</div> </div></div>CSS代码12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061.mob-con{ width: 100%; height: 100%; display: none; position: absolute; left: 0; top: 0; background: #32373b; z-index: 9990;}.mob-cen{ position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); z-index: 9999;}.mob-cen i{ margin: auto; display: block; width: 128px; height: 194px; /*background: url(../images/hengping.png 0 0 no-repeat);*/ background: url(images/hengping.png); background-size: 128px 194px; animation: mobileR 1.5s ease infinite alternate; -webkit-animation: mobileR 1.5s ease infinite alternate;}.mob-cen div{ font-size: 22px; margin-top: 20px; color: #ffd40a;}@keyframes mobileR{ 0% { -webkit-transform: rotate(-90deg); } 30% { -webkit-transform: rotate(-90deg); } 70% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(0deg); }}@-webkit-keyframes mobileR{ 0% { -webkit-transform: rotate(-90deg); } 30% { -webkit-transform: rotate(-90deg); } 70% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(0deg); }}屏幕判断方法一1234567/*方法一:*//* 媒体查询 orientation,定义'height'是否大于或等于'width'。值portrait代表是,landscape代表否 */@media screen and (orientation:landscape) { .mob-con{ display: block; }}方法二1234567891011121314151617181920212223242526<!-- 方法二: -->//判断屏幕横屏function oMobl(){ if(document.documentElement.clientHeight >= document.documentElement.clientWidth){ return "protrait"; }else{ return "landscape"; }}//显示实例提示function oMobx(){ var MoblieR = document.getElementById("MoblileR"); var oMobs = oMobl(); if(oMobs == "protrait"){ MoblieR.style.display = "none"; }else{ MoblieR.style.display = "block"; }}function oInit(){ oMobx(); window.addEventListener("onorientationchange" in window ? "orientationchange" : "resize",function(){ setTimeout(oMobx,200); })}oInit();Mobile Web开发基础之四————处理设备的横竖屏检测移动设备横竖屏]]></content>
<categories>
<category>Demo</category>
</categories>
<tags>
<tag>CSS3</tag>
</tags>
</entry>
<entry>
<title><![CDATA[关于移动端界面在PC端显示的实现]]></title>
<url>%2F2016%2F02%2F27%2FMobliePC%2F</url>
<content type="text"><![CDATA[概况:近阶段,移动端的开发十分火热,由于移动手机市场的宏大,在PC端浏览自己的移动端页面,如果不是响应式布局,样式会十分难看。MobilepadPC320px - 640px640px - 1024px1024px - 2800pxPC端显示Demo1234567891011121314151617181920@media screen and (min-width: 1024px) { .container { background: url(../images/iPhone-6S.png); background-repeat: no-repeat; background-size: 351px; margin: -8px auto; width: 352px; height: 739px; overflow: visible; } .page { /*overflow-y: auto;*/ -webkit-overflow-scrolling: touch; /* margin: auto; */ margin: 67px 0px 0px 17px; width: 324px; height: 602px; /* overflow-y: hidden; */ }}针对不同移动设备-响应式设计12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182device-pixel-ratio:定义输入设备屏幕的可视宽度与可见高度比率。device-width:输入设备屏幕的可视宽度。orientation :屏幕横竖屏定向。landscape 是横向,portrait 是纵向【ipad 相反】 /* iPhone 4 */@mediaonly screen and (-webkit-min-device-pixel-ratio : 1.5),only screen and (min-device-pixel-ratio : 1.5) {/* Styles */}/* iPads (portrait) */@media only screenand (min-device-width : 768px)and (max-device-width : 1024px)and (orientation : portrait) {/* Styles */}/* 智能手机 (portrait and landscape) */@media only screenand (min-device-width : 320px)and (max-device-width : 480px) {/* Styles */}/* 智能手机 (landscape) */@media only screenand (min-width : 321px) {/* Styles */}/* 智能手机 (portrait) */@media only screenand (max-width : 320px) {/* Styles */}/* iPads (portrait and landscape) */@media only screenand (min-device-width : 768px)and (max-device-width : 1024px) {/* Styles */}/* iPads (landscape) */@media only screenand (min-device-width : 768px)and (max-device-width : 1024px)and (orientation : landscape) {/* Styles */}/* iPads (portrait) */@media only screenand (min-device-width : 768px)and (max-device-width : 1024px)and (orientation : portrait) {/* Styles */}/* Desktops and laptops */@media only screenand (min-width : 1224px) {/* Styles */}/* Large screens */@media only screenand (min-width : 1824px) {/* Styles */}/* iPhone 4 */@mediaonly screen and (-webkit-min-device-pixel-ratio : 1.5),only screen and (min-device-pixel-ratio : 1.5) {/* Styles */}]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>Mobile</tag>
</tags>
</entry>
<entry>
<title><![CDATA[面向对象的CSS样式]]></title>
<url>%2F2016%2F02%2F27%2FOOCSS%2F</url>
<content type="text"><![CDATA[** OOCSS:**面向对象的CSS样式,通过对CSS样式的合理规范,重复使用,达到代码的精简,便于换肤。作用:12341. 加强代码复用以便方便维护1. 减少CSS体积1. 提升渲染效率1. 组件库思想、栅格布局可共用、减少选择器、方便扩展注意事项:123456789101112131. 不要直接定义子节点,应把共性声明放到父类.mod .inner{} //1. 结构和皮肤相分离1. 容器和内容相分离1. 抽象出可重用的元素,建好组件库,在组件库内寻找可用的元素组装页面1. 往你想要扩展的对象本身添加Class,而不是他的父节点1. 对象应保持独立性1. 避免使用ID选择器,权重太高,无法重用1. 避免位置相关的样式1. 保证选择器相同的权重1. 类名:简短、清晰、语义化、OOCSS的名字并不影响HTML语义化拓展OOCSSReset优点:样式初始化设置非常全面缺点:设置了部分多余的设置,borderNormalize优点:缺点:有些默认的没有设置Neat.css优点:解决Bug,低级浏览器常见Bug统一效果,但不盲目追求重置为0向后兼容考虑响应式考虑移动设备缺点:]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>OOCSS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[CSS3动画探秘]]></title>
<url>%2F2016%2F02%2F20%2Fanimation%2F</url>
<content type="text"><![CDATA[CSS3动画探秘:Canvas 实现也是可以的,这里不做介绍,本次主题是 css3 动画CSS3实现Demo来自 dribbble 某位大师的作品方式一:切换图片12345678910@-webkit-keyframes GIF{ 0% {background-image: url(GIF_1.png);} 14.3% {background-image: url(GIF_2.png);} 28.6% {background-image: url(GIF_3.png);} 42.9% {background-image: url(GIF_4.png);} 57.2% {background-image: url(GIF_5.png);} 71.5% {background-image: url(GIF_6.png);} 85.8% {background-image: url(GIF_7.png);} 100% {background-image: url(GIF_1.png);}}方式二:切换背景图片位置12345678910@-webkit-keyframes GIF{ 0% {background-position: 0 0;} 14.3% {background-position: -180px 0;} 28.6% {background-position: -360px 0;} 42.9% {background-position: -540px 0;} 57.2% {background-position: -720px 0;} 71.5% {background-position: -900px 0;} 85.8% {background-position: -1080px 0;} 100% {background-position: 0 0;}}方法分析:方式一:实现起来会比较简单,但带来额外的请求数,图片体积较大方式二:需要设计雪碧图,并量取背景位置,请求数少,压缩图片体积CSS3动画帧数计算器1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950案例分析:单向循环利用这个step阶梯函数我们可以做出像一开始我们做出的逐帧动画的效果 雪碧图内图标个数:23==帧数则动作个数:24由于是人物动作,所以要没有停顿效果动作个数:24动作过渡帧数:4.3animation: anim-name 1s linear infinite; 动画标准是一秒24帧@-webkit-keyframes anim-name{ 0%{ /* 动作1 */ } 4.3%{ /* 动作2 */ } 8.6%{ /* 动作3 */ } 12.9%{ /* 动作4 */ } 17.2%{ /* 动作5 */ } 21.5%{ /* 动作6 */ } 25.8%{ /* 动作7 */ } 30.1%{ /* 动作8 */ } 34.4%{ /* 动作9 */ } 38.7%{ /* 动作10 */ } 43%{ /* 动作11 */ } 47.3%{ /* 动作12 */ } 51.6%{ /* 动作13 */ } 55.9%{ /* 动作14 */ } 60.2%{ /* 动作15 */ } 64.5%{ /* 动作16 */ } 68.8%{ /* 动作17 */ } 73.1%{ /* 动作18 */ } 77.4%{ /* 动作19 */ } 81.7%{ /* 动作20 */ } 86%{ /* 动作21 */ } 90.3%{ /* 动作22 */ } 94.6%{ /* 动作23 */ } 100%{ /* 动作24 */ }}.GIF{ width: 800px; height: 600px; margin: auto; background: url(../img/charector.png) 0 0 no-repeat; animation: GIF 1s step-start infinite; -webkit-animation: GIF 1s step-start infinite;}12345用CSS代码的方式表示,就是:单向循环: animation-iteration-count: infinite; animation-direction: normal;双向循环: animation-iteration-count: infinite; animation-direction: alternate;雪碧图合成HTML5在线雪碧图片合成工具使用Compass生成雪碧图SmartSprites 智能批量合并 CSS 雪碧图ispritercssspritesanimation动画H5动效的常见制作手法css3-animation多屏CSS动画精进技巧]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>CSS3</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Node.js实战 建立简单的Web服务器]]></title>
<url>%2F2016%2F02%2F20%2FNodeJsWeb%2F</url>
<content type="text"><![CDATA[简单的Web服务器:作者本身也是刚接触nodejs,所以在知识面方面还存在很多漏洞由于一直到在使用nodejs搭建博客Hexo,但是还想使用服务器,搭建服务器的方法有很多种,但是既然有了NodeJs这样的大牛,我也就懒得用其他的了。123456789直接上代码:首先我们创建一个WebSvr.js,将其放置在文件夹中,通过代码进行启动。spfk@spfk-PC MINGW64$ cd e:/Githubspfk@spfk-PC MINGW64 /e/GithubWIN $ node.exe WebSvr.jsMAC $ node WebSvr.js123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111// 这是一个简单的Node HTTP服务器,能处理当前目录的文件// 并能实现两种特殊的URL用于测试// 用HTTP://localhost:4000或http://127.0.0.1:4000连接这个服务器// 首先加载所有需要用到的模块var http = require('http'); // Http服务器APIvar fs = require('fs'); // 用于处理本地文件var server = new http.Server(); // 创建新的HTTP服务器server.listen(4000); // 监听端口4000// 使用on方法注册时间处理server.on('request', function(request, response) { // 当有request请求的时候触发处理函数 console.log('Request'); // 解析请求的URL var url = require('url').parse(request.url); // 特殊URL会让服务器在发送响应前先等待 switch(url.pathname) { case ''||'/' : // 模拟欢迎页,nodejs是高效流处理的方案,也可以通过配置文件来配置 fs.readFile('./index.html', function(err, content){ if(err) { response.writeHead(404, { 'Content-Type':'text/plain; charset="UTF-8"' }); response.write(err.message); response.end(); } else { response.writeHead(200, { 'Content-Type' : 'text/html; charset=UTF-8' }); response.write(content); response.end(); } }); break; case '/test/delay':// 此处用于模拟缓慢的网络连接 // 使用查询字符串来获取延迟时长,或者2000毫秒 var delay = parseInt(url.query) || 2000; // 设置响应状态和头 response.writeHead(200, {'Content-type':'text/plain; charset=UTF-8'}); // 立即开始编写响应主体 response.write('Sleeping for' + delay + ' milliseconds...'); // 在之后调用的另一个函数中完成响应 setTimeout(function(){ response.write('done.'); response.end(); }, delay); break; case '/test/mirror':// 如果请求是test/mirror,则原文返回它 // 响应状态和头 response.writeHead(200, {'Content-type':'text/plain; charset=UTF-8'}); // 用请求的内容开始编写响应主体 response.write(request.mothod + ' ' + request.url + ' HTTP/' + request.httpVersion + '\r\n'); // 所有的请求头 for (var h in request.headers) { response.write(h + ':' + request.headers[h] + '\r\n'); } response.write('\r\n');// 使用额外的空白行来结束头 // 在这些事件处理程序函数中完成响应 // 当请求主体的数据块完成时,把其写入响应中 request.on('data', function(chunk) { response.write(chunk); }); // 当请求结束时,响应也完成 request.on('end', function(chunk){ response.end(); }); break; case '/json' : // 模拟JSON数据返回 // 响应状态和头 response.writeHead(200, {'Content-type':'application/json; charset=UTF-8'}); response.write(JSON.stringify({test:'success'})); response.end(); break; default:// 处理来自本地目录的文件 var filename = url.pathname.substring(1); // 去掉前导'/' var type = getType(filename.substring(filename.lastIndexOf('.')+1)); // 异步读取文件,并将内容作为单独的数据模块传给回调函数 // 对于确实很大的文件,使用流API fs.createReadStream()更好 fs.readFile(filename, function(err, content){ if(err) { response.writeHead(404, { 'Content-Type':'text/plain; charset="UTF-8"' }); response.write(err.message); response.end(); } else { response.writeHead(200, { 'Content-Type' : type }); response.write(content); response.end(); } }); break; } });function getType(endTag){ var type=null; switch(endTag){ case 'html' : case 'htm' : type = 'text/html; charset=UTF-8'; break; case 'js' : type = 'application/javascript; charset="UTF-8"'; break; case 'css' : type = 'text/css; charset="UTF-8"'; break; case 'txt' : type = 'text/plain; charset="UTF-8"'; break; case 'manifest' : type = 'text/cache-manifest; charset="UTF-8"'; break; default : type = 'application/octet-stream'; break; } return type;}//向控制台输出服务启动的信息 console.log('[WebServer][Start] running at http://localhost:4000');]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>NodeJs</tag>
</tags>
</entry>
<entry>
<title><![CDATA[移动前端知识总结]]></title>
<url>%2F2016%2F01%2F28%2FMobile-knowledge%2F</url>
<content type="text"><![CDATA[移动时代本以为到移动端,就再也不用担心IE兼容问题,可是移动的设备,其实是更大的坑。面对这些问题,一开始我们只能在未知中试错,知道错误的方案,才能更容易寻找正确的解决问题思路。可看到移动web在业界不断趋向于成熟,各种框架和解决方案,不断的涌现让移动端开发不再是个噩梦。这几天把想到的一点经验先罗列出来,后续会持续更新,这篇文章可以给刚接触webapp开发的同学带来帮助,任何疑问欢迎留言探讨!前因后果设备更新换代快低端机遗留下问题、高端机带来新挑战浏览器厂商不统一兼容问题多网络更复杂弱网络,页面打开慢低端机性能差页面操作卡顿HTML5新技术多学习成本不低未知问题坑多常见问题123移动端如何定义字体font-family中文字体使用系统默认即可,英文用Helvetica/* 移动端定义字体的代码 */body{font-family:Helvetica;}参考《移动端使用字体的思考》移动端字体单位font-size选择px还是rem12对于只需要适配少部分手机设备,且分辨率对页面影响不大的,使用px即可对于需要适配各种移动设备,使用rem,例如只需要适配iPhone和iPad等分辨率差别比较挺大的设备meta基础知识H5页面窗口自动调整到设备宽度,并禁止用户缩放页面1<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />忽略将页面中的数字识别为电话号码1<meta name="format-detection" content="telephone=no" />忽略Android平台中对邮箱地址的识别1<meta name="format-detection" content="email=no" />当网站添加到主屏幕快速启动方式,可隐藏地址栏,仅针对ios的safari12<meta name="apple-mobile-web-app-capable" content="yes" /><!-- ios7.0版本以后,safari上已看不到效果 -->体验demo,解决在主屏幕打开页面后,点击页面链接不会跳转到系统自带的Safari将网站添加到主屏幕快速启动方式,仅针对ios的safari顶端状态条的样式12<meta name="apple-mobile-web-app-status-bar-style" content="black" /><!-- 可选default、black、black-translucent -->viewport模板viewport模板——通用1234567891011121314<!DOCTYPE html><html><head><meta charset="utf-8"><meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"><meta content="yes" name="apple-mobile-web-app-capable"><meta content="black" name="apple-mobile-web-app-status-bar-style"><meta content="telephone=no" name="format-detection"><meta content="email=no" name="format-detection"><title>标题</title><link rel="stylesheet" href="index.css"></head><body>这里开始内容</body></html>viewport模板 - target-densitydpi=device-dpi,android 2.3.5以下版本不支持123456789101112131415<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=750, user-scalable=no, target-densitydpi=device-dpi"><!-- width取值与页面定义的宽度一致 --><meta content="yes" name="apple-mobile-web-app-capable"><meta content="black" name="apple-mobile-web-app-status-bar-style"><meta content="telephone=no" name="format-detection"><meta content="email=no" name="format-detection"><title>标题</title><link rel="stylesheet" href="index.css"></head><body>这里开始内容</body></html>参考案例:http://action.weixin.qq.com/payact/readtemplate?t=mobile/2015/wxzfsht/index_tmplrem配置参考:12345678910111213141516html{font-size:10px}@media screen and (min-width:321px) and (max-width:375px){html{font-size:11px}}@media screen and (min-width:376px) and (max-width:414px){html{font-size:12px}}@media screen and (min-width:415px) and (max-width:639px){html{font-size:15px}}@media screen and (min-width:640px) and (max-width:719px){html{font-size:20px}}@media screen and (min-width:720px) and (max-width:749px){html{font-size:22.5px}}@media screen and (min-width:750px) and (max-width:799px){html{font-size:23.5px}}@media screen and (min-width:800px){html{font-size:25px}}体验demo:http://1.peunzhang.sinaapp.com/demo/rem/index.html1234567移动端touch事件(区分webkit 和 winphone)当用户手指放在移动设备在屏幕上滑动会触发的touch事件以下支持webkittouchstart——当手指触碰屏幕时候发生。不管当前有多少只手指touchmove——当手指在屏幕上滑动时连续触发。通常我们再滑屏页面,会调用event的preventDefault()可以阻止默认情况的发生:阻止页面滚动touchend——当手指离开屏幕时触发touchcancel——系统停止跟踪触摸时候会触发。例如在触摸过程中突然页面alert()一个提示框,此时会触发该事件,这个事件比较少用12345TouchEventtouches:屏幕上所有手指的信息targetTouches:手指在目标区域的手指信息changedTouches:最近一次触发该事件的手指信息touchend时,touches与targetTouches信息会被删除,changedTouches保存的最后一次的信息,最好用于计算手指信息参数信息(changedTouches[0])clientX、clientY在显示区的坐标target:当前元素参考:https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent以下支持winphone 8MSPointerDown——当手指触碰屏幕时候发生。不管当前有多少只手指MSPointerMove——当手指在屏幕上滑动时连续触发。通常我们再滑屏页面,会调用css的html{-ms-touch-action: none;}可以阻止默认情况的发生:阻止页面滚动MSPointerUp——当手指离开屏幕时触发移动端click屏幕产生200-300 ms的延迟响应移动设备上的web网页是有300ms延迟的,玩玩会造成按钮点击延迟甚至是点击失效。以下是历史原因,来源一个公司内一个同事的分享:2007年苹果发布首款iphone上IOS系统搭载的safari为了将适用于PC端上大屏幕的网页能比较好的展示在手机端上,使用了双击缩放(double tap to zoom)的方案,比如你在手机上用浏览器打开一个PC上的网页,你可能在看到页面内容虽然可以撑满整个屏幕,但是字体、图片都很小看不清,此时可以快速双击屏幕上的某一部分,你就能看清该部分放大后的内容,再次双击后能回到原始状态。双击缩放是指用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。12原因就出在浏览器需要如何判断快速点击上,当用户在屏幕上单击某一个元素时候,例如跳转链接<a href="#"></a>,此处浏览器会先捕获该次单击,但浏览器不能决定用户是单纯要点击链接还是要双击该部分区域进行缩放操作,所以,捕获第一次单击后,浏览器会先Hold一段时间t,如果在t时间区间里用户未进行下一次点击,则浏览器会做单击跳转链接的处理,如果t时间里用户进行了第二次单击操作,则浏览器会禁止跳转,转而进行对该部分区域页面的缩放操作。那么这个时间区间t有多少呢?在IOS safari下,大概为300毫秒。这就是延迟的由来。造成的后果用户纯粹单击页面,页面需要过一段时间才响应,给用户慢体验感觉,对于web开发者来说是,页面js捕获click事件的回调函数处理,需要300ms后才生效,也就间接导致影响其他业务逻辑的处理。解决方案:fastclick可以解决在手机上点击事件的300ms延迟zepto的touch模块,tap事件也是为了解决在click的延迟问题触摸事件的响应顺序1、ontouchstart 2、ontouchmove 3、ontouchend 4、onclick解决300ms延迟的问题,也可以通过绑定ontouchstart事件,加快对事件的响应什么是Retina 显示屏,带来了什么问题retina:一种具备超高像素密度的液晶屏,同样大小的屏幕上显示的像素点由1个变为多个,如在同样带下的屏幕上,苹果设备的retina显示屏中,像素点1个变为4个在高清显示屏中的位图被放大,图片会变得模糊,因此移动端的视觉稿通常会设计为传统PC的2倍那么,前端的应对方案是:设计稿切出来的图片长宽保证为偶数,并使用backgroud-size把图片缩小为原来的1/2//例如图片宽高为:200px*200px,那么写法如下.css{width:100px;height:100px;background-size:100px 100px;}其它元素的取值为原来的1/2,例如视觉稿40px的字体,使用样式的写法为20px.css{font-size:20px}参考《高清显示屏原理及设计方案》ios系统中元素被触摸时产生的半透明灰色遮罩怎么去掉ios用户点击一个链接,会出现一个半透明灰色遮罩, 如果想要禁用,可设置-webkit-tap-highlight-color的alpha值为0,也就是属性值的最后一位设置为0就可以去除半透明灰色遮罩a,button,input,textarea{-webkit-tap-highlight-color: rgba(0,0,0,0;)}部分android系统中元素被点击时产生的边框怎么去掉android用户点击一个链接,会出现一个边框或者半透明灰色遮罩, 不同生产商定义出来额效果不一样,可设置-webkit-tap-highlight-color的alpha值为0去除部分机器自带的效果a,button,input,textarea{-webkit-tap-highlight-color: rgba(0,0,0,0;)-webkit-user-modify:read-write-plaintext-only; }-webkit-user-modify有个副作用,就是输入法不再能够输入多个字符另外,有些机型去除不了,如小米2对于按钮类还有个办法,不使用a或者input标签,直接用div标签参考《如何去除android上a标签产生的边框》winphone系统a、input标签被点击时产生的半透明灰色背景怎么去掉1<meta name="msapplication-tap-highlight" content="no">webkit表单元素的默认外观怎么重置1.css{-webkit-appearance:none;}webkit表单输入框placeholder的颜色值能改变么1input::-webkit-input-placeholder{color:#AAAAAA;}input:focus::-webkit-input-placeholder{color:#EEEEEE;}webkit表单输入框placeholder的文字能换行么123456ios可以,android不行~在textarea标签下都可以换行~IE10(winphone8)表单元素默认外观如何重置禁用 select 默认下拉箭头::-ms-expand 适用于表单选择控件下拉箭头的修改,有多个属性值,设置它隐藏 (display:none) 并使用背景图片来修饰可得到我们想要的效果。select::-ms-expand {display: none;}禁用 radio 和 checkbox 默认样式12::-ms-check 适用于表单复选框或单选按钮默认图标的修改,同样有多个属性值,设置它隐藏 (display:none) 并使用背景图片来修饰可得到我们想要的效果。input[type=radio]::-ms-check,input[type=checkbox]::-ms-check{display: none;}禁用PC端表单输入框默认清除按钮123当表单文本输入框输入内容后会显示文本清除按钮,::-ms-clear 适用于该清除按钮的修改,同样设置使它隐藏 (display:none) 并使用背景图片来修饰可得到我们想要的效果。input[type=text]::-ms-clear,input[type=tel]::-ms-clear,input[type=number]::-ms-clear{display: none;}禁止ios 长按时不触发系统的菜单,禁止ios&android长按时下载图片1.css{-webkit-touch-callout: none}禁止ios和android用户选中文字1.css{-webkit-user-select:none}参考《如何改变表单元素的外观(for Webkit and IE10)》打电话发短信写邮件怎么实现12打电话<a href="tel:0755-10086">打电话给:0755-10086</a>12发短信,winphone系统无效<a href="sms:10086">发短信给: 10086</a>写邮件,可参考《移动web页面给用户发送邮件的方法》1<a href="mailto:[email protected]">[email protected]</a>模拟按钮hover效果移动端触摸按钮的效果,可明示用户有些事情正要发生,是一个比较好体验,但是移动设备中并没有鼠标指针,使用css的hover并不能满足我们的需求,还好国外有个激活css的active效果,代码如下,123456789101112131415161718192021222324252627282930313233343536<!DOCTYPE html><html><head> <meta charset="utf-8"> <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"> <meta content="yes" name="apple-mobile-web-app-capable"> <meta content="black" name="apple-mobile-web-app-status-bar-style"> <meta content="telephone=no" name="format-detection"> <meta content="email=no" name="format-detection"> <style type="text/css"> a{ -webkit-tap-highlight-color: rgba(0,0,0,0); } .btn-blue{ display:block; height:42px; line-height:42px; text-align:center; border-radius:4px; font-size:18px; color:#FFFFFF; background-color: #4185F3; } .btn-blue:active{ background-color: #357AE8; } </style></head><body> <div class="btn-blue">按钮</div> <script type="text/javascript"> document.addEventListener("touchstart", function(){ }, true) </script></body></html>兼容性ios5+、部分android 4+、winphone 8要做到全兼容的办法,可通过绑定ontouchstart和ontouchend来控制按钮的类名12345678910111213141516<!DOCTYPE html><html><head><meta charset="utf-8"><meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"><meta content="yes" name="apple-mobile-web-app-capable"><meta content="black" name="apple-mobile-web-app-status-bar-style"><meta content="telephone=no" name="format-detection"><meta content="email=no" name="format-detection"><style type="text/css">a{-webkit-tap-highlight-color: rgba(0,0,0,0);}.btn-blue{display:block;height:42px;line-height:42px;text-align:center;border-radius:4px;font-size:18px;color:#FFFFFF;background-color: #4185F3;}.btn-blue-on{background-color: #357AE8;}</style></head><body><div class="btn-blue">按钮</div><script type="text/javascript">var btnBlue = document.querySelector(".btn-blue");btnBlue.ontouchstart = function(){ this.className = "btn-blue btn-blue-on"}btnBlue.ontouchend = function(){ this.className = "btn-blue"}</script></body></html>屏幕旋转的事件和样式12345678910事件window.orientation,取值:正负90表示横屏模式、0和180表现为竖屏模式;window.onorientationchange = function(){ switch(window.orientation){ case -90: case 90: alert("横屏:" + window.orientation); case 0: case 180: alert("竖屏:" + window.orientation); break; }}123456789101112样式//竖屏时使用的样式@media all and (orientation:portrait) { .css{}}//横屏时使用的样式@media all and (orientation:landscape) { .css{}}audio元素和video元素在ios和andriod中无法自动播放应对方案:触屏即播1$('html').one('touchstart',function(){ audio.play()})可参考《无法自动播放的audio元素》摇一摇功能HTML5 deviceMotion:封装了运动传感器数据的事件,可以获取手机运动状态下的运动加速度等数据。体验demo:手机拍照和上传图片1<input type="file">的accept 属性1234<!-- 选择照片 --><input type=file accept="image/*"><!-- 选择视频 --><input type=file accept="video/*">使用总结:123456789101112131415ios 有拍照、录像、选取本地图片功能部分android只有选取本地图片功能winphone不支持input控件默认外观丑陋微信浏览器用户调整字体大小后页面矬了,怎么阻止用户调整原因android侧是复写了layoutinflater 对textview做了统一处理ios侧是修改了body.style.webkitTextSizeAdjust值解决方案:android使用以下代码,该接口只在微信浏览器下有效(感谢jationhuang同学提供)/ * 页面加入这段代码可使Android机器页面不再受到用户字体缩放强制改变大小 * 但是会有一个1秒左右的延迟,期间可以考虑通过loading展示 * 仅供参考 */(function(){ if (typeof(WeixinJSBridge) == "undefined") { document.addEventListener("WeixinJSBridgeReady", function (e) { setTimeout(function(){ WeixinJSBridge.invoke('setFontSizeCallback',{"fontSize":0}, function(res) { alert(JSON.stringify(res)); }); },0); }); } else { setTimeout(function(){ WeixinJSBridge.invoke('setFontSizeCallback',{"fontSize":0}, function(res) { alert(JSON.stringify(res)); }); },0); }})();ios使用-webkit-text-size-adjust禁止调整字体大小1234body{-webkit-text-size-adjust: 100%!important;}最好的解决方案:整个页面用rem或者百分比布局消除transition闪屏12345网络都是这么写的,但我并没有测试出来.css{/*设置内嵌的元素在 3D 空间如何呈现:保留 3D*/-webkit-transform-style: preserve-3d;/*(设置进行转换的元素的背面在面对用户时是否可见:隐藏)*/-webkit-backface-visibility: hidden;}开启硬件加速解决页面闪白保证动画流畅1.css { -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);}参考《用CSS开启硬件加速来提高网站性能》取消input在ios下,输入的时候英文首字母的默认大写1<input autocapitalize="off" autocorrect="off" />android 上去掉语音输入按钮input::-webkit-input-speech-button {display: none}android 2.3 bug@-webkit-keyframes 需要以0%开始100%结束,0%的百分号不能去掉after和before伪类无法使用动画animationborder-radius不支持%单位translate百分比的写法和scale在一起会导致失效,例如-webkit-transform: translate(-50%,-50%) scale(-0.5, 1)android 4.x bug三星 Galaxy S4中自带浏览器不支持border-radius缩写同时设置border-radius和背景色的时候,背景色会溢出到圆角以外部分部分手机(如三星),a链接支持鼠标:visited事件,也就是说链接访问后文字变为紫色android无法同时播放多音频audio参考《border-radius 移动之伤》设计高性能CSS3动画的几个要素尽可能地使用合成属性transform和opacity来设计CSS3动画,不使用position的left和top来定位利用translate3D开启GPU加速参考《High Performance Animations》fixed bugios下fixed元素容易定位出错,软键盘弹出时,影响fixed元素定位android下fixed表现要比iOS更好,软键盘弹出时,不会影响fixed元素定位ios4下不支持position:fixed解决方案可用isroll.js,暂无完美方案参考《移动端web页面使用position:fixed问题总结》《使用iScroll.js解决ios4下不支持position:fixed的问题》如何阻止windows Phone的默认触摸事件winphone下默认触摸事件事件使用e.preventDefault是无效的目前解决方法是使用样式来禁用html{-ms-touch-action: none;}/* 禁止winphone默认触摸事件 */《Windows phone 8 touch support123<!--1.目前只有ios7+、winphone8+支持自动播放2.支持Airplay的设备(如:音箱、Apple TV)播放x-webkit-airplay="true" 3.播放视频不全屏,ios7+、winphone8+支持,部分android4+支持(含华为、小米、魅族)webkit-playsinline="true" --><video x-webkit-airplay="true" webkit-playsinline="true" preload="auto" autoplay src="http://"></video>体验demo:常用的移动端框架zepto.js语法与jquery几乎一样,会jquery基本会zepto~最新版本已经更新到1.16官网:中文(非官网):常使用的扩展模块:浏览器检测:tap事件:iscroll.js解决页面不支持弹性滚动,不支持fixed引起的问题~实现下拉刷新,滑屏,缩放等功能~最新版本已经更新到5.0官网:underscore.js笔者没用过,不过听说好用,推荐给大家~该库提供了一整套函数式编程的实用功能,但是没有扩展任何JavaScript内置对象。最新版本已经更新到1.8.2官网:滑屏框架适合上下滑屏、左右滑屏等滑屏切换页面的效果slip.jsiSlider.jsfullpage.jsswiper.jsflex布局flex布局目前可使用在移动中,并非所有的语法都全兼容,但以下写法笔者实践过,效果良好~1234567891011121314151617181920212223242526272829303132333435363738394041424344flex:定义布局为盒模型 flex-v:盒模型垂直布局 flex-1:子元素占据剩余的空间 flex-align-center:子元素垂直居中 flex-pack-center:子元素水平居中 flex-pack-justify:子元素两端对齐 兼容性:ios 4+、android 2.3+、winphone8+ .flex{ display:-webkit-box; display:-webkit-flex; display:-ms-flexbox; display:flex;}.flex-v{ -webkit-box-orient:vertical; -webkit-flex-direction:column; -ms-flex-direction:column; flex-direction:column;}.flex-1{ -webkit-box-flex:1; -webkit-flex:1; -ms-flex:1; flex:1;}.flex-align-center{ -webkit-box-align:center; -webkit-align-items:center; -ms-flex-align:center; align-items:center;}.flex-pack-center{ -webkit-box-pack:center; -webkit-justify-content:center; -ms-flex-pack:center; justify-content:center;}.flex-pack-justify{ -webkit-box-pack:justify; -webkit-justify-content:space-between; -ms-flex-pack:justify; justify-content:space-between;}示例:两端对齐1234567891011121314151617181920212223242526<!DOCTYPE html><html><head><meta charset="utf-8"><meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"><meta content="yes" name="apple-mobile-web-app-capable"><meta content="black" name="apple-mobile-web-app-status-bar-style"><meta content="telephone=no" name="format-detection"><meta content="email=no" name="format-detection"><style type="text/css">/* flex:定义布局为盒模型flex-v:盒模型垂直布局flex-1:子元素占据剩余的空间flex-align-center:子元素垂直居中flex-pack-center:子元素水平居中flex-pack-justify:子元素两端对齐 兼容性:ios 4+、android 2.3+、winphone8+ */.flex{ display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}.flex-v{-webkit-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.flex-1{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;}.flex-align-center{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;}.flex-pack-center{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}.flex-pack-justify{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;}</style></head><body><div class="flex flex-pack-justify"> <div>模块一</div> <div>模块二</div> <div>模块三</div> <div>模块四</div></div></body></html>使用注意:flex下的子元素必须为块级元素,非块级元素在android2.3机器下flex失效flex下的子元素宽度和高度不能超过父元素,否则会导致子元素定位错误,例如水平垂直居中参考:flexyboxes“老”的Flexbox和“新”的Flexbox跨浏览器的FlexboxFastClick消除在移动浏览器上触发click事件与一个物理Tap(敲击)之间的300延迟参考《FastClick》Sea.js提供简单、极致的模块化开发体验简单友好的模块定义规范:Sea.js 遵循 CMD 规范,可以像 Node.js 一般书写模块代码。自然直观的代码组织方式:依赖的自动加载、配置的简洁清晰,可以让我们更多地享受编码的乐趣。地址:http://seajs.org/docs/目录(更新于20160128)meta基础知识H5页面窗口自动调整到设备宽度,并禁止用户缩放页面忽略将页面中的数字识别为电话号码忽略Android平台中对邮箱地址的识别当网站添加到主屏幕快速启动方式,可隐藏地址栏,仅针对ios的safari将网站添加到主屏幕快速启动方式,仅针对ios的safari顶端状态条的样式viewport模板常见问题移动端如何定义字体font-family移动端字体单位font-size选择px还是rem移动端touch事件(区分webkit 和 winphone)移动端click屏幕产生200-300 ms的延迟响应触摸事件的响应顺序什么是Retina 显示屏,带来了什么问题ios系统中元素被触摸时产生的半透明灰色遮罩怎么去掉部分android系统中元素被点击时产生的边框怎么去掉winphone系统a、input标签被点击时产生的半透明灰色背景怎么去掉webkit表单元素的默认外观怎么重置webkit表单输入框placeholder的颜色值能改变么webkit表单输入框placeholder的文字能换行么IE10(winphone8)表单元素默认外观如何重置禁止ios 长按时不触发系统的菜单,禁止ios&android长按时下载图片禁止ios和android用户选中文字打电话发短信写邮件怎么实现模拟按钮hover效果屏幕旋转的事件和样式audio元素和video元素在ios和andriod中无法自动播放摇一摇功能手机拍照和上传图片微信浏览器用户调整字体大小后页面矬了,怎么阻止用户调整消除transition闪屏开启硬件加速取消input在ios下,输入的时候英文首字母的默认大写android上去掉语音输入按钮android 2.3 bugandroid 4.x bug设计高性能CSS3动画的几个要素fixed bug如何阻止windows Phone的默认触摸事件播放视频不全屏常用的移动端框架zepto.jsiscroll.jsunderscore.js滑屏框架flex布局FastClickSea.js移动布局:MDN:手机网页开发MDN:在移动浏览器中使用viewport元标签控制布局移动前端开发和 Web 前端开发的区别是什么Alloyteam移动开发规范概述手机/移动前端开发需要注意的20个要点w3cplus响应式技术资源浅谈移动Web开发Alloyteam Mars移动WEB开发入门移动开发资源集合The Mobile Web HandbookMobileWeb 适配总结移动前端不得不了解的html5 head 头标签]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>Mobile</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Ajax学习计划]]></title>
<url>%2F2016%2F01%2F27%2FAjax%2F</url>
<content type="text"><![CDATA[AJAX:Asynchronous Javascript And XML(异步JavaScript和XML)。是指一种创建交互式网页应用的网页开发技术。 AJAX = 异步 JavaScript和XML(标准通用标记语言的子集)。 AJAX 是一种用于创建快速动态网页的技术。 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。 传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。Ajax介绍特点:12什么是服务器:搭建简单的本地服务器软件Wamp、XAMPP,提供简单的用户服务,读取数据。使用Ajax12345基础:请求并显示静态TXT、json文件字符集编码:UTF-8、GB2312,使用相同的编码。缓存:chrome下的缓存还不是很严重,IE下的缓存比较严重,除非关闭浏览器。缓存的工作原理:通过URL进行缓存的。通常可以使用URL?t= + new Date().getTime()123456789101112window.onload = function (){ var oBtn = document.getElementById('Btn1'); oBtn.onclick = function (){ ajax('aa.txt?t=' + new Date().getTime(), function(str){ alert(str); },function(){ alert('失败'); }); }}通过Ajax读取的都是字符串1234567891011121314通过eval()将文件内容解析成JS可以识别的内容window.onload = function (){ var oBtn = document.getElementById('Btn1'); oBtn.onclick = function (){ ajax('aa.txt?t=' + new Date().getTime(), function(str){ var SA = eval(str); alert(SA[1]); },function(){ alert('失败'); }); }}读取Json文件123456789101112131415161718192021window.onload = function (){ var oBtn = document.getElementById('Btn1'); var oUls = document.getElementById('ul1'); oBtn.onclick = function (){ ajax('aa.txt?t=' + new Date().getTime(), function(str){ var SA = eval(str); for(var i=0;i<SA.length;i++){ var oLi = document.createElement('li'); oLi.innnerHTML='用户名:<strong>' + SA[i].name +'</strong>密码:<span>' + SA[i].pass + '</span>'; //添加到Ul里 oUl.appenChild(oLi); } alert(SA[1]); },function(){ alert('失败'); }); }}123456789HTTP请求的方法GET:用于获取数据(如:浏览贴子)POST:用于上传数据(如:用户注册)区别:get是在URL里传送数据:安全性低、容量有限(2000字符),有缓存,适合请求信息post是通过HTTP请求,安全性好一点,无缓存,适合传递信息安全的方式使用HTTPS。GET方式:?name=word&password=passwordAjax进阶创建Ajax1234IE6var oAjax = new ActiveXObject("Microsoft.XMLHTTP");var oAjax = new XMLHttpRequest();1234567注意://使用没有定义的变量——报错alert(a);//使用没有定义的属性——undefinedalert(window.a);1234567function (){ if(window.XMLHttpRequest){ var oAjax = new XMLHttpRequest(); }else{ var oAjax = new ActiveXObject("Microsoft.XMLHTTP"); }}连接服务器1234567891011121314open(方法,连接的文件名,同步/async异步true)ajxa其实都是异步的open(method,url,async);oAjax.opan('GET','a.text?=t'+new Date().getTime(),true);同步和异步的区别?同步:(一次加载)浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,j进行下一步操作。异步:(同时加载)浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容。(待完善)发送请求12oAjax.send();send(string);接收返回12345678910oAjax.onreadystatechange = function(){ //浏览器和服务器,进行到哪一步了 if(oAjax.readyState==4){ if(oAjax.status==200){ alert('成功:'+oAjax.status); }else{ alert('失败:'+oAjax.status); } }}123450 (未初始化)1 (载入)2 (载入完成)send()方法完成,已接收全部信息3 (解析)正在解析响应4 (完成)完成但不代表成功123456Ajax Status请求状态200 成功3013044041234IE6var oAjax = new ActiveXObject("Microsoft.XMLHTTP");var oAjax = new XMLHttpRequest();1234567891011121314151617181920212223242526272829封装函数function ajax(url,fnSucc,fnFaild){ if(window.XMLHttpRequest){ var oAjax = new XMLHttpRequest(); }else{ var oAjax = new ActiveXObject("Microsoft.XMLHTTP"); } oAjax.opan('GET','url?=t'+new Date().getTime(),true); oAjax.send(); oAjax.onreadystatechange = function(){ if(oAjax.readyState==4){ if(oAjax.status==200){ fnSucc(oAjax.responseText); }else{ if(fnFaild){ fnFaild(oAjax.status); } } } }}ajax('a.txt',function(str){ alert(str);})12345678910111213141516171819202122232425262728293031封装函数function ajax(url,data,fnSucc,fnFaild){ if(window.XMLHttpRequest){ var oAjax = new XMLHttpRequest(); }else{ var oAjax = new ActiveXObject("Microsoft.XMLHTTP"); } oAjax.opan('POST','url',true); oAjax.setRequestHeader("Content-type","application/x-www-form-urlencoded"); oAjax.send(data); oAjax.onreadystatechange = function(){ if(oAjax.readyState==4){ if(oAjax.status==200){ fnSucc(oAjax.responseText); }else{ if(fnFaild){ fnFaild(oAjax.status); } } } }}ajax('a.txt','name=' + document.getElementById("staffName").value + '&number=' + document.getElementById("staffNumber").value + '&sex=' + document.getElementById("staffSex").value + '&job=' + document.getElementById("staffJob").value,function(str){ alert(str);})Ajax数据1XML、Json:同等数据量,XML更大]]></content>
<categories>
<category>Ajax</category>
</categories>
<tags>
<tag>Ajax</tag>
</tags>
</entry>
<entry>
<title><![CDATA[前端Chrome插件]]></title>
<url>%2F2016%2F01%2F20%2FChromePlug%2F</url>
<content type="text"><![CDATA[** Google Chrome **是最好用的几个浏览器之一,自从2011年11月份赶超Firefox之后,已成为当今互联网的主流浏览器。今天,我来分享下自己收集的一系列Chrome插件,希望能够提高大家的工作效率。Devtools Termina在浏览器中的终端。开发调试利器!LiveReloa成LiveReload官方应用(Mac和Windows)以及guard-livereload、yeoman等第三方工具。帮助开发者快速构建Web应用。BrowserStack Local本地测试工具,借助它可以快速完成本地/内部服务器配置和测试工作,以及HTML、CSS、JavaScript静态文件的配置和测试。用BrowserStack提供的安全、便捷的云服务,在700多个真实的桌面系统和移动浏览器中,测试应用的布局、工作流和交互性。JSONView来验证和查看JSON文件。Postman口调试工具。接口编写、调试、文档撰写过程使用它能提升工作效率。有100多万用户了。Window Resizer整浏览器窗口大小,模拟各种分辨率。帮助Web设计师和开发者测试多种分辨率下的布局效果。WhatFont识别网页所使用的字体。Page Ruler取任意网页中元素大小、位置信息。Web Developer Checklist自己的网站是否符合Web设计、开发的最佳实践?对照这份清单,就能很容易发现网站是否有问题。Image Downloader查看和下载网页中的图像。Alexa Traffic RankAlexa Internet为Chrome开发的免费网站流量排名查看工具。在不干扰用户访问网站的情况下,给出当前网站的Alexa数据。Eye Dropper开源拾色器软件,可以从网页、其他拾色器和你用过的颜色中拾取颜色。Firebug Lite它可不是用来替代Firebug或Chrome的开发者工具,而是配合这些工具来使用。你可以像使用Firebug那样,用它来查看HTML、DOM元素和盒子模型。它还能提供其他比较酷的功能,比如用鼠标查看HTML元素,编辑CSS属性后能立马看到效果等。Web Developer工具栏形式提供一系列Web开发工具, 这是Web Developer官方为Chrome开发的版本,他们也为 Firefox、Opera开发了相应插件。Responsive Inspector于查看被访问网站的媒体特性(media query)。开发响应式Web布局时,可以直观地显示CSS样式表所定义的分辨率的效果。BuiltWith用于查看当前网站使用什么技术搭建。Corporate Ipsum随机生成企业相关信息,作为占位文本,方便查看布局效果。User-Agent Switcher修改用户代理(User-Agent)字符串,以伪装成某些浏览器和操作系统,还可以伪造特定的URL。YSlow分析网页,根据能够提高网页性能的一组规则,提出性能改进建议。CSS Shapes Editor在所选中元素上方显示交互式编辑器,用于新建和调整用CSS写的图形。Pesticide在当前网页插入Pesticide CSS,为元素添加明显的边框,方便查看元素位置。Responsive Web Design Tester试移动网站在移动设备上的效果。该插件能够模拟不同尺寸、装有不同浏览器的移动设备。Palettab安装后,新开一页卡,就能看到5种颜色和字体搭配方案!每次点击新页卡,就能有新发现。jQuery Audit在元素面板创建侧边栏,显示jQuery委托代理事件、内部数据、当前选中的DOM节点、函数和对象等信息。Font Changer改包括Facebook、Twitter、Google、Youtube在内的任意网站的字体。可以试试Google Web Fonts字体的效果。HTML5 Outliner使用网页中的标题和分区信息,创建可点击的大纲视图。PerfectPixel在页面上显示半透明的图像,便于逐像素对比调整前后的页面效果,以达到最佳水准。SelectorGadget有了这个开源工具,为复杂网站的元素生成CSS选择器,以及查看选择器所匹配的元素都将变得轻而易举。Stylebot快速修改网站样式。]]></content>
<categories>
<category>Plug</category>
</categories>
<tags>
<tag>Chrome</tag>
</tags>
</entry>
<entry>
<title><![CDATA[原生JS TitleTip]]></title>
<url>%2F2016%2F01%2F19%2FJSTip%2F</url>
<content type="text"><![CDATA[** 自用笔记:**本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why原生JS TitleTip为了实现对特定的A标签Title的美化,使其可以按照我们想要的样式显示。方案一:Demo1<a href="#" class="TitleTip" title="BI Scp" >A标签TitleTip</a>12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394<script type="text/javascript"> var Common = { getItself: function(id) { return "string" == typeof id ? document.getElementById(id) : id; }, getTextSize: function(text) { var span = document.createElement("span"); var result = {}; result.width = span.offsetWidth; result.height = span.offsetWidth; span.style.visibility = "hidden"; document.body.appendChild(span); if (typeof span.textContent != "undefined") span.textContent = text; else span.innerText = text; result.width = span.offsetWidth - result.width; result.height = span.offsetHeight - result.height; span.parentNode.removeChild(span); return result; } } var TitleTip = { showTitleTip: function(param, linkObj, e) { var div; if (document.getElementById("TitleTipDiv")) { document.body.removeChild(document.getElementById("TitleTipDiv")); } div = document.createElement("div"); div.id = "TitleTipDiv"; // div.style.cssText = "text-align: center; color: #fff; background: rgba(0,0,0,.8); position: absolute; z-index: 100; padding: 5px 15px; font-size: 12px; line-height: 20px; transform: translate(-50%); border-radius: 6px;"; div.innerHTML = linkObj.tip; document.body.appendChild(div); if (param && param.width) { //如未设置,默认一行显示 if (Common.getTextSize(div.innerHTML).width < param.width) { div.style.maxWidth = param.width + "px"; } else { div.style.width = param.width + "px"; } } //must before set opr to get offsetHeight... div.style.display = ""; ///set TitleTip position // console.log("a W"+linkObj.offsetWidth); // console.log("a H"+linkObj.offsetHeight); // console.log("a X"+linkObj.offsetTop); // console.log("a Y"+linkObj.offsetLeft); // console.log("Tip W"+div.offsetWidth); // console.log("Tip H"+div.offsetHeight); div.style.top = linkObj.offsetTop + linkObj.offsetHeight + 8 + "px"; div.style.left = linkObj.offsetLeft + linkObj.offsetWidth/2 + "px"; ///hide TitleTip after some time if (param && param.time) { setTimeout(this.hidTitleTip, param.time); } }, hidTitleTip: function() { if (document.getElementById("TitleTipDiv")) { document.getElementById("TitleTipDiv").style.display = "none"; } }, addTips: function(param) { var linkArr = document.getElementsByTagName("a"); if (!linkArr) { return false; } for (i = 0; i < linkArr.length; i++) { if (linkArr[i].className == "TitleTip") { linkArr[i].tip = linkArr[i].title; var tipObj = this; linkArr[i].onmouseover = function(e) { tipObj.showTitleTip(param, this, e); } linkArr[i].onmouseout = tipObj.hidTitleTip; if (param && param.moveable == true) { //默认不滚动 linkArr[i].onmousemove = function(e) { tipObj.showTitleTip(param, this, e); } } linkArr[i].title = ""; } } } } window.onload = function() { TitleTip.addTips({ width: 200 }); // time:5000, moveable: true }</script>]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[【转】2015-2016前端知识体系]]></title>
<url>%2F2016%2F01%2F16%2FFrontMap%2F</url>
<content type="text"><![CDATA[** 前端知识体系:**总结了下前端这两年的主流技术,大部分技术在我的博客里有较深入的研究学习对应技术博客地址:http://ouvens.github.io ,博客持续更新中,欢迎大家关注~框架与组件bootstrap等UI框架设计与实现1234567891011121314伸缩布局:grid网格布局基础UI样式:元素reset、按钮、图片、菜单、表单组件UI样式:按钮组、字体图标、下拉菜单、输入框组、导航组、面包屑、分页、标签、轮播、弹出框、列表、多媒体、警告响应式布局:布局、结构、样式、媒体、javascript响应式第三方插件:插件管理jQuery、zepto使用原理以及插件开发12支持amd、cmd、全局变量的模块化封装$.fn.method=function(){}mvc/mvvm框架原理设计,vue/angular/avalon等1234567891011121314directive设计:html、text、class、html、attr、repeat、ref,可扩展filter设计:bool、upperCase、lowerCase,可扩展表达式设计:if-else等实现viewmodel结构设计:例如数据,元素,方法的挂载与作用域数据更变检测:函数触发,脏数据检测、对象hijackingpolymer/angular2思想与设计思路1234import技术template和script引入方式css样式命名空间隔离简单复用第三方库reactjs原理与使用123virtualdom单向数据绑定js执行语法方式UI由状态控制commonJS/AMD/CMD12345模块引入模块定义模块标识UMD解决不同规范兼容性的问题,例如webpack封装模块懒执行(CMD)与与预执行(AMD)loadJs模块化加载原理与实现12345创建script标签,需要id映射到资源urlonload加载模块队列判断全部加载完成后触发加载失败问题优化requirejs、modjs、seajspolyfill、shim原理与实现12polyfill提供了开发者们希望浏览器原生提供支持的功能特性shim将新的API引入到旧的环境中,且仅靠旧环境中已有的手段实现virtualDom、IncrementalDOM123451.用js对象树表示dom树结构,根据该对象树构建dom树2.状态改变时,重新构建对象,和旧的对象对比,记录两个对象树差异3.将对象树差异应用到dom中小结:js对象模拟dom(elem.js),virtualdomdiff算法(diff.js)、差异渲染dom(patch.js)incrementaldom在状态改变时扫描旧对象树将差异直接应用到dom中shadowdom12345隔离外部环境用于封装组件:结构、样式、行为实现形式:新标签、class类属性+构建编译webwork与serviceWorker123webwork与主线程机制,on/postserviceworker可作为浏览器请求代理应用场景ES6转ES5、Babel与ES6开发规范体系1234567ES6编码规范全ES6在babel下兼容性ES6在node下兼容性与性能ES6新特性:看编码规范aureliaES6前端框架IsomorphicJavaScript12345678同构原理同构方案Rendrnodejs:服务器hapi:应用服务backbone.js:后台mvcrequirejs:模块加载jquery:dom处理reactjs同构:React+Flux+Koa双向数据绑定123函数触发:vuejs脏数据检测:angular对象hijacking:avalonbrowserify运行原理123451.从入口模块开始分析require函数调用2.根据依赖生成AST3.根据AST找到每个模块的模块名4.得到每个模块的依赖关系,生成一个依赖字典5.包装每个模块(传入依赖字典以及export和require函数),生成执行的jsperformancetiming1234performancetimingapiperformancetiming过程performancetiming性能计算performanceTrace库组件UI与js组件规范化123456789101112组件编码规范组件目录规范:组件目录与公用目录组件构建规范:构建环境支持组件模块化管理:spm,bowserify组件复用性管理第三方组件接入成本immutableJavaScriptgenerator与promise原理与使用构建生态grunt/gulp开发环境任务编写123456789101112文件处理插件:html、scss、js、image、font、其它优化插件:雪碧图、图片压缩、iconfont构建发布替换插件打包、压缩包插件:组件自动分析白名单配置自定义插件编写npm、jspm、bower包管理工具r.js、browserify、webpack、Rollup打包工具使用12345原理:根据依赖配置文件对文件进行依赖打包webpack支持更多的规范打包,AMD,Commonjswebpack+babel/reactjs+refluxfis3构建与插件开发、构建环境、fis3构建离线包webComponent:rosetta-org、x-view、Q、riot、novabrunch构建工具开发技巧与调试fiddler加willow基础组合调试12常见配置与分析结合浏览器调试werien、vorlonjs远程调试,chromeinspectmockjs,F.M.S(FrontMockServer)模拟调试使用与cgi自动调试macha/phantomjs/casperjs/karma测试自动化任务使用自动化UI测试,海豚node-supervior、node-inspector、karma开发发布系统流程sublime高效插件1emmet工具使用、sublimelinter、babelsnippets、sublimeLint、SassBeautify、emmet快速编辑、jsxlint、SideBarEnhancements、SnippetsMaker、SublimeCodeIntel、csssnippets、ColorPicker、html/css/jsPretty、SpinnetMacker、DocBlockr、MultiEditUtils、javascript&nodespinnet、JavaScript&NodeJSSnippets、jsLint、cssLint代码自动化检查fecshtml、css与重构jpeg、webp、apng、bpg图片123编码原理特点与优劣势适用场景iconfont使用与实现原理123自动打包构建方法iconfont兼容性写法fonthello、fontawesome、icomoon.io、iconfont.cn线上工具页面响应式设计123456layout布局响应式html结构响应式css样式响应式image媒体响应式javascript响应式mediaquery与平台判断css重置123resetnomalizeneatsass/compass/less/postcss常用语法与使用12345常用语法功能组件化UI设计管理构建工具实现方案雪碧图自动合成iconfont自动接入等等mediaquery与常见页面尺寸了解123媒体类型引入和媒体特性引入device-width适应retina屏幕适应em,rem原理与实现1234rem计算:width*retina/10,相当于屏幕宽度为10rem字体在rem情况下仍然使用pxcode4ui、code4app、初页、maka等1234前端dom操作即使刷新前端页面根据dom操作生成组件config配置保存到db根据config配置使用r.js或webpack打包发布打包后输出文件css3动画12345678910111213transformanimationtransiction3D加速与动画加速动画库缓动函数速查表:http://www.xuanfengge.com/easeing/easeing/Ceaser:http://xuanfengge.com/easeing/ceaser/cubic-bezier:http://cubic-bezier.com/css网格布局1234susyResponsiveGridSystemFluid960Grid(adaptjs)SimpleGrid搜索引擎与前端SEO123456789101112131415tdk优化页面内容优化唯一的H1标题img设置alt属性nofollowurl优化统一链接301跳转canonicalrobot优化robots.txtmetarobotssitemapSEO工具各种站长工具等浏览器缓存种类,resources,webSQL,indexDB,localstorage,cookie,appcache,cachestorage1store.js、cookie.jsUI框架123bootstrap、jqwidgets、semanticui、amazeui微信手Qui:frozenui、weui、blenduiextjs、echart图表uinative/hybrid/桌面开发ionic移动开发方案12345运行架构hybrid混合开发cordova交互离线包更新性能瓶颈nativescript移动开发方案reactNative移动开发方案123456运行架构:js引擎性能缺陷与内存泄露更新机制使用场景android/ios原生开发与框架1234567891011javaoc、swiftweb与native交互屏幕旋转摇一摇录像,拍照,选取本地图片打电话,发短信电池电量地理位置日期选择开启硬件加速桌面应用开发123456nodewebkitatom-shell(后改名为electron)网易Hexpomelo(游戏服务器框架)reactdesktopappjs:appjs.com前端/H5优化(另一个图已给出)yslow、pagespeed移动web性能优化1234567手机浏览器"省流量"原理增量更新原理及注意事项本地存储的应用加载优化图片优化单页面及路由实现业内著名站点案例分析全栈/全端开发express/nodeclub+mongodb、thinkjs等框架node.js直出实时web开发,meteor/express.ioMEAN(mongodb/express/angular/nodejs)http与http2协议、bigpipe、pipeline离线缓存,cookie、localstorage、indexdbcdn与dns12动态域名加速cdn原理与cdncombo研究实验WebAssembly、webTRC、typescriptMaterialdesign规范的前端框架1交互动效库AMP-HTML规范123使用受限HTML以及缓存技术来提高移动网络中静态内容的性能添加自定义的元素代替禁用掉的元素:amp-audio,amp-img、amp-video等数据分析与监控badjs数据上报1234567891011121314捕获错误两种方法:onerror、try-catch。抽样上报,先onerror统计语法错误,如果是scripterror,再使用tryjs。后台统计方法、不同业务接入体系、抽样统计onerror:可以捕捉语法错误和运行时错误;可以拿到出错的信息,堆栈,出错文件、行号、列号;当前页面执行的js脚本出错都会捕捉到;跨域的资源需要特殊头部支持。try-catch:无法捕捉语法错误,只能捕捉运行时错误;可以拿到出错的信息,堆栈,出错文件、行号、列号;需要借助工具把function块以及文件块加入try,catch,可以在这个阶段打入更多的静态信息。点击热力图clickHeat、heatMapjs加载失败优化方案123失败重发机制加载源域名服务器文件https反劫持百度alog数据上报其它软技能axure原型图设计xmind脑图管理效率管理caniuse、github知识管理/总结分享产品思维与技能前端技术网站技术社区12345w3ctech、w3cplus、w3helpdiv.io、nodeParty稀土掘金、前端早读课alloyteam、html5基地W3help行业会议12345segmentfault会议深js、杭jsGMIC(全球移动互联网大会)D2、webrebuildinfoQ内容、Qcon、velocity另外说明下,这里不仅仅是概念的罗列,过去也有些人有类似的总结,但是偏基础和概念罗列,没什么深度,这里有较多原理性的概述,博客有对应文章,较新热门的技术我的博客里也有很多,大家可以结合起来看,目前博客大概写了50%的总结文章。后面也会根据这个图去补齐我博客里的知识板块。持续更新中,如果觉得不错,请点star支持下,甚至在您的团队里扩散下,谢谢~]]></content>
<categories>
<category>Interview</category>
</categories>
<tags>
<tag>Interview</tag>
</tags>
</entry>
<entry>
<title><![CDATA[原生JavaScript探索]]></title>
<url>%2F2016%2F01%2F15%2FNativeJS%2F</url>
<content type="text"><![CDATA[** 自用笔记:**本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyTitle炫舞为了实现Title的动态变化,使用document.title修改Title的内容。方案一:Demo123456789101112<!-- 用户浏览其他页面 --><script type="text/javascript"> // window 失去焦点,停止输出 var Title = document.title window.onblur=function(){ document.title="对面的女孩看过来"; } // window 每次获得焦点 window.onfocus = function() { document.title=Title; }</script>变态的标题方案二:12345<script type="text/javascript"> document.addEventListener('visibilitychange', function() { document.title = document.hidden ? '出BUG了,快看!':'小剧客栈,剧中人的个人博客!' });</script>方案三:1234567891011<script type="text/javascript"> document.addEventListener("keydown", function(a) { a = a || window.event; var b = parseInt(a.keyCode); !a.ctrlKey || 115 !== b && 83 !== b ? (123 === b || a.ctrlKey && a.shiftKey && 73 === b || a.ctrlKey && 85 === b) && (a.returnValue = !1, a.preventDefault(), p()) : (a.returnValue = !1, a.preventDefault(), p()) }), document.addEventListener("contextmenu", function(a) { a = a || window.event, a.returnValue = !1, a.preventDefault() }, !1), document.addEventListener("visibilitychange", function() { document.title = document.hidden ? "看这里,看这里!" : "世平阜康的博客" })</script>1234567<script type="text/javascript"> var r = "记得回来点单哦! - 饿了么", n = document.title; angular.$(document).on("visibilitychange",function(){ document.title = "hidden"===document.visibilityState ? r : n })</script>禁用右键Demo123456<script type="text/javascript"> // 禁用右键 document.oncontextmenu = function (){ return (false); }</script>禁用F12禁用F12123456789<script type="text/javascript"> // 禁用F12 document.onkeydown = document.onkeyup = document.onkeypress = function() { if (window.event.keyCode == 123) { window.event.returnValue = false; return (false); } }</script>使用F12,弹出提示,关闭网页Demo123456789101112131415<script type="text/javascript"> // 禁用F12 document.onkeydown = document.onkeyup = document.onkeypress = function() { if (window.event.keyCode == 123) { document.getElementById("Popup").innerHTML="<div><a href=#>这个真的没什么好看的,还是看内容吧!</a></div>"; // 关闭窗口 setTimeout(b, 2000); function b() { window.close(); } window.event.returnValue = false; return (false); } }</script>自定义复制内容修改用户复制文档的内容,添加版权申明等信息。计时器Js 时间间隔计算(间隔天数)1234567function GetDateDiff(startDate,endDate) { var startTime = new Date(Date.parse(startDate.replace(/-/g, "/"))).getTime(); var endTime = new Date(Date.parse(endDate.replace(/-/g, "/"))).getTime(); var dates = Math.abs((startTime - endTime))/(1000*60*60*24); return dates; }计算网站运行的具体时间错误理解:没有计算12月份的,好吧,是我理解错误,就好像周期一样,没有7,0就是星期天。12345678910111213141516171819202122理解下时间的规则:document.write(new Date + "<br />");Fri Jan 15 2016 14:42:36 GMT+0800 (中国标准时间)document.write(new Date(2016, 0, 12, 10, 0, 0) + "<br />");Tue Jan 12 2016 10:00:00 GMT+0800 (中国标准时间)设置几月的时候要减1,0代表一月。document.write(Math.floor(((new Date).getTime() - new Date(2015, 10, 25, 10, 0, 0).getTime()) / 864e5) + "<br />")51年数c = b % 31104e6,月数d = c % 2592e6,天数e = d % 864e5,时间f = e % 36e5;Demo123456789101112function b() { var b = (new Date).getTime() - new Date(2015, 10, 25, 10, 0, 0).getTime(), c = b % 31104e6, d = c % 2592e6, e = d % 864e5, f = e % 36e5; i = [Math.floor(b / 31104e6), Math.floor(c / 2592e6), Math.floor(d / 864e5), Math.floor(e / 36e5), Math.floor(f / 6e4), Math.floor(f % 6e4 / 1e3)], h.each(function(b, c) { a(c).css({ backgroundPosition: "0 " + (-44 * i[b] + "px") }) })}调用微博123456789function() { // 调用微博 var oDiv = document.createElement("div"); oDiv.style.width = "384px"; oDiv.style.textAlign = "right"; oDiv.style.margin = "5px auto 10px"; oDiv.innerHTML = "<iframe width=\"117\" height=\"24\" frameborder=\"0\" allowtransparency=\"true\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\" border=\"0\" src=\"http://widget.weibo.com/relationship/followbutton.php?language=zh_cn&width=136&height=24&uid=1844880617&style=2&btn=red&dpc=1\"></iframe>"; document.body.appendChild(oDiv) }JS数据归类提取]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[HTML结构零散]]></title>
<url>%2F2016%2F01%2F13%2FHTMLbase%2F</url>
<content type="text"><![CDATA[HTML结构零散:头部分的标签、元素有很多,涉及到浏览器对网页的渲染,SEO 等等,而各个浏览器内核以及各个国内浏览器厂商都有些自己的标签元素,这就造成了很多差异性。移动互联网时代,head 头部结构,移动端的 meta 元素,显得更为重要。了解每个标签的意义,写出满足自己需求的 head 头标签,是本文的目的。本篇以一丝的文章为基础,进行扩展总结介绍常用的 head 中各个标签、元素的意义以及使用场景。版权声明DOCTYPE(Document Type),该声明位于文档中最前面的位置,处于 html 标签之前,此标签告知浏览器文档使用哪种 HTML 或者 XHTML 规范。DTD(Document Type Definition) 声明以 <!DOCTYPE> 开始,不区分大小写,前面没有任何内容,如果有其他内容(空格除外)会使浏览器在 IE 下开启怪异模式(quirks mode)渲染网页。公共 DTD,名称格式为注册//组织//类型 标签//语言,注册指组织是否由国际标准化组织(ISO)注册,+表示是,-表示不是。组织即组织名称,如:W3C。类型一般是 DTD。标签是指定公开文本描述,即对所引用的公开文本的唯一描述性名称,后面可附带版本号。最后语言是 DTD 语言的 ISO 639 语言标识符,如:EN 表示英文,ZH 表示中文。XHTML 1.0 可声明三种 DTD 类型。分别表示严格版本,过渡版本,以及基于框架的 HTML 文档。XHTML12<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" >HTML12345678<!-- HTML 4.01 strict --><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><!-- HTML 4.01 Transitional --><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><!-- HTML 4.01 Frameset --><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">HTML 5123<!-- HTML 5 --><!DOCTYPE html><html>123<!-- HTML 5 --><!DOCTYPE html><html lang='en' xmlns='http://www.w3.org/1999/xhtml'>HTML5兼容1234567891011121314引用Google的html5.js文件<!--[if IE]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->将上代码复制到head部分,记住一定要是head部分(因为IE必须在元素解析前知道这个元素,所以这个js文件不能在其他位置调用,否则失效)最后在css里面加上这段:/*html5*/article,aside,dialog,footer,header,section,footer,nav,figure,menu{display:block}主要是让这些html5标签成块状,像div那样。语言12345678<!-- 英文 --><html lang='en'><!-- 简体中文 --><html lang="zh-cmn-Hans"><!-- 繁体中文 --><html lang="zh-cmn-Hant">[网页头部语言](http://www.zhihu.com/question/20797118 “网页头部的声明应该是用 lang=”zh” 还是 lang=”zh-cn”?”)HTMLHEAD标题SEO12<!-- 标题 --><title>HTML Base</title>base默认地址123456<base> 标签为页面上的所有链接规定默认地址或默认目标。使用 <base> 标签可以改变这一点。浏览器随后将不再使用当前文档的 URL,而使用指定的基本 URL 来解析所有的相对 URL。这其中包括 <a>、<img>、<link>、<form> 标签中的 URL。在 HTML 中,<base> 标签没有结束标签;在 XHTML 中,<base> 标签必须被正确地关闭。但是还是建议要闭合标签,这样不同浏览器兼容不容。12345678910111213141516该标签将会控制所有链接,围棋添加默认的链接。默认的链接<base href="http://www.w3school.com.cn/i/" />默认的链接打开方式<base target="_blank" />注意:通常通常情况下,默认链接会自动添加到链接的前面。但是,也有特例:<base href="http://www.w3school.com.cn/i/" /><link rel="stylesheet" href="css/root.css"/>http://www.w3school.com.cn/i/css/root.css但是,如果添加根目录(绝对路径),链接会自动根据默认链接进行根目录的查询指定。<base href="http://www.w3school.com.cn/i/" /><link rel="stylesheet" href="/css/root.css"/>http://www.w3school.com.cn/css/root.cssmeta编码格式1234<!-- 编码格式 --><meta charset="utf-8"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta http-equiv="Content-Type" content="text/html; charset=gb2312" />编码格式123456789101112131415<meta http-equiv="X-UA-Compatible" content="IE=7"> <!-- 指定网页的兼容性模式设置 --><meta http-equiv="X-UA-Compatible" content="IE=8"> <!-- 以上代码告诉IE浏览器,无论是否用DTD声明文档标准,IE8/9都会以IE7引擎来渲染页面。 --><meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- 以上代码告诉IE浏览器,IE8/9都会以IE8引擎来渲染页面。 --><meta http-equiv="X-UA-Compatible" content="IE=7,IE=9"> <!-- 以上代码告诉IE浏览器,IE8/9及以后的版本都会以最高版本IE来渲染页面。 --><meta http-equiv="X-UA-Compatible" content="IE=7,9"> <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"><!-- 以上代码IE=edge告诉IE使用最新的引擎渲染网页,chrome=1则可以激活Chrome Frame. -->渲染页面1234567<meta name="renderer" content="webkit"><!-- 默认webkit内核 --><!-- 360 使用Google Chrome Frame --><meta name="renderer" content="ie-comp"><!-- 默认IE兼容模式 --><meta name="renderer" content="ie-stand"><!-- 默认IE标准模式 -->页面关键词SEO12<!-- 关键词 --><meta name="keywords" content="" />页面描述SEO1234每个网页都应有一个不超过 150 个字符且能准确反映网页内容的描述标签。<!-- 描述 --><meta name="description" content="" />1234<meta name="author" content="作者"> <meta name="build" content="日期"> <meta name="coprright" content="版权"> <meta name="reply-to" content="email">搜索引擎索引方式123456789101112Robots用来告诉搜索机器人哪些页面需要索引,哪些页面不需要索引。Content的参数有all、none、index、noindex、follow、nofollow。默认是all。<meta name="robots" content="index,follow" /><!--all:文件将被检索,且页面上的链接可以被查询;none:文件将不被检索,且页面上的链接不可以被查询;index:文件将被检索;follow:页面上的链接可以被查询;noindex:文件将不被检索;nofollow:页面上的链接不可以被查询。-->页面重定向和刷新1234content内的数字代表时间(秒),既多少时间后刷新。如果加url,则会重定向到指定网页(搜索引擎能够自动检测,也很容易被引擎视作误导而受到惩罚)。<meta http-equiv="refresh" content="5;url=http://luuman.github.io/" />页面期限123可以用于设定网页的到期时间。一旦网页过期,必须到服务器上重新传输,必须使用GMT的时间格式。<meta http-equiv="expires" Content="Wed, 26 Feb 1997 08:21:57 GMT">页面Cookie设定123如果网页过期,那么存盘的cookie将被删除。<meta http-equiv="Set-Cookie" content="cookievalue=xxx; expires=Friday, 12-Jan-2001 18:18:18 GMT; path=/">页面Cache模式123禁止浏览器从本地计算机的缓存中访问页面内容。<meta http-equiv="Pragma" content="no-cache">显示窗口的设定123强制页面在当前窗口以独立页面显示,用来防止别人在框架里调用自己的页面。<meta http-equiv="Window-target" content="_top">可视区域(移动端)12345678910111213<!-- 可视区域 --><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">width - viewport的宽度 height - viewport的高度 initial-scale - 初始的缩放比例 minimum-scale - 允许用户缩放到的最小比例 maximum-scale - 允许用户缩放到的最大比例 user-scalable - 用户是否可以手动缩放minimal-ui iOS 7.1 beta 2 中新增属性,可以在页面加载时最小化上下状态栏。这是一个布尔值,可以直接这样写:<meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">禁止了把数字转化为拨号链接12<!-- 禁止了把数字转化为拨号链接 --><meta name="format-detection" content="telephone=no" />忽略识别邮箱12<!-- 禁止了识别邮箱 --><meta name="format-detection" content="email=no" />关键词12<!-- 删除默认的苹果工具栏和菜单栏 --><meta name="apple-mobile-web-app-capable" content="yes" />关键词12345678<!-- 控制状态栏显示样式 --><meta name="apple-mobile-web-app-status-bar-style" content="default" /><meta name="apple-mobile-web-app-status-bar-style" content="black" /><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />默认:default(白色)black(黑色)black-translucent(灰色半透明)Iphone的Safari浏览器123<!-- iphone的safari浏览器 --><meta name="apple-itunes-app" content="app-id=432274380" /><!-- <meta name="znonce" content="74810a1113ff4cf49d97f2616bdfe158"> -->添加Meta声明123<!-- 用于添加Meta声明;无对应关系的PC页面无需添加Meta --><meta http-equiv="mobile-agent" content="format=[wml|xhtml|html5]; url=url"><meta http-equiv="mobile-agent" content="format=html5;url=http://www.z.com/">网站所有者12<!-- 验证网站所有者的一种方式 --><meta property="wb:webmaster" content="8e9c4b702508b902" />其他1234567891011121314151617181920212223242526<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 --> <meta name="HandheldFriendly" content="true"> <!-- 微软的老式浏览器 --> <meta name="MobileOptimized" content="320"> <!-- uc强制竖屏 --> <meta name="screen-orientation" content="portrait"> <!-- QQ强制竖屏 --> <meta name="x5-orientation" content="portrait"> <!-- UC强制全屏 --> <meta name="full-screen" content="yes"> <!-- QQ强制全屏 --> <meta name="x5-fullscreen" content="true"> <!-- UC应用模式 --> <meta name="browsermode" content="application"> <!-- QQ应用模式 --> <meta name="x5-page-mode" content="app"> <!-- windows phone 点击无高光 --> <meta name="msapplication-tap-highlight" content="no">社交分享(富媒体对象)12345678网页内容可以被其他社会化网站引用等,目前这种协议被SNS网站如Fackbook、renren采用。<meta property="og:type" content="article"><meta property="og:title" content="HTML结构零散"><meta property="og:url" content="http://yoursite.com/2016/01/13/HTMLbase/index.html"><meta property="og:site_name" content="Luuman's Blog"><meta property="og:description" content="自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why 最近,使用Hexo遇到了很多问题,在设立进行整理。"><meta property="og:updated_time" content="2016-01-20T16:59:08.000Z">123456789101112131415161718192021222324252627282930313233343536-----------Base Element基本类型-----------1、og:type 网页资源类型标识content enum: ● video 视频● audio 音频● link 链接● photo 图片● product 产品2、og:title 标题描述3、og:image 缩略图4、og:url 当前内容链接5、rr:appid 如果您的网站是CONNECT到renren.com的,请提供该ID 6、rr:appid 如果您的网站是CONNECT到renren.com的,请提供该ID 7、og:width 视频的宽度8、og:height 视频的高度-----------Audio Element 音频------------1、og:audiosrc 音乐资源链接,例如可是播放歌曲的flash地址2、og:artist 音乐家-----------Commen Page Element 普通网页------------1、og:abstract 内容摘要2、og:contentid 内容主体的ID,用来标识当前页面主要内容所处的HTML标签的ID -----------Graphic Element 图片------------1、og:photo 图片列表2、og:width 图片宽度3、og:height 图片高度-----------Product Element 商品-----------1、og:price 产品价格2、og:description 产品描述3、og:nick 店铺名4、og:postfee 运费12<meta property="fb:admins" content="100001422224225"><meta property="fb:page_id" content="241333394220">访问时以兼容模式访问123456789101112131415国内浏览器很多都是双内核(webkit和Trident),webkit内核高速浏览,IE内核兼容网页和旧版网站。而添加meta标签的网站可以控制浏览器选择何种内核渲染。<!-- 访问时以兼容模式访问 --><!-- 默认webkit内核 --><meta name="renderer" content="webkit"><!-- 默认IE兼容模式 --><meta name="renderer" content="ie-comp"><!-- 默认IE标准模式 --><meta name="renderer" content="ie-stand">国内双核浏览器默认内核模式如下:1. 搜狗高速浏览器、QQ浏览器:IE内核(兼容模式)2. 360极速浏览器、遨游浏览器:Webkit内核(极速模式)创建一个推特卡123456<meta name="twitter:card" content="summary" /><meta name="twitter:url" content="http://www.peerflyoffers.com/offer.php?id=7351" /><meta name="twitter:title" content="Tara Astrology - US" /><br /><meta name="twitter:description" content="Payout: $1.30 - CR: 28.91% - EPC: $0.38 - Get your free reading! Target demo is women 25+. Converts on first page." /><meta name="twitter:image" content="http://s.wordpress.com/mshots/v1/http%3A%2F%2Fpeerfly.com%2Fpreview.php%3Foffer%3D7351?w=400&amp;height=400" /><meta name="twitter:site" content="@peerflyoffers" /><meta name="twitter:creator" content="@LukePeerFly" />Windows 812345<!-- Windows 8 磁贴颜色 --><meta name="msapplication-TileColor" content="#000"/><!-- Windows 8 磁贴图标 --> <meta name="msapplication-TileImage" content="icon.png"/>手机页URL1234<meta name="mobile-agent" content="format=[wml|xhtml|html5]; url=url"><!--[wml|xhtml|html5]根据手机页的协议语言,选择其中一种;url="url" 后者代表当前PC页所对应的手机页URL,两者必须是一一对应关系。-->百度123用百度打开网页可能会对其进行转码(比如贴广告)<meta http-equiv="Cache-Control" content="no-siteapp" />引入linkIcon link12345678910111213141516<!-- Icon link --><link rel="shortcut icon" href="favicon.ico"><!-- 添加到主屏上的图标会使用指定的图片 --><link rel="apple-touch-icon" href="templets/default/images/ico/apple-touch-icon.png"><!-- ipad --><link rel="apple-touch-icon" sizes="72x72" href="templets/default/images/ico/apple-touch-icon-72.png"><!-- iPhone、iTouch --><link rel="apple-touch-icon" sizes="114x114" href="templets/default/images/ico/apple-touch-icon-114.png"><!-- precomposed --><link rel="apple-touch-icon-precomposed" href="static/img/ios/zhihu(57px).png" /><link rel="apple-touch-icon-precomposed" sizes="72x72" href="templets/default/images/ico/apple-touch-icon-72.png"><link rel="apple-touch-icon-precomposed" sizes="114x114" href="templets/default/images/ico/apple-touch-icon-114.png">section12<!-- 把搜索功能放到浏览器的快捷搜索工具上 --><link rel="search" type="application/opensearchdescription+xml" href="static/search.xml" title="知乎" />section1<link rel="stylesheet" href=".css">添加 RSS 订阅12<!-- 添加 RSS 订阅 --><link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />引入JavaScript12<!-- JavaScript --><script type="text/javascript"></script>引入style移动端123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293<!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --><html lang="zh-cmn-Hans"> <!-- 更加标准的 lang 属性写法 http://zhi.hu/XyIa --><head> <!-- 声明文档使用的字符编码 --> <meta charset='utf-8'> <!-- 优先使用 IE 最新版本和 Chrome --> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> <!-- 页面描述 --> <meta name="description" content="不超过150个字符"/> <!-- 页面关键词 --> <meta name="keywords" content=""/> <!-- 网页作者 --> <meta name="author" content="name, [email protected]"/> <!-- 搜索引擎抓取 --> <meta name="robots" content="index,follow"/> <!-- 为移动设备添加 viewport --> <meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"> <!-- `width=device-width` 会导致 iPhone 5 添加到主屏后以 WebApp 全屏模式打开页面时出现黑边 http://bigc.at/ios-webapp-viewport-meta.orz --> <!-- iOS 设备 begin --> <meta name="apple-mobile-web-app-title" content="标题"> <!-- 添加到主屏后的标题(iOS 6 新增) --> <meta name="apple-mobile-web-app-capable" content="yes"/> <!-- 是否启用 WebApp 全屏模式,删除苹果默认的工具栏和菜单栏 --> <meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL"> <!-- 添加智能 App 广告条 Smart App Banner(iOS 6+ Safari) --> <meta name="apple-mobile-web-app-status-bar-style" content="black"/> <!-- 设置苹果工具栏颜色 --> <meta name="format-detection" content="telphone=no, email=no"/> <!-- 忽略页面中的数字识别为电话,忽略email识别 --> <!-- 启用360浏览器的极速模式(webkit) --> <meta name="renderer" content="webkit"> <!-- 避免IE使用兼容模式 --> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 --> <meta name="HandheldFriendly" content="true"> <!-- 微软的老式浏览器 --> <meta name="MobileOptimized" content="320"> <!-- uc强制竖屏 --> <meta name="screen-orientation" content="portrait"> <!-- QQ强制竖屏 --> <meta name="x5-orientation" content="portrait"> <!-- UC强制全屏 --> <meta name="full-screen" content="yes"> <!-- QQ强制全屏 --> <meta name="x5-fullscreen" content="true"> <!-- UC应用模式 --> <meta name="browsermode" content="application"> <!-- QQ应用模式 --> <meta name="x5-page-mode" content="app"> <!-- windows phone 点击无高光 --> <meta name="msapplication-tap-highlight" content="no"> <!-- iOS 图标 begin --> <link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png"/> <!-- iPhone 和 iTouch,默认 57x57 像素,必须有 --> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="/apple-touch-icon-114x114-precomposed.png"/> <!-- Retina iPhone 和 Retina iTouch,114x114 像素,可以没有,但推荐有 --> <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/apple-touch-icon-144x144-precomposed.png"/> <!-- Retina iPad,144x144 像素,可以没有,但推荐有 --> <!-- iOS 图标 end --> <!-- iOS 启动画面 begin --> <link rel="apple-touch-startup-image" sizes="768x1004" href="/splash-screen-768x1004.png"/> <!-- iPad 竖屏 768 x 1004(标准分辨率) --> <link rel="apple-touch-startup-image" sizes="1536x2008" href="/splash-screen-1536x2008.png"/> <!-- iPad 竖屏 1536x2008(Retina) --> <link rel="apple-touch-startup-image" sizes="1024x748" href="/Default-Portrait-1024x748.png"/> <!-- iPad 横屏 1024x748(标准分辨率) --> <link rel="apple-touch-startup-image" sizes="2048x1496" href="/splash-screen-2048x1496.png"/> <!-- iPad 横屏 2048x1496(Retina) --> <link rel="apple-touch-startup-image" href="/splash-screen-320x480.png"/> <!-- iPhone/iPod Touch 竖屏 320x480 (标准分辨率) --> <link rel="apple-touch-startup-image" sizes="640x960" href="/splash-screen-640x960.png"/> <!-- iPhone/iPod Touch 竖屏 640x960 (Retina) --> <link rel="apple-touch-startup-image" sizes="640x1136" href="/splash-screen-640x1136.png"/> <!-- iPhone 5/iPod Touch 5 竖屏 640x1136 (Retina) --> <!-- iOS 启动画面 end --> <!-- iOS 设备 end --> <meta name="msapplication-TileColor" content="#000"/> <!-- Windows 8 磁贴颜色 --> <meta name="msapplication-TileImage" content="icon.png"/> <!-- Windows 8 磁贴图标 --> <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml"/> <!-- 添加 RSS 订阅 --> <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> <!-- 添加 favicon icon --> <title>标题</title></head>12<style></style>hack IE用于解决IE兼容性问题的特殊方案,只有满足条件,才会执行代码,否则视为注释。1234<!-- hack IE --><!--[if lt IE 9]><script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script><![endif]-->1</head>Body1<body>audio声音事件美团外卖商家中心1234567891011<audio id="main_audio" preload="auto" volume="1.0" loopdata-type="waimai"><source src="meituan://waimai.ogg" type="audio/ogg"/><source src="static/media/waimai.ogg" type="audio/ogg"/></audio><!-- 加入refundloop的判断 --><audio id="refund-audio" preload="auto" volume="1.0" data-type="one"><source src="meituan://refund.ogg" type="audio/ogg"/><source src="static/media/refund.ogg" type="audio/ogg"/></audio>]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>HTML</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo bug 整理机]]></title>
<url>%2F2015%2F12%2F27%2FHexoBug%2F</url>
<content type="text"><![CDATA[** 自用笔记:**本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why最近,使用Hexo遇到了很多问题,在设立进行整理。首页文章摘要hexo生成JSON内容hexo-generator-searchWiki聚沙成塔,记录碎片化信息,构筑个人知识体系圆圈导航JS出现问题有时候不出现多说表情溢出移动端,多说表情溢出,将页面撑开。标签显示数量移动端,标签显示数目有限,PC端也有这样的问题。Instagram图片显示移动端图片显示效果有待修改,应该不可以滑动,全屏填充。1-3 想办法添加作品介绍页面界面不够完美,有待于修改![W]IE 低版本浏览器不支持1234567891011121314<!--[if lt IE 10]><script>window.location.href="http://luuman.github.io/Works/PC/IE/";</script><![endif]--><!-- Google Analytics --><script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','js/eed8ec65a6dd9b05eed6d4a02e1439e4.js','ga'); ga('create', 'UA-65952334-1', 'auto'); ga('send', 'pageview');</script>2016 年1-28 TitleTip描述信息显示[W] 对A标签的title属性进行设置,将文本内容去除,使用div进行集中显示。[W] J:\Hexo\Hexo\themes\spfk\source\css_partial\tagcloud.styl1-7 首页添加loading效果[W] loading效果[W] Hexo\themes\landscape\source\css_partial\highlight.styl1-5 语法高亮样式修改[W] code highlight 代码高亮[W] Hexo\themes\landscape\source\css_partial\highlight.styl1-3 想办法添加作品介绍页面根据[Hexo][ ]官网的主题介绍,添加标签、名称、图片、介绍放置自己的作品。最终还是把这个页面弄出来了,但是还有很多地方需要修改,因为是响应式的页面,还有很多地方要优化。还有window.serch.index没有解决。[W] 为Hexo博客添加作品介绍页面[W] 为Hexo site[W][W]添加目录1-2 添加目录[W]Hexo博客系统 Hexo博客系统的核心支持生成目录(Table of Contents),但其默认的主题Landscape并不支持目录的显示。[W] 为Hexo博客添加目录[W] 为Hexo博客添加目录2015 年12-31 社交账号图标修改去除图片,将图标更换成字体文件,通过查看,得知系统通过自己设定的社交账号链接,进行自动生成\themes\spfk\layout_partial\left-col.ejs[W] 社交账号图标修改结果发现还有很多图标,fontawesome-webfont没有,了解图标的逻辑。12-31 百度分享图片修改由于博客已经建站,字体包,将class的名称就改了,改变分享效果[W] 百度分享美化12-30 添加版权声明参照M的版权声明,进行修改![W] 添加版权声明,修改样式12-29 侧边栏侧边栏图片背景的设置,要和?再次看了感觉还好,就不改了。12-28 instagram图片拉取添加instagram图片,展示自己的摄影爱好。[W] instagram总结[W] instagram图片拉取小经验[W] 管理客户端页面[W] Lookup Your Instagram User ID12-27 多说样式修改多说样式,被顶起的页面显示效果,还是不太好。具体样式请参照:多说.css]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo的使用介绍]]></title>
<url>%2F2015%2F12%2F27%2FHexo%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why最近,使用Hexo遇到了很多问题,在设立进行整理。写文章1234567891011121314151617181920212223242526272829$ hexo n #写文章 其中my new post为文章标题,执行命令后。 会在项目\source_posts中生成my new post.md文件,用编辑器打开编写即可。 当然,也可以直接在\source_posts中新建一个md文件,我就是这么做的。 文章开头语法:title: name #文章标题date: 2015-12-25 18:29:00 #写作时间description: #文章描述categories: #文章分类- 建站tags: #文章标签- 博客- 建站- Hexotoc: true # 生成目录author:comments:original:permalink: #指定链接--- 以上是摘要<!--more--> 以下是余下全文写多种文章1234567891011121314151617181920212223242526$ hexo new [layout] "postName" #新建文章 [layout]:其中layout是可选参数,默认值为post。 有哪些layout呢,请到 scaffolds 目录下查看,这些文件名称就是layout名称。 当然你可以添加自己的layout,方法就是添加一个文件即可。 同时你也可以编辑现有的layout,比如post的layout默认是 hexo\scaffolds\post.md 关于hexo\scaffolds\photo.md配置文件的介绍:layout: { { layout } } #layout名称title: { { title } } #文章标题date: { { date } } #文章生成时间ategories: #文章分类目录tags: #文章标签- #photos: #- #---layout: phototitle: 我的阅历date: 2085-01-16 07:33:44tags: [hexo]photos:- http://bruce.u.qiniudn.com/2013/11/27/reading/photos-0.jpg- http://bruce.u.qiniudn.com/2013/11/27/reading/photos-1.jpg自定义页面12345678910111213 执行new page命令$ hexo new page "about" 在 *hexo\source\* 下会生成 *about* 目录, 里面有个index.md,直接编辑就可以了, 然后在主题的 *_config.yml* 中将其配置显示出来。 上述步骤,也可以手工生成,在 *hexo\source\* 下手工新建 *about* 和 *index.md* 也是完全等价的。 因为markdown对table的支持不好,我是在about中直接 建立index.html,里面书写页面内容,hexo会帮你加上头和尾。写页面(404)12345$ hexo new page "404"UUhike@UUhike-pc MINGW64 /d/Hexo/Hexo (master)$ hexo new page "404"INFO Created: D:\Hexo\Hexo\source\404\index-1.md1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071title: 404 Not Found:该页无法显示comments: falsepermalink: /404fancybox: false---<style type="text/css"> .article-title { font-size: 2.1em; } strong a { color: #747474; } .share { display: none; } .player { margin-left: -10px; } .sign { text-align: right; font-style: italic; } #page-visit { display: none; } .center { text-align: center; height: 2.5em; font-weight: bold; } .search2 { height: 2.2em; font-size: 1em; width: 50%; margin: auto 24%; color: #727272; opacity: .6; border: 2px solid lightgray; } .search2:hover { opacity: 1; box-shadow: 0 0 10px rgba(0, 0, 0, 0.3) }; .article-entry hr { margin: 0; } .pic { text-align: center; margin: 0; } .pic br { display: none; }</style>***<div class="pic"><img src="/resources/Mihawk-Wind.gif" title="Mihawk-Wind"></div><p class="center">很抱歉,您所访问的地址并不存在: </p><p class="center"><a href="/">回主页</a> · <a href="/archives">所有文章</a> · <a href="/about">留言板</a></p><p class="center">可在边栏搜索框中对本站进行检索,以获取相关信息。</p><div style="text-align: center">以下是博主喜欢的一些歌曲,可以听听,稍作休息~<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=320 height=330 src="http://music.163.com/outchain/player?type=0&id=112513213&auto=0&height=430"></iframe></div>发布博客内容实现发布,前提是配置好,部署到Github前需要配置_config.yml文件。123456# Deployment## Docs: http://hexo.io/docs/deployment.htmldeploy: type: github repository: [email protected]:zhchnchn/zhchnchn.github.io.git branch: master更新的最新版本,可能会有Bug,自行百度,好像要修改type:git。12345678910$ hexo server #开启预览访问端口(默认端口4000,'ctrl + c'关闭server)Hexo 会监视文件变动并自动更新,您无须重启服务器。$ hexo g #生成$ hexo generate #生成静态页面至public目录(最终上传这个文件到GitHub)$ hexo d == hexo deploy#部署$ hexo d #部署 # 可与hexo g合并为 hexo d -g$ hexo deploy -g$ hexo server -g # 生成默认文件群再执行,开启本地静态html服务器主题的更改123456789101112131415161718191. 将Git Shell 切到/D/Hexo目录下,然后执行下面的命令,将pacman下载到 themes/pacman 目录下。$ git clone https://github.com/A-limon/pacman.git themes/pacman2. 修改你的博客根目录/D/Hexo下的config.yml配置文件中的theme属性,将其设置为pacman。3. 更新pacman主题$ cd themes/pacman$ git pullNOTE:先备份_config.yml 文件后再升级主题: yilia$ git clone https://github.com/litten/hexo-theme-yilia.git themes/yilia modernist$ git clone https://github.com/heroicyang/hexo-theme-modernist.git themes/modernist jacman$ git clone https://github.com/cnfeat/cnfeat.git themes/jacman文章图片路径Hexo如何方式图片,图片应该放置到哪里,不会应为上传而覆盖掉。然后把文章里的index.md删除,将文件存放在resource文件夹中间。123456 发布页面$ hexo new page "name" # 新建一个页面,页面名称name UUhike@UUhike-pc MINGW64 /d/Hexo/Hexo (master)$ hexo new page "resoures" INFO Created: D:\Hexo\Hexo\source\resoures\index.mdHexo文件备份1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 git-backup. Install if your hexo version is 2.x.x, you should install as follow:$ npm install [email protected] --save if version is 3.x.x, you should install as follow:$ npm install hexo-git-backup --save Update if you install with --save, you must remove firstly when you update it.$ npm remove hexo-git-backup$ npm install hexo-git-backup --save Configure You should configure this plugin in _config.yml.backup: type: git repository: github: [email protected]:xxx/xxx.git,branchName gitcafe: [email protected]:xxx/xxx.git,branchNameUsinghexo backup orhexo bOptionsif you want to back up with your theme,just add theme: your theme name,your theme name in _config.yml.backup: type: git theme: coney,landscape,xxx repository: github: [email protected]:xxx/xxx.git,branchName gitcafe: [email protected]:xxx/xxx.git,branchNameAttention: if you do as above, the dir themes/coney/.gitwill be removedif you want DIY commit message, just add 'message: update xxx'.backup: type: git message: update xxx repository: github: [email protected]:xxx/xxx.git,branchName gitcafe: [email protected]:xxx/xxx.git,branchNameNow you can backup all the blog!ProblemsYou may get some troubles by your computer' permission。Error: EISDIR, openit is caused by permission. just do 'sudo hexo b'sudo hexo b本地浏览12hexo shexo s --draf 浏览全部文章同时可以浏览不同目录中的文件参考资料:使用GitHub搭建Hexo博客Hexo插件安装hexo你的博客如何搭建一个独立博客——简明Github Pages与Hexo教程]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo 主题:SPFK]]></title>
<url>%2F2015%2F12%2F27%2FHexoTheme%2F</url>
<content type="text"><![CDATA[** Hexo 主题:**用了yilia主题一段时间,感觉还有很多可以提高的地方,就查阅资料,对其进行粗类的修改,但是,有其实还有很多不完善的地方,欢迎大家前捧场。没想到,这么多人喜欢黑色版本的,建议不是每个人都喜欢我的这些功能,所以准备个基础版本,插件可以看教程自行安装。使用安装1$ git clone https://github.com/luuman/hexo-theme-spfk.git themes/spfk配置修改hexo根目录下的 _config.yml : theme: spfk更新12cd themes/spfkgit pull配置关于配置文件,主题配置文件在主目录下的_config.yml:_config.yml相关插件的安装:请参照Hexo插件安装12345678910111213141516171819202122### HeaderJ:\Hexo\Hexo\themes\spfk\_config.ymlmenu: 主页: / 所有文章: /archives # 随笔: /tags/随笔 #是否开启多说评论,填写你在多说申请的项目名称 duoshuo: duoshuo-key(http://duoshuo-key.duoshuo.com/) #若使用disqus,请在博客config文件中填写disqus_shortname,并关闭多说评论 duoshuo: true网页侧边栏背景:# Background | 背景## "background_sum": show images form /source/background/的图片数目background_sum: 24## "on: true": 自动随机显示这5张图片## "on: false": 自定义显示图片设置,background_image: 109background: on: true #on: false background_sum: 24 background_image: 109多说评论12345678duoshuo: on: true domain: luuman # 是否开启多说评论,http://duoshuo.com/create-site/ # 使用上面网址登陆你的多说,然后创建站点,在 domain 中填入你设定的域名前半部分 # http://<要填的部分>.duoshuo.com (domain只填上<>里的内容,不要填整个网址)J:\Hexo\Hexo\themes\spfk\source\css\多说.css添加方法:添加方法:打开「后台」 > 「多说评论」 > 「设置」 > 「基本设置」 > 然后把样式粘贴到「自定义CSS」文本框 > 「保存」具体样式请参照:多说.css头像12头像尺寸大概200*200pxE:\Github\Hexo\themes\spfk\source\img\head.jpgApple Touch icon 苹果图标:123替换路径: /spfk/source/apple-touch-icon.pngE:\Github\Hexo\themes\spfk\source\img\favicon.png背景123456789# Background | 背景## "background_sum": show images form /source/background/的图片数目## "on: true": 自动随机显示这5张图片## "on: false": 自定义显示图片设置 background_image: 5background: on: true #on: false background_sum: 24 background_image: 109文章摘要12345678910111213141516171819title: 前端知识体系date: 2016-01-16 13:58:41description: categories:- HTML 书籍- HTML 书籍tags:- HTML 标签 - HTML 标签toc: true 文章目录author:comments:original:permalink: --- ** 前端知识体系:**<Excerpt in index | 首页摘要> + <!-- more --><The rest of contents | 余下全文>404 Page:123hexo new page 404And then set permalink: /404 in /source/404/index.md front matter.在 Hexo 中创建匹配主题的404页面404.htmlabout.html主题结构:123456789101112131415161718.├── languages #多语言| ├── default.yml #默认语言| └── zh-CN.yml #中文语言├── layout #布局,根目录下的*.ejs文件是对主页,分页,存档等的控制| ├── _partial #局部的布局,此目录下的*.ejs是对头尾等局部的控制| └── _widget #小挂件的布局,页面下方小挂件的控制├── source #源码| ├── css #css源码 | | ├── _base #*.styl基础css| | ├── _partial #*.styl局部css| | ├── fonts #字体| | ├── images #图片| | └── style.styl #*.styl引入需要的css源码| ├── fancybox #fancybox效果源码| └── js #javascript源代码├── _config.yml #主题配置文件└── README.md #用GitHub的都知道关于Hexo迁移最近,Waterstrong提交了一版,这版本可以将hexo布置在GitHub其下的其他项目,比如Blog等。但是还是有些东西需要修改。1234567891011121314151617181920非常感谢Waterstrong# URL #这项暂不配置,绑定域名后,欲创建sitemap.xml需要配置该项## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'url: http://luuman.github.io/Blog/root: /Blog/permalink: :year/:month/:day/:title/permalink_defaults:上传是需要出入密码# Deployment 站点部署到github要配置,上一节中已经讲过## Docs: http://zespia.tw/hexo/docs/deploy.htmldeploy: type: git #repository: [email protected]:luuman/Blog.git repository: https://github.com/luuman/Blog.git branch: gh-pagesBlogBlog]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo插件安装]]></title>
<url>%2F2015%2F12%2F27%2FHexoPlug%2F</url>
<content type="text"><获取CLIENT ID:a0d4bdab154b4c689aff70602cb34a2c用client_id去换取token:在浏览器中请求: https://instagram.com/oauth/authorize/?client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&response_type=token https://instagram.com/oauth/authorize/?client_id=a0d4bdab154b4c689aff70602cb34a2c&redirect_uri=http://luuman.github.io/&response_type=token 花括号里面的值,对应上一步最终得到的client_id和自己设定的redirect_uri。 请求到的是一个授权页面,授权完毕后,则重定向到你的redirect_uri。 注意看授权成功后的url,hash部分会附带给你的token。至此,token成功获取,将至放在data-client-id。data-user-id:需要到[lookup-user-id](http://jelled.com/instagram/lookup-user-id#)填写用户名并查找。分享按钮添加代码123456789101112131415161718192021222324252627282930以下代码是百度分享的页面24页面分享的代码,可以自行选择以下标签。配置vim themes/light/layout/_partial/article.ejs删除<%-partial('post/share')%>替换为刚刚获取的分享代码<div class="bdsharebuttonbox"> <a href="#" class="fx fa-weibo bds_tsina" data-cmd="tsina" title="分享到新浪微博"></a> <a href="#" class="fx fa-weixin bds_weixin" data-cmd="weixin" title="分享到微信"></a> <a href="#" class="fx fa-qq bds_sqq" data-cmd="sqq" title="分享到QQ好友"></a> <a href="#" class="fx fa-facebook-official bds_fbook" data-cmd="fbook" title="分享到Facebook"></a> <a href="#" class="fx fa-twitter bds_twi" data-cmd="twi" title="分享到Twitter"></a> <a href="#" class="fx fa-linkedin bds_linkedin" data-cmd="linkedin" title="分享到linkedin"></a> <a href="#" class="fx fa-files-o bds_copy" data-cmd="copy" title="分享到复制网址"></a> <a href="#" class="fx fa-plus-square bds_more" data-cmd="more"></a> <a href="#" class="fx fa-tencent-weibo bds_tqq" data-cmd="tqq" title="分享到腾讯微博"></a> <a href="#" class="fx fa-renren bds_renren" data-cmd="renren" title="分享到人人网"></a> <a href="#" class="fx fa-paw bds_tieba" data-cmd="tieba" title="分享到百度贴吧"></a> <a href="#" class="fx fa-envelope-o bds_mail" data-cmd="mail" title="分享到邮件分享"></a></div> <a href="#" class="fx fa-print bds_print" data-cmd="print" title="分享到打印"></a> <a href="#" class="fx fa-share-alt bds_mshare" data-cmd="mshare" title="分享到一键分享"></a> <a href="#" class="fx bds_douban" data-cmd="douban" title="分享到豆瓣网"></a> <a href="#" class="fx fa- bds_qzone" data-cmd="qzone" title="分享到QQ空间"></a> <a href="#" class="fx fa- bds_evernotecn" data-cmd="evernotecn" title="分享到印象笔记"></a></div><script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"1","bdMiniList":false,"bdPic":"","bdStyle":"2","bdSize":"24"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>修改样式1234567891011121314151617181920212223242526272829303132\themes\spfk\source\css\_partial\article.styl/* bd share button box */.bdshare-button-style2-24{ width: 330px; margin: auto; .fx { color: #999; padding: 0; margin: 6px; height: 54px; display: inline-block; font: normal normal normal 36px/1 FontAwesome; background: none; text-rendering: auto; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .fx:hover{ color: #FFF; opacity: 1; }}themes\spfk\source\css\_partial\mobile.styl/* bd share button box */.bdshare-button-style2-24{ width: 289px; .fx { font: normal normal normal 30px/1 FontAwesome; }}百度统计添加代码1234567891011121314151617181920212223242526去百度统计获取统计代码vim themes/light/layout/_partial/baidu_analytics.ejs<% if (theme.baidu_analytics){ %><script>var _hmt = _hmt || [];(function() { var hm = document.createElement("script"); hm.src = "//hm.baidu.com/hm.js?819b1c6493df653afb8c784db6"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s);})();</script><% } %>vim hexo/themes/light/_config.ymlbaidu_analytics: truevim hexo/themes/light/layout/_partial/head.ejs在/head前添加<%- partial('baidu_analytics') %></head>不蒜子添加代码123456789101112131415161718192021222324252627themes/你的主题/layout/_partial/footer.ejs<footer id="footer"> <div class="outer"> <div id="footer-info"> <div class="footer-left"> &copy; <%= date(new Date(), 'YYYY') %> <%= config.author || config.title %> </div> <div class="footer-right"> <a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://github.com/luuman/hexo-theme-spfk" target="_blank">spfk</a> by luuman </div> </div> <div class="visit"> <span id="busuanzi_container_site_pv" style='display:none'> <span id="site-visit" >本站到访数: <span id="busuanzi_value_site_uv"></span> </span> </span> <span id="busuanzi_container_page_pv" style='display:none'> <span id="page-visit">, 本页阅读量: <span id="busuanzi_value_page_pv"></span> </span> </span> </div> </div><script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script></footer>修改样式移动端出现上移themes\spfk\source\css_partial\mobile.styl1234567891011121314#footer { bottom: 10px; .footer-left{ float: initial; margin-bottom: 10px; } .footer-right{ float: initial; margin-bottom: 10px; }}#container .visit { margin-top: 1em;}版权声明添加代码123456789101112131415161718192021222324252627282930313233343536373839404142\layout\_partial\post\nav.ejs<% if (post.original != false && !is_page()){ %> <div class="copyright"> <p><span>本文标题:</span><a href="<%- url_for(post.path) %>"><%= post.title %></a></p> <p><span>文章作者:</span><a href="/" title="请访问 <%=theme.author%> 博客"><%=theme.author%></a></p> <!-- <p><span>发布时间:</span><%= post.date.format("YYYY年MM月DD日 - HH时mm分") %></p> --> <!-- <p><span>最后更新:</span><%= post.updated.format("YYYY年MM月DD日 - HH时mm分") %></p> --> <p> <span>原始链接:</span><a class="post-url" href="<%- url_for(post.path) %>" title="<%= post.title %>"><%= post.permalink %></a> <span class="copy-path" data-clipboard-text="原文: <%= post.permalink %> 作者: <%=theme.author%>" title="点击复制文章链接"><i class="fa fa-clipboard"></i></span> <script src="/js/clipboard.min.js"></script> <script> var clipboard = new Clipboard('.copy-path'); </script> </p> <p> <span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/cn/" title="中国大陆 (CC BY-NC-SA 3.0 CN)">"署名-非商用-相同方式共享 3.0"</a> 转载请保留原文链接及作者。 </p> </div><% } %><% if (post.prev || post.next){ %><nav id="article-nav"> <% if (post.prev){ %> <a href="<%- url_for(post.prev.path) %>" id="article-nav-newer" class="article-nav-link-wrap"> <strong class="article-nav-caption"><</strong> <div class="article-nav-title"> <% if (post.prev.title){ %> <%= post.prev.title %> <% } else { %> (no title) <% } %> </div> </a> <% } %> <% if (post.next){ %> <a href="<%- url_for(post.next.path) %>" id="article-nav-older" class="article-nav-link-wrap"> <div class="article-nav-title"><%= post.next.title %></div> <strong class="article-nav-caption">></strong> </a> <% } %></nav><% } %>修改样式12345678910111213141516171819202122232425262728293031323334353637383940\themes\spfk\source\css\_partial\article.styl/* copyright */.copyright { width: 85%; max-width: 45em; margin: 0 auto; padding: .5em 1.8em; border: 1px solid lightgray; font-size: .93em; line-height: 1.6em; word-break: break-word; background: rgba(255, 255, 255, .4); span { margin-right: 1em; color: #B5B5B5; font-weight: bold; } a { color: gray; &:hover { font-weight: bold; color: #a3d2a3; text-decoration: underline; } } &:hover p .copy-path::after { content: "复制"; } .post-url:hover { font-weight: normal; } .copy-path { margin-left: 1em; &:hover { color: gray; cursor: pointer; } }}社交账号图标修改添加代码123456789\themes\spfk\layout\_partial\left-col.ejs<nav class="header-nav"> <div class="social"> <% for (var i in theme.subnav){ %> <a class="fl <%= i %>" target="_blank" href="<%- url_for(theme.subnav[i]) %>" title="<%= i %>"><%= i %></a> <%}%> </div></nav>修改样式站内搜索框添加代码用ajax+json搜索完美解决Hexo静态博客搜索问题站点Swiftype搜索框添加代码12345678910111213141516171819202122232425\themes\spfk\layout\_partial\left-col.ejs<form> <input type="text" class="st-default-search-input search" id="search" placeholder=" Search..." autocomplete="off" autocorrect="off" autocapitalize="off"></form>D:\Hexo\Hexo\themes\spfk\layout\_partial\after-footer.ejs<script type="text/javascript"> window.onload = function(){ document.getElementById("search").onclick = function(){ console.log("search") search(); } } function search(){ (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){ (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t); e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e); })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st'); _st('install','A1Pz-LKMXbrzcFg2FWi6','2.0.0'); }</script>修改样式1234567891011121314151617181920212223242526272829303132333435363738394041.search { width: 68%; height: 18px; margin-top: 1px; padding: 0; font-family: inherit; border: 2px solid transparent; border-bottom: 2px solid lightgray; border-radius: 2px; opacity: .7; background: none; &:hover { border: 0px solid lightgray; opacity: 1; box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); };}display: inline-block; width: 190px; height: 16px; padding: 7px 11px 7px 28px; border: 1px solid #bbb; border: 1px solid rgba(0,0,0,0.25); font-weight: 400; color: #444; font-size: 14px; line-height: 16px; box-sizing: content-box; background: #fff 8px 8px no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6%2BR8AAAACXB…Hx4Taq1nrnKaW8K6XUUsrHWuvNevdRRLzFGwzvDbXAB9cDAHvhedDruuxSAAAAAElFTkSuQmCC); background-clip: padding-box; -webkit-border-radius: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; border-radius: 5px; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;RSS不显示123456789 安装RSS插件$ npm install hexo-generator-feed --save 开启RSS功能 编辑hexo/themes_config.yml,添加如下代码: rss: /atom.xml #rss地址 默认即可sitemap网站地图12345678910111213141516171819202122232425262728293031323334353637381、安装插件:$ npm install hexo-generator-sitemap --save$ npm install hexo-generator-baidu-sitemap --save2、在博客目录的hexo/_config.yml中添加如下代码:# 自动生成sitemap编辑sitemap:path: sitemap.xmlbaidusitemap:path: baidusitemap.xml3、hexo编译的时候会自动在根目录生成站点地图 UUhike@UUhike-pc MINGW64 /d/Hexo/Hexo (master) $ npm install hexo-generator-sitemap --save npm WARN install Couldn't install optional dependency: Unsupported npm WARN install Couldn't install optional dependency: Unsupported [email protected] D:\Hexo\Hexo └── [email protected] UUhike@UUhike-pc MINGW64 /d/Hexo/Hexo (master) $ npm install hexo-generator-baidu-sitemap --save npm WARN install Couldn't install optional dependency: Unsupported npm WARN install Couldn't install optional dependency: Unsupported [email protected] D:\Hexo\Hexo └── [email protected] UUhike@UUhike-pc MINGW64 /d/Hexo/Hexo (master) $ hexo g INFO Files loaded in 2.42 s INFO Generated: baidusitemap.xml INFO Generated: sitemap.xml INFO 2 files generated in 477 ms多说评论插件添加代码123456789101112131415161718192021222324252627282930313233343536373839 ├── spfk ├── _config.yml #主题配置文件 #是否开启多说评论,填写你在多说申请的项目名称 duoshuo: duoshuo-key(http://duoshuo-key.duoshuo.com/) #若使用disqus,请在博客config文件中填写disqus_shortname,并关闭多说评论 duoshuo: true复制到 themes\landscape\layout\_partial\article.ejs把<% if (!index && post.comments && config.disqus_shortname){ %><section id="comments"><div id="disqus_thread"><noscript>Please enable JavaScript to view the <a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript></div></section><% } %>改为<% if (!index && post.comments && config.disqus_shortname){ %><section id="comments"><!-- 多说评论框 start --><div class="ds-thread" data-thread-key="<%= post.layout %>-<%= post.slug %>" data-title="<%= post.title %>" data-url="<%= page.permalink %>"></div><!-- 多说评论框 end --><!-- 多说公共JS代码 start (一个网页只需插入一次) --><script type="text/javascript">var duoshuoQuery = {short_name:'<%= config.disqus_shortname %>'}; (function() { var ds = document.createElement('script'); ds.type = 'text/javascript';ds.async = true; ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js'; ds.charset = 'UTF-8'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ds); })(); </script><!-- 多说公共JS代码 end --></section><% } %>修改样式:V说:设计达人:设计达人:添加方法:添加方法:打开「后台」 > 「多说评论」 > 「设置」 > 「基本设置」 > 然后把样式粘贴到「自定义CSS」文本框 > 「保存」个性样式:1#ds-thread #ds-reset ul.ds-comments-tabs li.ds-tab a.ds-current{border:0;color:#848568;text-shadow:none;background:#dddfc2}#ds-thread #ds-reset .ds-highlight{font-family:Arial,Helvetica,sans-serif;font-size:14px;font-weight:700;color:#848568!important}#ds-thread #ds-reset ul.ds-comments-tabs li.ds-tab a.ds-current:hover{color:#696a52;background:#d4d6ba}#ds-thread #ds-reset a.ds-highlight:hover{color:#696a52!important}#ds-thread{padding-left:30px}#ds-thread #ds-reset #ds-hot-posts,#ds-thread #ds-reset li.ds-post{overflow:visible}#ds-thread #ds-reset .ds-post-self{padding:10px 0 10px 10px}#ds-thread #ds-reset .ds-post-self,#ds-thread #ds-reset li.ds-post{border:0!important}#ds-reset .ds-avatar,#ds-thread #ds-reset ul.ds-children .ds-avatar{position:absolute;top:26px;left:-14px;padding:5px;width:36px;height:36px;box-shadow:-1px 0 1px rgba(0,0,0,.15) inset;border-radius:46px;background:#E5E6D0}#ds-thread #ds-reset ul.ds-children .ds-avatar{left:-23px}#ds-thread .ds-avatar a{display:inline-block;padding:1px;width:32px;height:32px;border:1px solid #b9baa6;border-radius:50%;background-color:#fff!important}#ds-thread .ds-avatar a:hover{border-color:#de5a4e}#ds-thread .ds-avatar>img{margin:2px 0 0 2px}#ds-thread #ds-reset .ds-replybox{box-shadow:none}#ds-reset .ds-replybox.ds-inline-replybox a.ds-avatar,#ds-thread #ds-reset ul.ds-children .ds-replybox.ds-inline-replybox a.ds-avatar{left:0;top:0;padding:0;width:32px!important;height:32px!important;background:0 0;box-shadow:none}#ds-reset .ds-replybox.ds-inline-replybox a.ds-avatar img{width:32px!important;height:32px!important;border-radius:50%}#ds-reset .ds-replybox .ds-avatar img,#ds-reset .ds-replybox a.ds-avatar{padding:0;width:50px!important;height:50px!important;border-radius:5px}#ds-reset .ds-avatar img{width:32px!important;height:32px!important;border-radius:32px;box-shadow:0 1px 3px rgba(0,0,0,.22);-webkit-transition:.4s all ease-in-out;-moz-transition:.4s all ease-in-out;-o-transition:.4s all ease-in-out;-ms-transition:.4s all ease-in-out;transition:.4s all ease-in-out}.ds-post-self:hover .ds-avatar img{-webkit-transform:rotate(360deg);-moz-transform:rotate(360deg);-o-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}#ds-thread #ds-reset .ds-comment-body{background:#F0F0E3;padding:15px 15px 12px 32px;border-radius:5px;box-shadow:0 1px 2px rgba(0,0,0,.15),0 1px 0 rgba(255,255,255,.75) inset}#ds-thread #ds-reset .ds-comment-body p{color:#787968}#ds-thread #ds-reset .ds-comments a.ds-user-name{font-weight:700;color:#696A52!important}#ds-thread #ds-reset .ds-comments a.ds-user-name:hover{color:#D32!important}#ds-thread #ds-reset #ds-hot-posts{border:0}#ds-reset #ds-hot-posts .ds-gradient-bg{background:0 0}#ds-reset #ds-bubble #ds-ctx .ds-ctx-entry{padding:0}#ds-reset #ds-bubble #ds-ctx-bubble .ds-avatar a,#ds-reset #ds-bubble .ds-avatar{position:static;padding:0;border:0;background:0 0;box-shadow:none}#ds-reset #ds-bubble #ds-ctx-bubble .ds-avatar a,#ds-reset #ds-bubble .ds-avatar img{width:45px!important;height:45px!important}#ds-reset #ds-bubble .ds-user-name{padding-left:13px}#ds-reset .ds-comment-body #ds-ctx{border-left:1px solid #b9baa6;background-color:#e8e8dc!important}#ds-reset #ds-ctx{margin-right:-15px}#ds-reset #ds-ctx .ds-ctx-entry{position:relative;padding:10px 30px 10px 10px}#ds-reset #ds-ctx .ds-ctx-entry .ds-avatar{top:6px;left:5px;background:0 0;box-shadow:none}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-body{margin-left:46px}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-content{color:#787968}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-head a{color:#696A52;font-weight:700}个性样式:[震动效果]: http://www.vsay.cn/wp-content/uploads/2012/09/7.gif1#ds-reset .ds-avatar img,#ds-reset .ds-avatar img:hover{-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;-ms-animation-fill-mode:both;-o-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:0s;-moz-animation-duration:0s;-ms-animation-duration:0s;-o-animation-duration:0s;animation-duration:0s;-webkit-animation-duration:.7s;-moz-animation-duration:.7s;-ms-animation-duration:.7s;-o-animation-duration:.7s;animation-duration:.7s}@-webkit-keyframes wobble{0%{-webkit-transform:translateX(0)}15%{-webkit-transform:translateX(-25%) rotate(-5deg)}30%{-webkit-transform:translateX(20%) rotate(3deg)}45%{-webkit-transform:translateX(-15%) rotate(-3deg)}60%{-webkit-transform:translateX(10%) rotate(2deg)}75%{-webkit-transform:translateX(-5%) rotate(-1deg)}100%{-webkit-transform:translateX(0)}}@-moz-keyframes wobble{0%{-moz-transform:translateX(0)}15%{-moz-transform:translateX(-25%) rotate(-5deg)}30%{-moz-transform:translateX(20%) rotate(3deg)}45%{-moz-transform:translateX(-15%) rotate(-3deg)}60%{-moz-transform:translateX(10%) rotate(2deg)}75%{-moz-transform:translateX(-5%) rotate(-1deg)}100%{-moz-transform:translateX(0)}}@-o-keyframes wobble{0%{-o-transform:translateX(0)}15%{-o-transform:translateX(-25%) rotate(-5deg)}30%{-o-transform:translateX(20%) rotate(3deg)}45%{-o-transform:translateX(-15%) rotate(-3deg)}60%{-o-transform:translateX(10%) rotate(2deg)}75%{-o-transform:translateX(-5%) rotate(-1deg)}100%{-o-transform:translateX(0)}}@keyframes wobble{0%{transform:translateX(0)}15%{transform:translateX(-25%) rotate(-5deg)}30%{transform:translateX(20%) rotate(3deg)}45%{transform:translateX(-15%) rotate(-3deg)}60%{transform:translateX(10%) rotate(2deg)}75%{transform:translateX(-5%) rotate(-1deg)}100%{transform:translateX(0)}}#ds-reset .ds-avatar img:hover{-webkit-animation-name:wobble;-moz-animation-name:wobble;-o-animation-name:wobble;animation-name:wobble}个性样式:[MOxFIVE]: http://www.vsay.cn/wp-content/uploads/2012/09/7.gif1#ds-ssr{display:none !important}#ds-reset{font-weight:normal;font-size:13px;font-size-adjust:none;color:#333;line-height:1;text-align:left}#ds-reset *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}#ds-reset input[type=button],#ds-reset input[type=submit],#ds-reset input[type=reset],#ds-reset button{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#ds-reset div,#ds-reset ul,#ds-reset ol,#ds-reset li,#ds-reset ul li,#ds-reset ol li,#ds-reset iframe,#ds-reset h1,#ds-reset h2,#ds-reset h3,#ds-reset h4,#ds-reset h5,#ds-reset h6,#ds-reset p,#ds-reset img,#ds-reset blockquote,#ds-reset a,#ds-reset span,#ds-reset pre,#ds-reset code,#ds-reset strong,#ds-reset sub,#ds-reset sup,#ds-reset fieldset,#ds-reset form,#ds-reset label,#ds-reset input,#ds-reset textarea,#ds-reset select{border:0;padding:0;margin:0;vertical-align:baseline;font:inherit;line-height:inherit;background:none;width:auto;float:none;overflow:visible;transition:none}#ds-reset strong{font-weight:bold}#ds-reset p{text-indent:0;clear:none}#ds-reset span,#ds-reset strong,#ds-reset label,#ds-reset input{display:inline;margin:0}#ds-reset textarea:focus,#ds-reset input:focus{outline:none}#ds-reset ul,#ds-reset ol,#ds-reset ul li,#ds-reset ol li{list-style:none;display:block}#ds-reset input,#ds-reset button{-webkit-border-radius:3px;border-radius:3px}#ds-indicator{display:none;position:fixed;z-index:99999;top:150px;left:0;padding:8px;border-bottom-right-radius:3px;border-top-right-radius:3px;width:16px;height:16px;background:#666 url("data:image/gif;base64,R0lGODlhEAAQAPQAAGZmZv///2lpadzc3K+vr/r6+ufn5319fZmZmfDw8Le3t8DAwHV1daOjo4eHh9LS0srKygAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAAFUCAgjmRpnqUwFGwhKoRgqq2YFMaRGjWA8AbZiIBbjQQ8AmmFUJEQhQGJhaKOrCksgEla+KIkYvC6SJKQOISoNSYdeIk1ayA8ExTyeR3F749CACH5BAkKAAAALAAAAAAQABAAAAVoICCKR9KMaCoaxeCoqEAkRX3AwMHWxQIIjJSAZWgUEgzBwCBAEQpMwIDwY1FHgwJCtOW2UDWYIDyqNVVkUbYr6CK+o2eUMKgWrqKhj0FrEM8jQQALPFA3MAc8CQSAMA5ZBjgqDQmHIyEAIfkECQoAAAAsAAAAABAAEAAABWAgII4j85Ao2hRIKgrEUBQJLaSHMe8zgQo6Q8sxS7RIhILhBkgumCTZsXkACBC+0cwF2GoLLoFXREDcDlkAojBICRaFLDCOQtQKjmsQSubtDFU/NXcDBHwkaw1cKQ8MiyEAIfkECQoAAAAsAAAAABAAEAAABVIgII5kaZ6AIJQCMRTFQKiDQx4GrBfGa4uCnAEhQuRgPwCBtwK+kCNFgjh6QlFYgGO7baJ2CxIioSDpwqNggWCGDVVGphly3BkOpXDrKfNm/4AhACH5BAkKAAAALAAAAAAQABAAAAVgICCOZGmeqEAMRTEQwskYbV0Yx7kYSIzQhtgoBxCKBDQCIOcoLBimRiFhSABYU5gIgW01pLUBYkRItAYAqrlhYiwKjiWAcDMWY8QjsCf4DewiBzQ2N1AmKlgvgCiMjSQhACH5BAkKAAAALAAAAAAQABAAAAVfICCOZGmeqEgUxUAIpkA0AMKyxkEiSZEIsJqhYAg+boUFSTAkiBiNHks3sg1ILAfBiS10gyqCg0UaFBCkwy3RYKiIYMAC+RAxiQgYsJdAjw5DN2gILzEEZgVcKYuMJiEAOwAAAAAAAAAAAA==") 8px 8px no-repeat;*background-image:url("//static.duoshuo.com/images/loading.gif");*position:absolute;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}#ds-waiting{cursor:wait;display:block;width:16px;height:11px;padding:0 0 3px 5px;margin:0;background:url("data:image/gif;base64,R0lGODlhEAALAPQAAP///z2LqeLt8dvp7u7090GNqz2LqV+fuJ/F1IW2ycrf51aatHWswaXJ14i4ys3h6FmctUCMqniuw+vz9eHs8fb5+meku+Tu8vT4+cfd5bbT3tbm7PH2+AAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCwAAACwAAAAAEAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJCwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJCwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHTuBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V55zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAAABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7AAAAAAAAAAAA") 0 0 no-repeat;*background-image:url("//static.duoshuo.com/images/waiting.gif")}#ds-reset .ds-highlight{color:#d32 !important}#ds-reset .ds-rounded{-webkit-border-radius:3px;border-radius:3px}#ds-reset .ds-rounded-top{-webkit-border-top-right-radius:3px;-webkit-border-top-left-radius:3px;border-top-right-radius:3px;border-top-left-radius:3px}#ds-reset .ds-rounded-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-webkit-border-bottom-right-radius:3px}#ds-reset .ds-gradient-bg{background:url("//static.duoshuo.com/images/bg_sprites.png") 0 -60px repeat-x}#ds-reset .ds-avatar{box-shadow:0 1px 1px rgba(255,255,255,0.75);position:relative;-webkit-border-radius:3px;border-radius:3px;background-color:#fff;float:left}#ds-reset .ds-avatar img{display:block;width:50px;height:50px;max-width:none;box-shadow:0 1px 3px rgba(0,0,0,0.22);-webkit-border-radius:3px;border-radius:3px}#ds-reset .ds-avatar .ds-service-icon{display:block;position:absolute;bottom:-4px;right:-4px}#ds-reset img.ds-smiley{margin:0;padding:0;display:inline;border:none}#ds-reset .ds-icon{vertical-align:middle;display:inline-block;overflow:hidden;background:transparent url("//static.duoshuo.com/images/sprites.png") no-repeat;_background-image:url("//static.duoshuo.com/images/sprites.gif")}#ds-reset a .ds-icon{opacity:.6;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;transition:opacity .15s linear}#ds-reset a:hover .ds-icon{opacity:1}#ds-reset .ds-service-list a{vertical-align:middle;padding-right:3px}#ds-reset .ds-service-list li:hover a{color:#333}#ds-reset .ds-service-icon,#ds-reset .ds-service-icon-grey{width:16px !important;height:16px !important;line-height:100px;display:inline-block;background:url("//static.duoshuo.com/images/service-icons-color.png?v=2") no-repeat;_background-image:url("//static.duoshuo.com/images/service-icons-color.gif?v=2");overflow:hidden}#ds-reset .ds-service-icon-grey{background-image:url("//static.duoshuo.com/images/service-icons-grey.png");_background-image:url("//static.duoshuo.com/images/service-icons-grey.gif")}#ds-reset .ds-service-link{height:16px !important;line-height:16px;padding-left:20px;display:block;background:url("//static.duoshuo.com/images/service-icons-color.png?v=2") no-repeat;_background-image:url("//static.duoshuo.com/images/service-icons-color.gif?v=2");overflow:hidden}#ds-reset .ds-weibo{background-position:0 0}#ds-reset .ds-renren{background-position:0 -32px}#ds-reset .ds-qqt{background-position:0 -64px}#ds-reset .ds-kaixin{background-position:0 -80px}#ds-reset .ds-douban{background-position:0 -96px}#ds-reset .ds-qzone{background-position:0 -128px}#ds-reset .ds-duoshuo{background-position:0 -144px}#ds-reset .ds-qq{background-position:0 -192px}#ds-reset .ds-baidu{background-position:0 -208px}#ds-reset .ds-google{background-position:0 -240px}#ds-reset .ds-weixin{background-position:0 -272px}#ds-reset .ds-wechat{background-position:0 -272px}.ds-icons-32 a{display:block;cursor:pointer;width:32px !important;height:32px !important;background:url("//static.duoshuo.com/images/icons_large.png") no-repeat !important;overflow:hidden;text-indent:-9999px}.ds-icons-32 a.ds-weibo{background-position:-37px 0 !important}.ds-icons-32 a.ds-qzone{background-position:0 0 !important}.ds-icons-32 a.ds-qqt{background-position:-74px 0 !important}.ds-icons-32 a.ds-renren{background-position:-148px 0 !important}.ds-icons-32 a.ds-kaixin{background-position:-111px 0 !important}.ds-icons-32 a.ds-weixin{background-position:-224px 0 !important}.ds-icons-32 a.ds-wechat{background-position:-224px 0 !important}.ds-icons-32 a.ds-qq{background-position:-488px 0 !important}.ds-icons-32 a.ds-douban{background-position:-186px 0 !important}.ds-icons-32 a.ds-baidu{background-position:-262px 0 !important}#ds-reset #ds-ctx{padding:0;margin:8px 0;max-width:640px}#ds-reset #ds-ctx .ds-ctx-entry{padding:6px;margin:0;border-bottom:1px solid #e6e6e6}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-head a{color:#e77064}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-head a:hover{color:#d32}#ds-reset #ds-ctx .ds-ctx-entry .ds-avatar{margin:0;width:30px;height:30px}#ds-reset #ds-ctx .ds-ctx-entry .ds-avatar img{width:30px;height:30px;box-shadow:none}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-body{margin-left:38px}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-head{position:relative;_zoom:1;line-height:1em;padding:1px 0 0;margin:0 0 .25em}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-nth{color:#999;font-size:12px;position:absolute;top:2px;right:0}#ds-reset #ds-ctx .ds-ctx-entry .ds-time{font-size:12px;*font-size:12px;margin-left:8px;color:#999;_zoom:1}#ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-content{position:relative;_zoom:1;padding:0;margin:0;overflow:hidden;line-height:1.5em}#ds-reset #ds-ctx .ds-ctx-entry:hover .ds-comment-actions{display:block}#ds-reset #ds-ctx .ds-comment-actions{bottom:0;right:0;line-height:18px;position:absolute;display:none;*display:block}#ds-reset #ds-ctx .ds-comment-actions a{margin:0 0 0 6px}#ds-reset.ds-touch #ds-ctx .ds-ctx-entry .ds-comment-actions{display:block}#ds-reset .ds-comment-body #ds-ctx{border-left:3px solid #ccc;background-color:rgba(0,0,0,0.03)}#ds-reset.ds-no-opacity .ds-comment-body #ds-ctx{background:#f8f8f8}#ds-reset .ds-dialog-body #ds-ctx .ds-ctx-entry:hover .ds-comment-actions{display:none}#ds-thread{clear:both;position:relative;overflow:visible;_zoom:1}#ds-thread #ds-reset a{cursor:pointer;text-decoration:none;color:#777;background-color:transparent;-webkit-transition:color .15s linear;-moz-transition:color .15s linear;transition:color .15s linear}#ds-thread #ds-reset a:hover{color:#333}#ds-thread #ds-reset ul,#ds-thread #ds-reset ul li{background:none;margin:0;padding:0}#ds-thread #ds-reset .ds-arrow{position:absolute;width:0;height:0;font-size:0 !important;line-height:0 !important;_border-right-color:#ffc0cb !important;_border-left-color:#ffc0cb !important;_filter:chroma(color=#ffc0cb) !important}#ds-thread #ds-reset .ds-arrow-down{border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #fff}#ds-thread #ds-reset button{cursor:pointer;margin:0;padding:0;border-radius:0}#ds-thread #ds-reset .ds-meta{position:relative;padding:8px 0;line-height:24px;border-bottom:1px solid rgba(0,0,0,0.13)}#ds-thread #ds-reset .ds-like-tooltip{position:absolute;z-index:9999;background-color:#fcfcfc;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#fcfcfc), to(#f9f9f9));background:-moz-linear-gradient(top, #fcfcfc 0, #f9f9f9 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fcfcfc), color-stop(100%, #f9f9f9));background:-webkit-linear-gradient(top, #fcfcfc 0, #f9f9f9 100%);background:-ms-linear-gradient(top, #fcfcfc 0, #f9f9f9 100%);background:linear-gradient(top, #fcfcfc 0, #f9f9f9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fcfcfc',endColorstr='#f9f9f9',GradientType=0);border:1px solid #aaa;box-shadow:0 0 2px rgba(0,0,0,0.2);text-shadow:0 1px 0 #fff;font-size:12px;padding:8px 14px}#ds-thread #ds-reset .ds-like-tooltip ul{width:84px;float:left}#ds-thread #ds-reset .ds-like-tooltip li{line-height:16px;margin:6px 0}#ds-thread #ds-reset .ds-like-tooltip p{clear:both;margin:6px 0}#ds-thread #ds-reset .ds-like-tooltip .ds-like-tooltip-footer{text-align:right}#ds-thread #ds-reset a.ds-like-thread-button{color:#555;padding:4px 8px;border:1px solid #ccc;border-bottom-color:#aaa;box-shadow:inset 0 0 1px #fff;margin-right:15px;text-shadow:0 1px 0 #fff;background-color:#e0e0e0;background-repeat:no-repeat;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), color-stop(25%, #fff), to(#e0e0e0));background-image:-webkit-linear-gradient(#fff, #fff 25%, #e0e0e0);background-image:-moz-linear-gradient(top, #fff, #fff 25%, #e0e0e0);background-image:-ms-linear-gradient(#fff, #fff 25%, #e0e0e0);background-image:linear-gradient(#fff, #fff 25%, #e0e0e0)}#ds-thread #ds-reset a.ds-like-thread-button .ds-icon-heart{position:relative;top:-2px;opacity:1}#ds-thread #ds-reset a.ds-like-thread-button span{color:#555}#ds-thread #ds-reset .ds-thread-cancel-like{display:none}#ds-thread #ds-reset a.ds-thread-liked{background:#e9e9e9}#ds-thread #ds-reset a.ds-thread-liked:hover .ds-thread-cancel-like{display:inline}#ds-thread #ds-reset a.ds-thread-liked:hover .ds-thread-like-text{display:none}#ds-thread #ds-reset #ds-hot-posts{border:1px solid #ccc;overflow:hidden;margin:8px 0;padding:0;_height:100%}#ds-thread #ds-reset .ds-header{font-weight:bold;font-size:14px;color:#555;line-height:30px;padding:0 12px}#ds-thread #ds-reset .ds-toolbar{position:relative;z-index:5;font-size:12px;padding:8px 0;width:100%;clear:both}#ds-thread #ds-reset .ds-toolbar:after{content:".";display:block;height:0;clear:both;visibility:hidden}#ds-thread #ds-reset .ds-visitor{float:right;line-height:1.5em;margin-right:6px}#ds-thread #ds-reset .ds-account-control{float:right;position:relative;font-size:12px;cursor:pointer;text-align:right;line-height:18px;padding-bottom:3px;width:75px}#ds-thread #ds-reset .ds-account-control span{display:block;float:left;color:#999}#ds-thread #ds-reset .ds-account-control ul{display:none;position:absolute;top:19px;left:0;border:1px solid #aaa;background:#f8f8f8;box-shadow:inset 0 1px 1px #fff,0 1px 1px rgba(0,0,0,0.3);border-radius:3px;text-align:center}#ds-thread #ds-reset .ds-account-control ul li a{border-top:1px solid #fff;border-bottom:1px solid #ddd;display:block;padding:3px 10px;text-shadow:0 1px 0 #fff}#ds-thread #ds-reset .ds-account-control ul li a:hover{color:#555}#ds-thread #ds-reset .ds-account-control.ds-active span{color:#555}#ds-thread #ds-reset .ds-account-control.ds-active ul{display:block}#ds-thread #ds-reset .ds-alert{margin:.5em 0;border:1px solid #fbeed5;border-radius:3px;padding:6px 6px;color:#c09853;background-color:#fcf8e3;line-height:1.5em}#ds-thread #ds-reset .ds-login-buttons{width:100%;position:relative;padding:10px 0 6px}#ds-thread #ds-reset .ds-login-buttons p{float:left;line-height:24px;margin:0}#ds-thread #ds-reset .ds-login-buttons .ds-service-list li{float:left;height:16px;width:54px;padding:4px 0;margin:0 0 0 6px}#ds-thread #ds-reset .ds-login-buttons .ds-more-services{color:#d32 !important;line-height:16px;display:block}#ds-thread #ds-reset .ds-login-buttons .ds-more-services:hover{color:#e77064 !important}#ds-thread #ds-reset .ds-login-buttons .ds-additional-services{display:none}#ds-thread #ds-reset .ds-login-buttons .ds-social-links{float:left;width:306px}#ds-thread #ds-reset .ds-login-buttons:after{content:".";display:block;height:0;clear:both;visibility:hidden}#ds-thread #ds-reset a.ds-unread-comments-count{display:none;background-color:#d32;color:#fff !important;margin-right:6px;padding:1px 5px;font-weight:bold;-webkit-border-radius:5px;border-radius:5px;box-shadow:inset 0 1px 1px rgba(255,255,255,0.4),0 1px 1px rgba(0,0,0,0.3);text-shadow:0 1px 1px rgba(0,0,0,0.3)}#ds-thread #ds-reset a.ds-unread-comments-count:hover{background:#f00}#ds-thread #ds-reset .ds-replybox{width:auto;font-size:12px;z-index:3;margin:8px 0;padding:0 0 0 60px;position:relative;_zoom:1}#ds-thread #ds-reset .ds-replybox:after{content:".";display:block;height:0;clear:both;visibility:hidden}#ds-thread #ds-reset .ds-replybox .ds-avatar{position:absolute;top:0;left:0}#ds-thread #ds-reset .ds-replybox .ds-avatar img{width:50px;height:50px;visibility:visible;margin:0}#ds-thread #ds-reset .ds-inline-replybox{margin:8px 0 2px 0;padding-left:38px}#ds-thread #ds-reset .ds-inline-replybox .ds-avatar img{width:30px;height:30px;box-shadow:0 1px 2px rgba(0,0,0,0.22)}#ds-thread #ds-reset .ds-textarea-wrapper{position:relative;border:1px solid #ccc;border-bottom:none;padding-right:20px;background:#fff url("//static.duoshuo.com/images/bg_sprites.png") 0 -90px repeat-x;overflow:hidden}#ds-thread #ds-reset .ds-textarea-wrapper textarea{box-shadow:none;-webkit-appearance:none;overflow:auto;padding:10px;height:54px;margin:0;resize:none;color:#999;width:100%}#ds-thread #ds-reset .ds-textarea-wrapper textarea:focus{color:#333}#ds-thread #ds-reset .ds-textarea-wrapper .ds-hidden-text{word-wrap:break-word;visibility:hidden;position:absolute;top:0;left:10px;right:10px}#ds-thread #ds-reset .ds-textarea-wrapper textarea,#ds-thread #ds-reset .ds-textarea-wrapper .ds-hidden-text{display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:20px;border:none}#ds-thread #ds-reset .ds-post-toolbar{position:relative;width:100%;box-shadow:0 1px 0 rgba(255,255,255,0.6)}#ds-thread #ds-reset .ds-post-toolbar span,#ds-thread #ds-reset .ds-post-toolbar input,#ds-thread #ds-reset .ds-post-toolbar label,#ds-thread #ds-reset .ds-post-toolbar a{vertical-align:middle;width:auto}#ds-thread #ds-reset .ds-post-options{position:relative;margin-right:100px;height:30px;border:1px solid #ccc;border-right:none;border-bottom-color:#aaa;border-bottom-left-radius:3px;-webkit-border-bottom-left-radius:3px}#ds-thread #ds-reset .ds-toolbar-buttons{position:absolute;top:5px;left:6px}#ds-thread #ds-reset .ds-toolbar-button{display:block;width:19px !important;height:19px;float:left;margin-right:4px;background:transparent url("//static.duoshuo.com/images/sprites.png") no-repeat;_background-image:url("//static.duoshuo.com/images/sprites.gif");vertical-align:middle;opacity:.6;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;transition:opacity .15s linear}#ds-thread #ds-reset .ds-toolbar-button:hover{opacity:1}#ds-thread #ds-reset .ds-add-image{background-position:0 -48px}#ds-thread #ds-reset .ds-add-image:hover{background-position:0 -66px}#ds-thread #ds-reset .ds-add-emote{background-position:0 -12px}#ds-thread #ds-reset .ds-add-emote:hover{background-position:0 -30px}#ds-thread #ds-reset .ds-sync{font-size:12px;color:#999;line-height:30px;position:absolute;right:5px}#ds-thread #ds-reset .ds-sync label{color:#777;cursor:pointer;-webkit-transition:color .15s linear;-moz-transition:color .15s linear;transition:color .15s linear}#ds-thread #ds-reset .ds-sync label:hover{color:#555}#ds-thread #ds-reset .ds-sync a.ds-service-icon,#ds-thread #ds-reset .ds-sync a.ds-service-icon-grey{margin:7px 2px 7px 3px}#ds-thread #ds-reset .ds-post-button{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;position:absolute;right:0;top:0;height:32px;width:100px;text-align:center;text-shadow:0 1px 0 #fff;color:#555;font-size:14px;font-weight:bold;border:1px solid #ccc;border-bottom-color:#aaa;border-bottom-right-radius:3px;-webkit-border-bottom-right-radius:3px;background-color:#e6e6e6;background-repeat:no-repeat;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fcfcfc), color-stop(25%, #fcfcfc), to(#e6e6e6));background-image:-webkit-linear-gradient(#fcfcfc, #fcfcfc 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #fcfcfc, #fcfcfc 25%, #e6e6e6);background-image:-ms-linear-gradient(#fcfcfc, #fcfcfc 25%, #e6e6e6);background-image:linear-gradient(#fcfcfc, #fcfcfc 25%, #e6e6e6);-webkit-transition:all .15s linear;-moz-transition:all .15s linear;transition:all .15s linear;box-shadow:inset 0 0 1px #fff}#ds-thread #ds-reset .ds-post-button:hover{background-position:0 -15px;color:#333}#ds-thread #ds-reset .ds-post-button:active{-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}#ds-thread #ds-reset .ds-comments-info{width:100%;font-size:13px;margin-top:10px;padding:8px 0;line-height:25px;position:relative}#ds-thread #ds-reset .ds-sort{position:absolute;right:0;top:8px}#ds-thread #ds-reset .ds-sort a{color:#999;padding:0 4px;margin:0 2px}#ds-thread #ds-reset .ds-sort a:hover{color:#333}#ds-thread #ds-reset .ds-sort a.ds-current,#ds-thread #ds-reset .ds-sort a:active{color:#d32}#ds-thread #ds-reset ul.ds-comments-tabs .ds-highlight{margin:0 2px 0 0}#ds-thread #ds-reset ul.ds-comments-tabs .ds-service-icon{vertical-align:middle;margin:0 2px 1px 0}#ds-thread #ds-reset li.ds-tab{display:inline;font-size:13px;margin:0 5px 0 0;padding:0}#ds-thread #ds-reset li.ds-tab a{text-shadow:0 1px 0 #fff;padding:3px 5px;display:inline;-webkit-border-radius:5px;border-radius:5px}#ds-thread #ds-reset li.ds-tab a.ds-current{border:1px solid #ccc;background-color:rgba(0,0,0,0.04)}#ds-thread #ds-reset li.ds-tab a:hover{background-color:rgba(0,0,0,0.04)}#ds-thread #ds-reset .ds-comments{width:100%;border-bottom:1px solid rgba(0,0,0,0.13)}#ds-thread #ds-reset .ds-comments:after{content:".";display:block;height:0;clear:both;visibility:hidden}#ds-thread #ds-reset li.ds-post{width:100%;overflow:hidden;clear:both;border-top:1px solid rgba(0,0,0,0.13);margin:0;padding:0;list-style:none}#ds-thread #ds-reset li.ds-post-placeholder{text-align:center;color:#999;padding:1em 0}#ds-thread #ds-reset .ds-post-self{position:relative;padding:10px;border-top:1px solid rgba(255,255,255,0.7)}#ds-thread #ds-reset .ds-post-self:after{content:".";display:block;height:0;clear:both;visibility:hidden}#ds-thread #ds-reset .ds-post-self:hover .ds-post-delete,#ds-thread #ds-reset .ds-post-self:hover .ds-post-report{display:inline-block}#ds-thread #ds-reset.ds-touch .ds-post-self .ds-post-delete,#ds-thread #ds-reset.ds-touch .ds-post-self .ds-post-report{display:inline-block}#ds-thread #ds-reset .ds-comment-body{padding-left:60px}#ds-thread #ds-reset .ds-comment-body p{font-size:13px;line-height:1.5em;margin:.5em 0;word-wrap:break-word}#ds-thread #ds-reset .ds-comment-body img{max-width:100%;vertical-align:text-bottom;box-shadow:none}#ds-thread #ds-reset .ds-comment-body embed{max-width:100%}#ds-thread #ds-reset .ds-comment-body code{display:block;font-size:12px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;padding:8px 12px;background-color:#f0f0f0;margin:8px 0;border-radius:3px;border:1px solid #ddd;color:#666}#ds-thread #ds-reset .ds-comment-body a{color:#777}#ds-thread #ds-reset .ds-comment-body a:hover{color:#555}#ds-thread #ds-reset a.ds-comment-context{position:relative;margin:.5em 0;color:#e77064}#ds-thread #ds-reset a.ds-comment-context:hover{color:#d32}#ds-thread #ds-reset #ds-bubble{position:absolute;background-color:#fff;-webkit-border-radius:5px;border-radius:5px;padding:10px;color:#333;border:1px solid #aaa;box-shadow:0 0 2px rgba(0,0,0,0.2);z-index:9999;font-size:13px}#ds-thread #ds-reset #ds-bubble a{color:#e77064}#ds-thread #ds-reset #ds-bubble a:hover{color:#d32}#ds-thread #ds-reset #ds-bubble p{line-height:18px}#ds-thread #ds-reset #ds-bubble .ds-arrow-border{border-top-color:#aaa;bottom:-6px}#ds-thread #ds-reset #ds-bubble .ds-arrow{left:32px;bottom:-5px}#ds-thread #ds-reset #ds-ctx-bubble{width:300px}#ds-thread #ds-reset #ds-ctx-bubble .ds-bubble-footer{padding:6px 0 0 0;line-height:18px}#ds-thread #ds-reset #ds-user-card{width:276px;min-height:50px}#ds-thread #ds-reset #ds-user-card .ds-avatar{margin-right:10px}#ds-thread #ds-reset #ds-user-card .ds-avatar img{width:50px;height:50px}#ds-thread #ds-reset #ds-user-card .ds-user-name{vertical-align:top;display:inline-block;max-width:8em;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:14px}#ds-thread #ds-reset #ds-user-card .ds-user-card-meta{margin:14px 0 0 62px}#ds-thread #ds-reset #ds-user-card .ds-user-description{border-top:1px dotted #ddd;margin-top:.5em;color:#aaa}#ds-thread #ds-reset #ds-user-card .ds-service-icon{margin-right:3px}#ds-thread #ds-reset .ds-comment-header{padding-top:1px}#ds-thread #ds-reset .ds-comment-footer{line-height:1.5em}#ds-thread #ds-reset .ds-comment-footer a{margin:0 6px 0 0;padding:0 6px 0 0}#ds-thread #ds-reset .ds-comment-actions a{font-size:12px;color:#999}#ds-thread #ds-reset .ds-comment-actions a .ds-icon{position:relative;top:-1px}#ds-thread #ds-reset .ds-user-name{color:#777;font-size:13px;margin-right:8px}#ds-thread #ds-reset .ds-post-liked .ds-icon-like{background-position:0 -130px}#ds-thread #ds-reset .ds-post-liked a.ds-post-likes{color:#d32}#ds-thread #ds-reset .ds-reply-active{display:block}#ds-thread #ds-reset .ds-reply-active .ds-post-reply{color:#333}#ds-thread #ds-reset .ds-reply-active .ds-post-reply .ds-icon{opacity:1}#ds-thread #ds-reset .ds-post-delete,#ds-thread #ds-reset .ds-post-report{display:none}#ds-thread #ds-reset .ds-icon-heart{width:14px;height:13px;background-position:0 -130px}#ds-thread #ds-reset .ds-icon-settings{width:12px;height:12px;margin:3px 4px 0;opacity:1}#ds-thread #ds-reset .ds-icon-like{width:14px;height:13px;background-position:0 -117px}#ds-thread #ds-reset .ds-icon-share{width:18px;height:13px;background-position:0 -234px}#ds-thread #ds-reset .ds-icon-reply{width:18px;height:13px;background-position:0 -105px}#ds-thread #ds-reset .ds-icon-delete{width:13px;height:13px;background-position:0 -176px}#ds-thread #ds-reset .ds-icon-report{width:12px;height:12px;background-position:0 -189px}#ds-thread #ds-reset .ds-time{font-size:12px;*font-size:12px;margin-right:8px;color:#999;_zoom:1}#ds-thread #ds-reset ul.ds-children{margin-left:38px}#ds-thread #ds-reset ul.ds-children .ds-avatar{width:30px;height:30px}#ds-thread #ds-reset ul.ds-children .ds-avatar img{width:30px;height:30px}#ds-thread #ds-reset ul.ds-children .ds-post-self{padding-left:0}#ds-thread #ds-reset ul.ds-children .ds-comment-body{padding-left:38px}#ds-thread #ds-reset .ds-paginator{border-bottom:1px solid rgba(0,0,0,0.13);text-align:right;padding-bottom:15px;clear:both;line-height:1em}#ds-thread #ds-reset .ds-paginator div.ds-border{border-top:1px solid rgba(255,255,255,0.7);margin-bottom:15px}#ds-thread #ds-reset .ds-paginator a{font-size:12px;margin:0 3px;padding:2px 5px;border:1px solid transparent}#ds-thread #ds-reset .ds-paginator a:hover,#ds-thread #ds-reset .ds-paginator a.ds-current{-webkit-border-radius:3px;border-radius:3px;background-color:rgba(0,0,0,0.03)}#ds-thread #ds-reset .ds-paginator a.ds-current{color:#d32;border:1px solid #ccc}#ds-thread #ds-reset .ds-powered-by{font-size:12px;text-align:right;padding:10px 0}#ds-thread #ds-reset .ds-powered-by a{color:#999;text-decoration:none}#ds-thread #ds-reset .ds-powered-by a:hover{color:#555}#ds-thread #ds-reset.ds-no-transition .ds-post-button,#ds-thread #ds-reset.ds-no-transition .ds-more a{background:url("//static.duoshuo.com/images/bg_sprites.png") repeat-x !important}#ds-thread #ds-reset.ds-no-transition .ds-post-button:hover,#ds-thread #ds-reset.ds-no-transition .ds-more a:hover{background-position:0 -30px !important}#ds-thread #ds-reset.ds-no-transition .ds-like-thread-button{background:url("//static.duoshuo.com/images/bg_sprites.png") repeat-x}#ds-thread #ds-reset.ds-no-opacity li.ds-post{border-top:1px solid #ddd}#ds-thread #ds-reset.ds-no-opacity .ds-comments,#ds-thread #ds-reset.ds-no-opacity .ds-paginator{border-bottom:1px solid #ddd}#ds-thread #ds-reset.ds-no-opacity .ds-post-self{border-top:none}#ds-thread #ds-reset.ds-no-opacity .ds-tab a.ds-current{background:#f8f8f8}#ds-thread #ds-reset.ds-ie6 .ds-post-report,#ds-thread #ds-reset.ds-ie6 .ds-post-delete{display:inline !important}#ds-thread #ds-reset.ds-ie6 .ds-textarea-wrapper{padding:10px 10px}#ds-thread #ds-reset.ds-ie6 .ds-textarea-wrapper textarea{width:95%;color:#333;padding:0}#ds-thread #ds-reset.ds-ie6 .ds-post{width:100%;float:left}#ds-thread #ds-reset.ds-ie6 .ds-tab a.ds-current{padding-bottom:5px}#ds-thread #ds-reset.ds-ie6 #ds-ctx-bubble .ds-arrow{bottom:-8px}#ds-thread #ds-reset.ds-ie6 #ds-ctx-bubble .ds-arrow-border{bottom:-9px}#ds-thread.ds-narrow #ds-reset .ds-post-self{padding:8px}#ds-thread.ds-narrow #ds-reset .ds-comment-body,#ds-thread.ds-narrow #ds-reset .ds-replybox{padding-left:38px}#ds-thread.ds-narrow #ds-reset .ds-avatar img{width:30px;height:30px}#ds-thread.ds-narrow #ds-reset .ds-post-button{width:70px}#ds-thread.ds-narrow #ds-reset .ds-post-options{margin-right:70px}#ds-smilies-tooltip{border:1px solid #aaa;position:absolute;width:400px;background-color:#fff;z-index:9999;box-shadow:0 0 2px rgba(0,0,0,0.2);text-shadow:0 1px 0 #fff;-webkit-border-radius:3px;border-radius:3px}#ds-smilies-tooltip a{cursor:pointer}#ds-smilies-tooltip ul{list-style-type:none;padding:0;margin:0}#ds-smilies-tooltip ul.ds-smilies-tabs{width:119px;position:absolute;top:0;left:0;height:159px;overflow-y:auto;background:#f8f8f8;border-right:1px solid #ccc;border-top-left-radius:3px;border-bottom-left-radius:3px}#ds-smilies-tooltip ul.ds-smilies-tabs li a{color:#999;padding:6px 10px;display:block;border-bottom:1px solid #ccc;background-color:#fff;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#fff), to(#e9e9e9));background:-moz-linear-gradient(top, #fff 0, #e9e9e9 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(100%, #e9e9e9));background:-webkit-linear-gradient(top, #fff 0, #e9e9e9 100%);background:-ms-linear-gradient(top, #fff 0, #e9e9e9 100%);background:linear-gradient(top, #fff 0, #e9e9e9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#e9e9e9',GradientType=0);font-size:12px;line-height:1.3em}#ds-smilies-tooltip ul.ds-smilies-tabs li:first-child a{border-top-left-radius:3px}#ds-smilies-tooltip ul.ds-smilies-tabs li a.ds-current{color:#666;background:#e3e3e3;filter:none;box-shadow:inset 0 0 4px rgba(0,0,0,0.1)}#ds-smilies-tooltip .ds-smilies-container{padding:10px 5px;height:140px;margin-left:125px;overflow-y:auto}#ds-smilies-tooltip .ds-smilies-container li{list-style:none;float:left;width:26px;height:26px;text-align:center;cursor:pointer}#ds-smilies-tooltip .ds-smilies-container li img{visibility:visible}#ds-smilies-tooltip .ds-smilies-container li:hover{position:relative;top:-1px}#ds-wrapper{left:0;right:0;top:20%;bottom:0;width:100%;margin:auto;z-index:9999;position:fixed;_position:absolute;text-align:center;color:#777}#ds-wrapper .ds-dialog,#ds-wrapper #ds-reset.ds-dialog{margin:0 auto;text-align:left;_zoom:1;width:480px;max-width:100%}#ds-wrapper #ds-reset.ds-dialog-bind-more .ds-service-list{width:50%}#ds-wrapper #ds-reset a{cursor:pointer;text-decoration:none;color:#777}#ds-wrapper #ds-reset .ds-dialog-inner{width:100%;position:relative;border:1px solid #aaa;background:#fff url("//static.duoshuo.com/images/bg_sprites.png") 0 -90px repeat-x;text-shadow:0 1px 0 #fff;box-shadow:inset 0 1px 1px #fff,0 2px 6px rgba(0,0,0,0.4)}#ds-wrapper #ds-reset .ds-dialog-inner .ds-unread-list{max-height:300px;overflow-y:auto}#ds-wrapper #ds-reset .ds-control-group{margin:18px 0;position:relative;padding-right:80px;max-width:166px}#ds-wrapper #ds-reset .ds-control-group input{color:#777;width:100%;font-size:13px;border:1px solid #ccc;padding:4px 80px 6px 6px;box-shadow:inset 0 1px 3px rgba(0,0,0,0.1)}#ds-wrapper #ds-reset .ds-control-group input:focus{border-color:#08b5fb}#ds-wrapper #ds-reset .ds-control-group label{font-size:13px;color:#ccc;letter-spacing:1px;position:absolute;right:0;top:8px}#ds-wrapper #ds-reset tr{height:45px}#ds-wrapper #ds-reset button{cursor:pointer;color:#555;background-color:#e6e6e6;background-repeat:no-repeat;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), color-stop(25%, #fff), to(#e6e6e6));background-image:-webkit-linear-gradient(#fff, #fff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #fff, #fff 25%, #e6e6e6);background-image:-ms-linear-gradient(#fff, #fff 25%, #e6e6e6);background-image:linear-gradient(#fff, #fff 25%, #e6e6e6);-webkit-transition:all .15s linear;-moz-transition:all .15s linear;transition:all .15s linear;border:1px solid #aaa;display:inline-block;font-size:15px;height:30px;width:100px;padding:0}#ds-wrapper #ds-reset button:hover{background-position:0 -15px;color:#333}#ds-wrapper #ds-reset button:active{top:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}#ds-wrapper #ds-reset h2{display:block;font-weight:normal;font-size:16px;margin:0 0 15px 0;color:#555}#ds-wrapper #ds-reset .ds-dialog-body{padding:30px 30px 25px;position:relative;overflow:hidden}#ds-wrapper #ds-reset .ds-icons-32{height:32px;margin-bottom:20px;overflow:hidden}#ds-wrapper #ds-reset .ds-icons-32 a{float:left;margin:0 5px 0 0}#ds-wrapper #ds-reset ul li{margin:10px 0}#ds-wrapper #ds-reset .ds-service-list{width:45%;float:left}#ds-wrapper #ds-reset .ds-service-list .ds-more-services{display:none}#ds-wrapper #ds-reset .ds-icon-ok{background-position:0 -203px;width:12px;height:12px}#ds-wrapper #ds-reset .ds-quote{margin:10px 0;padding:6px 10px;background:#f8f8f8;line-height:1.5em;font-size:12px;overflow-y:auto;max-height:180px}#ds-wrapper #ds-reset .ds-textarea-wrapper{border:1px solid #ccc;padding:0 20px 0 0;position:relative;margin:12px 0}#ds-wrapper #ds-reset .ds-textarea-wrapper textarea{width:100%;height:54px;margin:0;resize:none;padding:6px 10px;overflow:auto}#ds-wrapper #ds-reset .ds-textarea-wrapper .ds-hidden-text{top:0;left:10px;right:10px;position:absolute;visibility:hidden;word-wrap:break-word}#ds-wrapper #ds-reset .ds-textarea-wrapper textarea,#ds-wrapper #ds-reset .ds-textarea-wrapper .ds-hidden-text{font-size:13px;line-height:1.5em}#ds-wrapper #ds-reset .ds-actions{position:relative;height:30px}#ds-wrapper #ds-reset .ds-actions button{display:block;position:absolute;top:0;right:0}#ds-wrapper #ds-reset .ds-dialog-close{position:absolute;bottom:13px;right:11px;display:block;width:13px;height:13px;overflow:hidden;background:transparent url("//static.duoshuo.com/images/sprites.png") 0 -163px no-repeat;_background-image:url("//static.duoshuo.com/images/sprites.gif")}#ds-wrapper #ds-reset .ds-dialog-close:hover{background-position:0 -176px}#ds-wrapper #ds-reset .ds-logo{display:inline-block;width:64px;height:21px;margin-right:10px;background:url("//static.duoshuo.com/images/logo.png") 0 0 no-repeat}#ds-wrapper #ds-reset .ds-dialog-footer{clear:both;border-top:1px dotted #ccc;padding:10px 15px 6px}#ds-wrapper #ds-reset .ds-dialog-footer span{color:#999;position:relative;top:-6px}#ds-wrapper #ds-reset .ds-connect{display:none}#ds-wrapper #ds-reset .ds-unread-list li{position:relative;margin:0;padding:8px 0;border-top:1px solid #eee;line-height:1.5em;color:#777}#ds-wrapper #ds-reset .ds-unread-list li a{color:#d32}#ds-wrapper #ds-reset .ds-unread-list li a:hover{color:#e45c4e}#ds-wrapper #ds-reset .ds-unread-list li a[rel~="author"]{color:#777}#ds-wrapper #ds-reset .ds-unread-list li .ds-delete{display:none;position:absolute;right:0;bottom:10px;text-indent:-9999px;width:14px;height:14px;overflow:hidden;background:transparent url("//static.duoshuo.com/images/delete.gif") no-repeat scroll 0 -14px}#ds-wrapper #ds-reset .ds-unread-list li:hover .ds-delete{display:block}#ds-wrapper #ds-reset.ds-touch .ds-unread-list li .ds-delete{display:block}#ds-wrapper.ds-no-transition #ds-reset button{background:url("//static.duoshuo.com/images/bg_sprites.png") repeat-x !important}#ds-wrapper.ds-no-transition #ds-reset button:hover{background-position:0 -30px !important}#ds-wrapper.ds-no-transition #ds-reset.ds-dialog{background-image:url("//static.duoshuo.com/images/black.png")}#ds-wrapper.ds-ie6 #ds-reset{margin-top:0}#ds-wrapper.ds-ie6 #ds-reset .ds-dialog-footer span{top:-3px}#ds-notify{position:fixed;*position:absolute;z-index:9999;max-width:144px;_width:130px;display:block;float:none;padding:8px 12px;background-color:#fff;-webkit-border-radius:5px;border-radius:5px;box-shadow:0 1px 1px rgba(0,0,0,0.25);border:1px solid #aaa}#ds-notify #ds-reset{line-height:14px}#ds-notify #ds-reset a.ds-logo{width:18px;height:14px;background:transparent url("//static.duoshuo.com/images/sprites.png") 0 -220px no-repeat;_background-image:url("//static.duoshuo.com/images/sprites.gif");position:absolute;display:block;top:8px;left:12px}#ds-notify #ds-reset span.ds-unread-count{font-weight:bold;color:#e32}#ds-notify #ds-reset ul.ds-notify-unread{line-height:150%;display:inline-block;margin:0 0 0 22px;padding:0}#ds-notify #ds-reset ul.ds-notify-unread li a{color:#d32;text-decoration:none}#ds-recent-comments li.ds-comment{list-style-type:none;position:relative !important;margin:0 !important;padding:6px 0 !important;_zoom:1;border-top:1px solid #dcdcdc;word-wrap:break-word;font-size:13px}#ds-recent-comments li.ds-comment a{display:inline}#ds-recent-comments li.ds-comment div{padding:0;margin:0}#ds-recent-comments li.ds-comment .ds-avatar{position:absolute !important;top:6px !important;left:0 !important}#ds-recent-comments li.ds-comment .ds-avatar a{display:block}#ds-recent-comments li.ds-comment .ds-meta{*margin-left:-15px;_margin-left:0}#ds-recent-comments li.ds-comment .ds-time{font-size:10px;color:#999;margin-left:5px}#ds-recent-comments li.ds-comment .ds-thread-title{margin:0 0 4px 0;line-height:13px;font-size:12px;color:#777}#ds-recent-comments li.ds-comment .ds-thread-title a{font-size:12px}#ds-recent-comments li.ds-comment .ds-excerpt{line-height:18px}#ds-recent-comments li.ds-comment.ds-show-avatars{padding-left:38px !important}#ds-recent-visitors .ds-avatar{display:inline;padding:0 !important;margin:4px !important}#ds-login .ds-icons-32 a{float:left;margin:0 5px 0 0}#ds-share #ds-reset.ds-share-aside-left ul,#ds-share #ds-reset.ds-share-aside-right ul,#ds-share #ds-reset.ds-share-inline ul{list-style:none;margin:0;padding:0;*zoom:1}#ds-share #ds-reset.ds-share-aside-left ul:after,#ds-share #ds-reset.ds-share-aside-right ul:after,#ds-share #ds-reset.ds-share-inline ul:after{content:".";display:block;height:0;clear:both;visibility:hidden}#ds-share #ds-reset.ds-share-aside-left ul li,#ds-share #ds-reset.ds-share-aside-right ul li,#ds-share #ds-reset.ds-share-inline ul li{list-style:none;float:left;font-size:14px;padding:7px 0}#ds-share #ds-reset.ds-share-inline{position:relative}#ds-share #ds-reset.ds-share-inline ul li{margin-left:8px}#ds-share #ds-reset.ds-share-inline ul li:first-child{margin-left:0}#ds-share #ds-reset.ds-share-aside-left,#ds-share #ds-reset.ds-share-aside-right{position:fixed;top:50%;z-index:1000;-webkit-transition:all .2s linear;-moz-transition:all .2s linear;transition:all .2s linear}#ds-share #ds-reset.ds-share-aside-left{left:0;-webkit-transform:translate(-100%, -50%);-ms-transform:translate(-100%, -50%);-o-transform:translate(-100%, -50%);transform:translate(-100%, -50%)}#ds-share #ds-reset.ds-share-aside-right{right:0;-webkit-transform:translate(100%, -50%);-ms-transform:translate(100%, -50%);-o-transform:translate(100%, -50%);transform:translate(100%, -50%)}#ds-share #ds-reset .ds-share-aside-toggle{width:28px;padding:23px 2px;background:#e94c4c;color:#fff;position:absolute;top:0;text-align:center;font-size:16px;font-weight:bolder;cursor:pointer}#ds-share #ds-reset.ds-share-aside-left .ds-share-aside-toggle{right:-32px;border-top-right-radius:3px;border-bottom-right-radius:3px}#ds-share #ds-reset.ds-share-aside-left .ds-share-icons{border-top-right-radius:0;border-top-left-radius:0;border-bottom-left-radius:0;border-left:none}#ds-share #ds-reset.ds-share-aside-right .ds-share-aside-toggle{left:-32px;border-top-left-radius:3px;border-bottom-left-radius:3px}#ds-share #ds-reset.ds-share-aside-right .ds-share-icons{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:0;border-right:none}#ds-share #ds-reset.slide-to-left{-webkit-transform:translate(0, -50%);-ms-transform:translate(0, -50%);-o-transform:translate(0, -50%);transform:translate(0, -50%)}#ds-share #ds-reset.slide-to-right{-webkit-transform:translate(0, -50%);-ms-transform:translate(0, -50%);-o-transform:translate(0, -50%);transform:translate(0, -50%)}#ds-share #ds-reset .ds-share-icons-32 .ds-weibo,#ds-share #ds-reset .ds-share-icons-32 .ds-sohu,#ds-share #ds-reset .ds-share-icons-32 .ds-renren,#ds-share #ds-reset .ds-share-icons-32 .ds-netease,#ds-share #ds-reset .ds-share-icons-32 .ds-qqt,#ds-share #ds-reset .ds-share-icons-32 .ds-kaixin,#ds-share #ds-reset .ds-share-icons-32 .ds-douban,#ds-share #ds-reset .ds-share-icons-32 .ds-msn,#ds-share #ds-reset .ds-share-icons-32 .ds-qzone,#ds-share #ds-reset .ds-share-icons-32 .ds-duoshuo,#ds-share #ds-reset .ds-share-icons-32 .ds-360,#ds-share #ds-reset .ds-share-icons-32 .ds-alipay,#ds-share #ds-reset .ds-share-icons-32 .ds-qq,#ds-share #ds-reset .ds-share-icons-32 .ds-baidu,#ds-share #ds-reset .ds-share-icons-32 .ds-taobao,#ds-share #ds-reset .ds-share-icons-32 .ds-google,#ds-share #ds-reset .ds-share-icons-32 .ds-more,#ds-share #ds-reset .ds-share-icons-32 .ds-wechat,#ds-share #ds-reset .ds-share-icons-32 .ds-diandian,#ds-share #ds-reset .ds-share-icons-32 .ds-huaban,#ds-share #ds-reset .ds-share-icons-32 .ds-duitang,#ds-share #ds-reset .ds-share-icons-32 .ds-youdao,#ds-share #ds-reset .ds-share-icons-32 .ds-pengyou,#ds-share #ds-reset .ds-share-icons-32 .ds-facebook,#ds-share #ds-reset .ds-share-icons-32 .ds-twitter,#ds-share #ds-reset .ds-share-icons-32 .ds-linkedin,#ds-share #ds-reset .ds-share-icons-32 .ds-meilishuo,#ds-share #ds-reset .ds-share-icons-32 .ds-mogujie{height:32px;width:32px;text-decoration:none;color:#999;display:block;overflow:hidden;background-image:url("//static.duoshuo.com/images/service-icons-color-32.png");background-repeat:no-repeat;_background-image:url("//static.duoshuo.com/images/service-icons-color-32.gif")}#ds-share #ds-reset .ds-share-icons-32 .ds-weibo{background-position:0 0}#ds-share #ds-reset .ds-share-icons-32 .ds-sohu{background-position:0 -32px}#ds-share #ds-reset .ds-share-icons-32 .ds-renren{background-position:0 -64px}#ds-share #ds-reset .ds-share-icons-32 .ds-netease{background-position:0 -96px}#ds-share #ds-reset .ds-share-icons-32 .ds-qqt{background-position:0 -128px}#ds-share #ds-reset .ds-share-icons-32 .ds-kaixin{background-position:0 -160px}#ds-share #ds-reset .ds-share-icons-32 .ds-douban{background-position:0 -192px}#ds-share #ds-reset .ds-share-icons-32 .ds-msn{background-position:0 -224px}#ds-share #ds-reset .ds-share-icons-32 .ds-qzone{background-position:0 -256px}#ds-share #ds-reset .ds-share-icons-32 .ds-duoshuo{background-position:0 -288px}#ds-share #ds-reset .ds-share-icons-32 .ds-360{background-position:0 -320px}#ds-share #ds-reset .ds-share-icons-32 .ds-alipay{background-position:0 -352px}#ds-share #ds-reset .ds-share-icons-32 .ds-qq{background-position:0 -384px}#ds-share #ds-reset .ds-share-icons-32 .ds-baidu{background-position:0 -416px}#ds-share #ds-reset .ds-share-icons-32 .ds-taobao{background-position:0 -448px}#ds-share #ds-reset .ds-share-icons-32 .ds-google{background-position:0 -480px}#ds-share #ds-reset .ds-share-icons-32 .ds-more{background-position:0 -512px}#ds-share #ds-reset .ds-share-icons-32 .ds-wechat{background-position:0 -544px}#ds-share #ds-reset .ds-share-icons-32 .ds-diandian{background-position:0 -576px}#ds-share #ds-reset .ds-share-icons-32 .ds-huaban{background-position:0 -608px}#ds-share #ds-reset .ds-share-icons-32 .ds-duitang{background-position:0 -640px}#ds-share #ds-reset .ds-share-icons-32 .ds-youdao{background-position:0 -672px}#ds-share #ds-reset .ds-share-icons-32 .ds-pengyou{background-position:0 -704px}#ds-share #ds-reset .ds-share-icons-32 .ds-facebook{background-position:0 -736px}#ds-share #ds-reset .ds-share-icons-32 .ds-twitter{background-position:0 -768px}#ds-share #ds-reset .ds-share-icons-32 .ds-linkedin{background-position:0 -800px}#ds-share #ds-reset .ds-share-icons-32 .ds-meilishuo{background-position:0 -832px}#ds-share #ds-reset .ds-share-icons-32 .ds-mogujie{background-position:0 -864px}#ds-share #ds-reset .ds-share-icons-32 .flat{background-image:url("//static.duoshuo.com/images/service-icons-color-flat-32.png");_background-image:url("//static.duoshuo.com/images/service-icons-color-flat-32.gif")}#ds-share #ds-reset .ds-share-icons-16 .ds-weibo,#ds-share #ds-reset .ds-share-icons-16 .ds-sohu,#ds-share #ds-reset .ds-share-icons-16 .ds-renren,#ds-share #ds-reset .ds-share-icons-16 .ds-netease,#ds-share #ds-reset .ds-share-icons-16 .ds-qqt,#ds-share #ds-reset .ds-share-icons-16 .ds-kaixin,#ds-share #ds-reset .ds-share-icons-16 .ds-douban,#ds-share #ds-reset .ds-share-icons-16 .ds-msn,#ds-share #ds-reset .ds-share-icons-16 .ds-qzone,#ds-share #ds-reset .ds-share-icons-16 .ds-duoshuo,#ds-share #ds-reset .ds-share-icons-16 .ds-360,#ds-share #ds-reset .ds-share-icons-16 .ds-alipay,#ds-share #ds-reset .ds-share-icons-16 .ds-qq,#ds-share #ds-reset .ds-share-icons-16 .ds-baidu,#ds-share #ds-reset .ds-share-icons-16 .ds-taobao,#ds-share #ds-reset .ds-share-icons-16 .ds-google,#ds-share #ds-reset .ds-share-icons-16 .ds-more,#ds-share #ds-reset .ds-share-icons-16 .ds-wechat,#ds-share #ds-reset .ds-share-icons-16 .ds-diandian,#ds-share #ds-reset .ds-share-icons-16 .ds-huaban,#ds-share #ds-reset .ds-share-icons-16 .ds-duitang,#ds-share #ds-reset .ds-share-icons-16 .ds-youdao,#ds-share #ds-reset .ds-share-icons-16 .ds-pengyou,#ds-share #ds-reset .ds-share-icons-16 .ds-facebook,#ds-share #ds-reset .ds-share-icons-16 .ds-twitter,#ds-share #ds-reset .ds-share-icons-16 .ds-linkedin,#ds-share #ds-reset .ds-share-icons-16 .ds-meilishuo,#ds-share #ds-reset .ds-share-icons-16 .ds-mogujie{line-height:16px;padding-left:20px;text-decoration:none;color:#999;display:block;overflow:hidden;background-image:url("//static.duoshuo.com/images/service-icons-color.png?v=2");background-repeat:no-repeat;_background-image:url("//static.duoshuo.com/images/service-icons-color.gif?v=2")}#ds-share #ds-reset .ds-share-icons-16 .ds-weibo{background-position:0 0}#ds-share #ds-reset .ds-share-icons-16 .ds-sohu{background-position:0 -16px}#ds-share #ds-reset .ds-share-icons-16 .ds-renren{background-position:0 -32px}#ds-share #ds-reset .ds-share-icons-16 .ds-netease{background-position:0 -48px}#ds-share #ds-reset .ds-share-icons-16 .ds-qqt{background-position:0 -64px}#ds-share #ds-reset .ds-share-icons-16 .ds-kaixin{background-position:0 -80px}#ds-share #ds-reset .ds-share-icons-16 .ds-douban{background-position:0 -96px}#ds-share #ds-reset .ds-share-icons-16 .ds-msn{background-position:0 -112px}#ds-share #ds-reset .ds-share-icons-16 .ds-qzone{background-position:0 -128px}#ds-share #ds-reset .ds-share-icons-16 .ds-duoshuo{background-position:0 -144px}#ds-share #ds-reset .ds-share-icons-16 .ds-360{background-position:0 -160px}#ds-share #ds-reset .ds-share-icons-16 .ds-alipay{background-position:0 -176px}#ds-share #ds-reset .ds-share-icons-16 .ds-qq{background-position:0 -192px}#ds-share #ds-reset .ds-share-icons-16 .ds-baidu{background-position:0 -208px}#ds-share #ds-reset .ds-share-icons-16 .ds-taobao{background-position:0 -224px}#ds-share #ds-reset .ds-share-icons-16 .ds-google{background-position:0 -240px}#ds-share #ds-reset .ds-share-icons-16 .ds-more{background-position:0 -256px}#ds-share #ds-reset .ds-share-icons-16 .ds-wechat{background-position:0 -272px}#ds-share #ds-reset .ds-share-icons-16 .ds-diandian{background-position:0 -288px}#ds-share #ds-reset .ds-share-icons-16 .ds-huaban{background-position:0 -304px}#ds-share #ds-reset .ds-share-icons-16 .ds-duitang{background-position:0 -320px}#ds-share #ds-reset .ds-share-icons-16 .ds-youdao{background-position:0 -336px}#ds-share #ds-reset .ds-share-icons-16 .ds-pengyou{background-position:0 -352px}#ds-share #ds-reset .ds-share-icons-16 .ds-facebook{background-position:0 -368px}#ds-share #ds-reset .ds-share-icons-16 .ds-twitter{background-position:0 -384px}#ds-share #ds-reset .ds-share-icons-16 .ds-linkedin{background-position:0 -400px}#ds-share #ds-reset .ds-share-icons-16 .ds-meilishuo{background-position:0 -416px}#ds-share #ds-reset .ds-share-icons-16 .ds-mogujie{background-position:0 -432px}#ds-share #ds-reset .ds-share-icons-16 .flat{background-image:url("//static.duoshuo.com/images/service-icons-color-flat.png");_background-image:url("//static.duoshuo.com/images/service-icons-color-flat.gif")}#ds-share #ds-reset .ds-share-icons{border:1px solid #ccc;background:#fff;border-radius:3px}#ds-share #ds-reset .ds-share-icons .ds-share-icons-inner{width:208px;padding:10px}#ds-share #ds-reset .ds-share-icons .ds-share-icons-inner ul{margin:0;padding:0}#ds-share #ds-reset .ds-share-icons .ds-share-icons-inner ul li{padding-left:8px;margin-left:0;width:92px;font-size:12px}#ds-share #ds-reset .ds-share-icons .ds-share-icons-inner ul li:hover{border-radius:3px;background:#eee}#ds-share #ds-reset .ds-share-icons .ds-share-icons-inner ul li:nth-child(even){margin-left:8px}#ds-share #ds-reset .ds-share-icons .ds-share-icons-footer{text-align:right;line-height:30px;font-size:12px;color:#ccc;background-color:#eee;padding-right:10px}#ds-share #ds-reset .ds-share-icons-more{top:30px;left:0;position:absolute;z-index:1000}#ds-share.ds-no-transition #ds-reset.ds-share-aside-left{left:-229px;transform:none}#ds-share.ds-no-transition #ds-reset.ds-share-aside-right{right:-229px;transform:none}#ds-share .ds-share-aside-left,#ds-share .ds-share-aside-right{width:230px;_position:absolute;_bottom:auto;_top:expression(eval(document.documentElement.scrollTop+200))}#ds-share .ds-share-aside-left{_left:expression(eval(document.documentElement.scrollLeft-230))}#ds-share .ds-share-aside-right{_right:auto;_left:expression(eval(document.documentElement.scrollLeft+document.documentElement.clientWidth-this.offsetWidth)-(parseInt(this.currentStyle.marginLeft,10)||0)-(parseInt(this.currentStyle.marginRight,10)||0 - 230))}具体样式请参照:多说.css为Hexo博客添加目录Hexo博客系统的核心支持生成目录(Table of Contents),但其默认的主题Landscape并不支持目录的显示。我们只需对Landscape的主题文件稍作修改并添加一点目录的CSS就可以在文章前面显示友好的目录了。修改Landscape主题的ejs文件我们首先要编辑文章显示页面的模板,也就是themes/landscape/layout/_partial/article.ejs文件。为了将目录生成在正文之前,我们首先在这个文件中找到<%- post.content %>,并在这一行之前加入如下代码:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 引入文件_partial\article.ejs <% if (!index && post.toc != false && !is_page()){ %> <%- partial('_partial/toc') %> <% } %> <% if (!index && post.toc){ %> <%- partial('post/toc') %> <% } %><div id="toc" class="toc-article"> <strong class="toc-title">文章目录</strong> <%- toc(post.content) %></div><style> .left-col .switch-btn { display: none; } .left-col .switch-area { display: none; }</style><input type="button" id="tocButton" value="隐藏目录" title="点击按钮隐藏或者显示文章目录"><%- js('http://7.url.cn/edu/jslib/comb/require-2.1.6,jquery-1.9.1.min') %><script> var toc_button = document.getElementById("tocButton"); var toc_div = document.getElementById("toc"); toc_button.onclick=function() { if (toc_div.style.display == "none") { toc_div.style.display = "block"; toc_button.value = "隐藏目录"; document.getElementById("switch-btn").style.display = "none"; document.getElementById("switch-area").style.display = "none"; } else { toc_div.style.display = "none"; toc_button.value = "显示目录"; document.getElementById("switch-btn").style.display = "block"; document.getElementById("switch-area").style.display = "block"; } } if ($(".toc").length < 1) { $("#toc").css("display","none"); $("#tocButton").css("display","none"); $(".switch-btn").css("display","block"); $(".switch-area").css("display","block"); }</script><% if (theme.toc_nowrap) { %> <style> .toc { white-space: nowrap; overflow-x: hidden; } </style> <script> $(document).ready(function() { $(".toc li a").mouseover(function() { var title = $(this).attr('href'); $(this).attr("title", title); }); }) </script><% } %>这段代码的含义清晰明了,if语句中有两个条件,!index是为了不在首页的文章摘要中生成目录,post.toc确保了只在显式地标记了toc: true的文章中生成目录。若这两个条件满足,则创建一个目录的。修改完这个文件之后,找一篇包含了多个子标题的文章,并在文章开头的front-matter中添加一句toc: true,在浏览器中访问这篇文章,应该可以看到文章的开头处已经有了带链接的目录。但是这样的目录实在太难看,我们还需要添加相应的CSS来将其指定为我们想要的样式。为目录编写CSS文件要指定目录的样式,我们要修改的文件是themes/landscape/source/css/_partial/article.styl。在文件的最后,添加如下代码:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110/*toc*/#tocButton { position: fixed; border: none; left: 220px; top: 382px; background: none; font-size: .9em; font-weight: bold; color: lightgray; cursor: pointer font-family: inherit; outline: none; /*Remove button border when clicked.*/ -webkit-appearance: none; /*Remove iOS button style*/ &:hover { color: #88acdb; }}.toc-article { position: fixed; width: 230px; top: 378px; bottom: 1em; left: 0; margin-left: 0em; padding: 6px 10px 10px 50px; border-radius: 2.8%; overflow: auto;}#toc { float: right; font-size: .9em; line-height: 1.65em; z-index: 12; a { color: gray; &:visited { color: rgba(244, 131, 133, 1); } &:hover { color: #88acdb; text-decoration: none; } } li:hover { background: none; li:hover { background: rgba(158, 188, 226, .21); } } .toc-title { font-weight: bold; color: gray; } .toc { padding: .7em; padding-right: 0; li { list-style-type: none; } } ol { margin-left: 0; } .toc-child { padding-left: 1.25em; margin: 4px 0; } .toc-link:hover { background: rgba(158, 188, 226, .21); }}.copyright { width: 85%; max-width: 45em; margin: 0 auto; padding: .5em 1.8em; border: 1px solid lightgray; font-size: .93em; line-height: 1.6em; word-break: break-word; background: rgba(255, 255, 255, .4); span { margin-right: 1em; color: #B5B5B5; font-weight: bold; } a { color: gray; &:hover { font-weight: bold; color: #a3d2a3; text-decoration: underline; } } &:hover p .copy-path::after { content: "复制"; } .post-url:hover { font-weight: normal; } .copy-path { margin-left: 1em; &:hover { color: gray; cursor: pointer; } }}第一段的toc-article指定了目录整个的背景色、边框色、倒角半径、各种间距以及最大的宽度。注意这里最好指定目录的最大宽度,我将其设为了28%,也就是文章正文那个框的宽度的28%,也可以设为一个固定的长度,比如在笔记本电脑上16em就是个不错的宽度,但为了能适配各种不同尺寸的屏幕,最好还是设置为百分比。如果不指定最大宽度,遇到比较长的标题时,生成的目录会非常难看。这个最大宽度的设置是我在网上其他添加目录的方法中没有见到的。第二段的toc-title指的就是“文章目录”那四个字,这四个字要比其他字大一些,将其字号设为其他字的120%。第三段的#toc.toc指定了目录列表的一些细节,将font-size设为0.9em会让目录的字比文章的字稍小一些。最后的.toc-child指定了二级目录的缩进量。再次生成页面,应该已经可以显示比较美观的目录了。收尾工作通常情况下我们不需要为每一篇文章都添加目录,因为大部分文章的长度还是相对较短,或者结构简单而没有添加小标题。在我的博客上,需要添加目录的长文还是相对较少的。因为我选择了默认不生成目录,而手动为需要目录的文章添加显式地标记。下面我就需要编辑每一篇需要添加目录的文章,在文章开头的front-matter中加入toc: true。插入自定义页面仿照Hexo官网,了解到单页面的添加方式。添加代码1234567891011121314151617181920D:\Hexo\Hexos\themes\spfk\layout\plugins.swig<div id="content-wrap"> <div class="wrapper"> <div class="inner"> <header id="plugin-list-header"> <h1 id="plugin-list-title">{{ page.title }}</h1> <input type="search" id="plugin-search-input" placeholder="Search"> <div id="plugin-list-count">{{ site.data[page.data].length }} items</div> </header> <ul id="plugin-list"> {% for plugin in _.sortBy(site.data[page.data], 'name') %} {{ partial('_partial/' + page.partial, {plugin: plugin}) }} {% endfor %} </ul> </div> </div></div><script>window.SEARCH_INDEX = {{ lunr_index(site.data[page.data]) }}</script>1234567891011D:\Hexo\Hexos\themes\spfk\layout\_partial\plugin.swig<li class="plugin on"> <a href="{{ plugin.link }}" class="plugin-name" target="_blank">{{ plugin.name }}</a> <p class="plugin-desc">{{ plugin.description }}</p> <div class="plugin-tag-list"> {% for tag in plugin.tags %} <a href="#{{ tag }}" class="plugin-tag">{{ tag }}</a> {% endfor %} </div></li>123456789101112131415161718D:\Hexo\Hexos\themes\spfk\layout\_partial\work.swig<li class="plugin on"> <div class="plugin-screenshot"> <img src="{{ plugin.imgs }}" class="plugin-screenshot-img"> {% if plugin.preview %} <a href="{{ plugin.preview }}" class="plugin-preview-link" target="_blank"><i class="fa fa-eye"></i></a> {% endif %} </div> <a href="{{ plugin.link }}" class="plugin-name" target="_blank">{{ plugin.name }}</a> <p class="plugin-desc">{{ plugin.description }}</p> <div class="plugin-tag-list"> {% for tag in plugin.tags %} <a href="#{{ tag }}" class="plugin-tag">{{ tag }}</a> {% endfor %} </div></li>1234引入样式文件D:\Hexo\Hexos\themes\spfk\source\css\style.styl@import "_partial/plugins"修改样式123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126D:\Hexo\Hexos\themes\spfk\layout\_partial\plugin.swig#plugin-list-header clearfix() margin: 40px 0#plugin-list-title font-family: font-title font-size: 36px font-weight: 300 line-height: 1 float: left#plugin-list-count color: color-gray padding-top: 1em text-align: right @media mq-normal float: right line-height: 40px padding-top: 0 padding-right: 15px#plugin-search-input font-size: 16px font-family: inherit -webkit-appearance: none border: 1px solid color-border padding: 10px 10px width: 100% margin-top: 25px @media mq-normal float: right width: 50% margin-top: 0#plugin-list margin: 40px -20px display: flex flex-flow: column @media mq-tablet flex-flow: row wrap.plugin display: none padding: 20px @media mq-tablet flex: 0 0 50% @media mq-normal flex: 0 0 (100 / 3)% &.on display: block.plugin-name font-family: font-title font-weight: bold color: color-link font-size: 20px text-decoration: none line-height: 1 &:hover color: color-link-hover.plugin-desc line-height: line-height margin: 1em 0.plugin-tag-list clearfix() line-height: 1.3.plugin-tag color: color-gray font-size: 0.9em text-decoration: none float: left margin-right: 10px &:hover color: color-link-hover &:before content: "#".plugin-screenshot margin-bottom: 15px position: relative padding-top: (10 / 16 * 100)% // 16:10 ratio height: 0 overflow: hidden.plugin-screenshot-img position: absolute top: 0 left: 0 width: 100% height: auto.plugin-preview-link position: absolute top: 0 left: 0 width: 100% height: 100% background: rgba(0, 0, 0, 0.7) color: #fff text-align: center opacity: 0 transition: 0.15s &:hover opacity: 1 .fa opacity: 1 transform: scale(1) .fa position: absolute top: 0 left: 0 bottom: 0 right: 0 margin: auto font-size: 50px width: @font-size height: @font-size opacity: 0 transform: scale(6) transition: 0.2s transition-delay: 0.15s自定义挂件除了默认已提供的挂件外,你还可以自定义自己的小挂件,在hexo\themes\modernist\layout_widget\下,新建自己的ejs文件,如myWidget.ejs,然后在配置文件hexo\themes\modernist_config.yml中配置。1234567widgets: - myWidget用上述方法可以添加新浪微博小挂件。生成自己的微博组件。添加hexo\themes\modernist\layout\_widget\weibo.ejs文件。配置hexo\themes\modernist\_config.yml。Hexo语法高亮查阅格式高亮代码,了解到本主题,通过特定的规律进行语法高亮!好像无法识别不同代码的语法高亮!测试:通过测试代码,查看后台代码逻辑,了解到可以识别Apache、C++、bash等,还有部分不可识别。那么这个主题用的是什么的语法高亮?代码code,table-gutter-pre是代码前面的序号。class=”highlight apache”123456789101112131415161718192021J:\Hexo\Hexo\themes\spfk\source\css\_partial\highlight.styl// https://github.com/luuman/hexo-theme-spfkcode-bgc = #002B36code-tag = #F92672code-attr = #A6E22Ecode-word = #FFFFFFcode-value = #E6DB74code-number = #9E90FFcode-keyword = #66D9EFcode-comment = #75715Ecode-argument = #FD971F$code-block background: code-bgc margin: 10px 0 padding: 10px 10px overflow: auto color: #4C4C4C line-height: font-size * line-height参考:highlight.js:Demo https://highlightjs.org/static/demo/Solarized DarkAtelier Sulphurpool Dark文档:http://highlightjs.readthedocs.org/en/latest/css-classes-reference.html下载:https://highlightjs.org/download/首页添加loading效果themes\spfk\layout\index.ejs123456789101112131415<link rel="stylesheet" href="css/loading-style.css"><div id="loader-wrapper"> <div id="loader"></div></div><%- partial('_partial/archive', {pagination: 2, index: true}) %><!-- loading --><script>window.jQuery || document.write('<script src="js/jquery-1.9.1.min.js"><\/script>')</script><script type="text/javascript"> $(window).load(function() { // makes sure the whole site is loaded $('#loader').fadeOut(); // will first fade out the loading animation $('#loader-wrapper').delay(350).fadeOut('slow'); // will fade out the white DIV that covers the website. $('body').delay(350).css({'overflow-y':'visible'}); })</script>LoadingBar页面顶部加载进度条J:\Hexo\Hexo\themes\spfk\layout_partial\head.ejs12345<!-- 加载特效 --><% if(theme.animate) { %> <script src="/js/pace.js"></script><link href="/css/pace/pace-theme-flash.css" rel="stylesheet" /><% } %>highlight.js1234567891011121314151617J:\Hexo\Hexo\node_modules\hexo-renderer-marked\node_modules\hexo-util\lib\highlight.js: 37 } 38 39: result += '<figure class="highlight' + (data.language ? ' ' + data.language : '') + '"' + 'data-lang="' + (data.language ? ' ' + data.language : '') + '">'; 40 41 if (caption) {J:\Hexo\Hexo\node_modules\hexo-util\lib\highlight.js: 33 } 34 35: result += '<figure class="highlight' + (data.language ? ' ' + data.language : '') + '">'; 36 37 if (caption){6 matches across 2 files result += '<figure class="highlight' + (data.language ? ' ' + data.language : '') + '"' + 'data-lang="' + (data.language ? ' ' + data.language : '') + '">';Hexo插件Swiftype微搜索不蒜子百度统计CNZZ数据Font Awesome百度脑图ICON图标Font AwesomeFREE Icon MakerIcon Font在线icoIcoMoonDisqus多说评论QQ邮箱开放平台七牛云存储百度分享AddThis分享一个方法解决Facebook,Linkedin,Twitter,Google+等SNS平台太多更新不过来的问题。 - 米课问答GitCafeCoding.NetGitHub]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[使用GitHub搭建Hexo博客]]></title>
<url>%2F2015%2F12%2F27%2FGitHubHexo%2F</url>
<content type="text"><![CDATA[来到GitHub这么长时间,才开始真真的了解GitHub,这个国外的代码托管平台,充满着大牛的身影。国内也有不多少的代码托管平台,本文将就用GitHub的GitHub Pages 功能来搭建,我的个性博客,最近在学习JS后端Node.js, 现在火的不行, 异步IO的机制, 所以在学习过程中发现了hexo是由Node.js驱动的一款快速、简单且功能强大的博客框架。比起WordPress,hexo的搭建更加简洁,配合上markdown的使用,更加便捷的管理自己的学习文档。概况为什么选择GitHub Pages1、GitHub Pages有免费的代码托管空间,资料自己管理,保存可靠;2、学着用 GitHub,享受 GitHub 的便利,上面有很多大牛,眼界会开阔很多;3、顺便理解 GitHub 工作原理,最好的团队协作流程;4、GitHub建立私有仓库才会收费,所以会有很多开源代码。GitHub Pages是什么应用GitHub Pages创建属于自己的个人博客,GitHub将提供免费的空间。GitHub提供的域名(用户名+github+io),在Repository name对应处填写资源名,其需要使用自己的用户名,每个用户名下面只能建立一个,并且资源命名必须符合这样的规则username/username.github.io,之后勾选下面的”Initialize this repository with a README” 。hexo出自何人hexo出自台湾大学生 tommy351 之手,是一个基于Node.js的静态博客程序,其编译上百篇文字只需要几秒。hexo生成的静态网页可以直接放到GitHub Pages,BAE,SAE等平台上。安装准备环境搭建:Node.js:下载地址Git:下载地址Sublime:下载地址安装Node到 Node.js 官网下载相应平台的 最新版本 ,一路安装即可。我用的是 node-v0.10.22-x86.msi安装GitGit的客户端很多,我用的是 msysgit ,喜欢用绿色版本 Portable application for official Git for Windows 1.8.4 ,下载下来设置一下环境变量即可,Git_HOME,%Git_HOME%\bin之类的,不多说。安装SublimeSublime Text 2 在这里仅仅作为一个文本编辑器使用,支持各种编程语言和文件格式,当然也支持Markdown语法,实在是个不可多得的练码奇才。喜欢追鲜的也可以尝试处于beta版本的 Sublime Text 3 。GitHub注册与配置注册:访问:GitHub,注册你的username和邮箱,邮箱十分重要,GitHub上很多通知都是通过邮箱的。注册过程比较简单,详细也可以看:使用Github Page搭建博客, 需要遵循一定的规则, 需要在github建立仓库,仓库名为Github用户.github.io, 更多详情请参考官方文档配置和使用Github以下教程主要参考beiyuu的《使用Github Pages建独立博客》写成。配置SSH keys我们如何让本地git项目与远程的github建立联系呢?用SSH keys。打开Git Bash工具,执行以下操作检查SSH keys的设置123456789101112 首先我们需要检查你电脑上现有的ssh key:$ cd ~/. ssh 检查本机的ssh密钥 如果提示:No such file or directory 说明你是第一次使用git。 生成新的SSH Key:$ ssh-keygen -t rsa -C "邮件地址@youremail.com"Generating public/private rsa key pair.Enter file in which to save the key (/Users/your_user_directory/.ssh/id_rsa):<回车就好>注意1: 此处的邮箱地址,你可以输入自己的邮箱地址;注意2: 此处的「-C」的是大写的「C」然后系统会要你输入密码:Enter passphrase (empty for no passphrase):<输入加密串>Enter same passphrase again:<再次输入加密串>在回车中会提示你输入一个密码,这个密码会在你提交项目时使用,如果为空的话提交项目时则不用输入。这个设置是防止别人往你的项目里提交内容。注意:输入密码的时候没有*字样的,你直接输入就可以了。最后看到这样的界面,就成功设置ssh key了:12添加SSH Key到GitHub在本机设置SSH Key之后,需要添加到GitHub上,以完成SSH链接的设置。打开本地C:\Documents and Settings\Administrator.ssh\id_rsa.pub文件。此文件里面内容为刚才生成人密钥。如果看不到这个文件,你需要设置显示隐藏文件。准确的复制这个文件的内容,才能保证设置的成功。登陆github系统。点击右上角的 Account Settings—>SSH Public keys —> add another public keys把你本地生成的密钥复制到里面(key文本框中), 点击 add key 就ok了测试1234567891011121314151617181920212223242526 可以输入下面的命令,看看设置是否成功,[email protected]的部分不要修改:$ ssh -T [email protected] 如果是下面的反馈:The authenticity of host 'github.com (207.97.227.239)' can't be established.RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.Are you sure you want to continue connecting (yes/no)? 不要紧张,输入yes就好,然后会看到:Hi cnfeat! You've successfully authenticated, but GitHub does not provide shell access. 设置用户信息: 现在你已经可以通过SSH链接到GitHub了,还有一些个人信息需要完善的。 Git会根据用户的名字和邮箱来记录提交。 GitHub也是用这些信息来做权限的处理,输入下面的代码进行个人信息的设置,把名称和邮箱替换成你自己的,名字必须是你的真名,而不是GitHub的昵称。$ git config --global user.name "cnfeat"//用户名$ git config --global user.email "[email protected]"//填写自己的邮箱 SSH Key配置成功,本机已成功连接到github。Hexo博客HexoHexo的作者是tommy351,根据官方介绍,Hexo是一个简单、快速、强大的博客发布工具,支持Markdown格式。hexo的主题列表 Hexo Themes。 我比较喜欢 pacman , modernist 、 ishgo , raytaylorism 。安装Hexo打开Git Bash工具(前提确保Node.js已经安装,环境配置OK)$ npm install -g hexo注释:执行命令:npm install -g hexo,报错如下:12345678910111213141516171819202122232425262728293031npm ERR! Error: shasum check failed for C:\Users\ADMINI~1\AppData\Local\Temp\npm-30024-KDJHJzgP\registry.npmjs.org\hexo-cli\-\hexo-cli-0.1.6.tgznpm ERR! Expected: 7dc3ab939d0889c4bed6a961605ff3e2d67f67a2npm ERR! Actual: 41de7d67a9b764352eb07c49c32fc38dd7f479b9npm ERR! From: https://registry.npmjs.org/hexo-cli/-/hexo-cli-0.1.6.tgznpm ERR! at d:\Program Files\nodejs\node_modules\npm\node_modules\sha\index.js:38:8npm ERR! at ReadStream.<anonymous> (d:\Program Files\nodejs\node_modules\npm\node_modules\sha\index.js:85:7)npm ERR! at ReadStream.emit (events.js:117:20)npm ERR! at _stream_readable.js:943:16npm ERR! at process._tickCallback (node.js:419:13)npm ERR! If you need help, you may report this *entire* log,npm ERR! including the npm and node versions, at:npm ERR! <http://github.com/npm/npm/issues>npm ERR! System Windows_NT 6.2.9200npm ERR! command "d:\\Program Files\\nodejs\\node.exe" "d:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "-g" "hexo"npm ERR! cwd C:\Users\Administrator\Desktopnpm ERR! node -v v0.10.31npm ERR! npm -v 1.4.23npm ERR! registry error parsing jsonnpm ERR!npm ERR! Additional logging details can be found in:npm ERR! C:\Users\Administrator\Desktop\npm-debug.lognpm ERR! not ok code 0 莫非是因为被墙了?换国内镜像源试试。npm config set registry="http://registry.cnpmjs.org", 然后再次执行npm install -g hexo,成功!部署Hexo123456789101112131415161718192021 在我的电脑中建立一个名字叫「Hexo」的文件夹,然后在此文件夹中右键打开Git Bash。$ hexo init 如果无法使用右击“Git Bash”,则可以切换到指定目录 UUhike@UUhike-pc MINGW64 ~$ cd j:/github/hexo UUhike@UUhike-pc MINGW64 /j/github/hexo 安装依赖包$ npm install Hexo随后会自动在目标文件夹建立网站所需要的所有文件。 现在我们已经搭建起本地的hexo博客了,执行以下命令(在H:\hexo),然后到浏览器输入localhost:4000看看。 本地查看$ hexo generate #生成静态页面至public目录(最终上传这个文件到GitHub)$ hexo server #开启预览访问端口(默认端口4000,'ctrl + c'关闭server)部署到GitHub123456789编辑E:\hexo下的_config.yml,修改Deployment部分:# Deployment## Docs: http://hexo.io/docs/deployment.htmldeploy: type: git repository: https://github.com/luuman/luuman.github.io.git branch: master注释:hexo d,执行该命令,报错:1234567891011121314151617181920212223242526272829303132333435ERROR Deployer not found: git执行命令:npm install hexo-deployer-git --save再次执行hexo d,报错:INFO Deploying: gitINFO Clearing .deploy folder...INFO Copying files from public folder...warning: LF will be replaced by CRLF in 2015/05/30/hello-world/index.html.The file will have its original line endings in your working directory.......*** Please tell me who you are.Run git config --global user.email "[email protected]" git config --global user.name "Your Name"to set your account's default identity.Omit --global to set the identity only in this repository.fatal: unable to auto-detect email address (got 'Administrator@PC-201505290750.(none)')Username for 'https://github.com': voidkingPassword for 'https://[email protected]':error: src refspec master does not match any.error: failed to push some refs to 'https://github.com/voidking/voidking.github.io.git'FATAL Something's wrong. Maybe you can find the solution here: http://hexo.io/docs/troubleshooting.htmlError: error: src refspec master does not match any.error: failed to push some refs to 'https://github.com/voidking/voidking.github.io.git' at ChildProcess.<anonymous> (E:\hexo\node_modules\hexo-deployer-git\node_modules\hexo-util\lib\spawn.js:42:17) at ChildProcess.emit (events.js:98:17) at maybeClose (child_process.js:756:16) at Process.ChildProcess._handle.onexit (child_process.js:823:5)hexo d,执行该命令,报错:复制cnfeat的主题以下进入复制主题环节,如果那一步出现问题,或者修改后没有显示修改的结果,建议来来一个,再看看,可以解决很多问题。12345678910111213$ hexo clean$ hexo generate #生成静态页面至public目录(最终上传这个文件到GitHub)$ hexo server #开启预览访问端口(默认端口4000,'ctrl + c'关闭server)建立了Hexo文件,复制我的主题了到themes文件夹中yilia$ git clone https://github.com/litten/hexo-theme-yilia.git themes/yiliamodernist$ git clone https://github.com/heroicyang/hexo-theme-modernist.git themes/modernistjacman$ git clone https://github.com/cnfeat/cnfeat.git themes/jacman启用cnfeat的主题修改Hexo目录下的config.yml配置文件中的theme属性,将其设置为jacman。同时请设置stylus属性中的compress值为true。theme: jacman注意:Hexo有两个config.yml文件,一个在根目录,一个在theme下,此时修改的是在根目录下的。更新主题 $ cd themes/jacman $ git pull注意:为避免出错,请先备份你的_config.yml 文件后再升级本地查看调试1234567891011121314$ hexo g #生成$ hexo s #启动本地服务,进行文章预览调试或者直接作用组合命令$ hexo deploy -g$ hexo server -g简写:hexo n == hexo newhexo g == hexo generatehexo s == hexo serverhexo d == hexo deploy4、浏览器中查看效果浏览器输入http://localhost:4000 ,查看搭建效果。此后的每次变更_config.yml文件或者上传文件都可以先用此命令调试,非常好用,尤其是当你想调试出自己想要的主题时。#进阶篇:Hexo设置网站搭建完成后,就可以根据自己爱好来对Hexo生成的网站进行设置了,对整站的设置,只要修改项目目录的hexo/_config.yml就可以了,这是我的设置,可供参考。默认目录结构:1234567891011.├── .deploy├── public├── scaffolds├── scripts├── source| ├── _drafts| └── _posts├── themes├── _config.yml└── package.jsonhexo/_config.yml12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485# Hexo Configuration## Docs: http://hexo.io/docs/configuration.html## Source: https://github.com/hexojs/hexo/# Site #整站的基本信息title: 1000 words a Day #网站标题subtitle: Writing 1000 Words a Day Changes My Life #网站副标题description: 学习总结 思考感悟 知识管理 #网站描述author: cnFeat #网站作者,在下方显示email: [email protected] #联系邮箱language: zh-CN #主题实际的文件名称timezone:# URL #这项暂不配置,绑定域名后,欲创建sitemap.xml需要配置该项## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'url: http://yoursite.comroot: /permalink: :year/:month/:day/:title/permalink_defaults:# Directorysource_dir: sourcepublic_dir: publictag_dir: tagsarchive_dir: archivescategory_dir: categoriescode_dir: downloads/codei18n_dir: :langskip_render:# Writing 文章布局、写作格式的定义,不修改new_post_name: :title.md # File name of new postsdefault_layout: posttitlecase: false # Transform title into titlecaseexternal_link: true # Open external links in new tabfilename_case: 0render_drafts: falsepost_asset_folder: falserelative_link: falsefuture: truehighlight: enable: true line_number: true auto_detect: true tab_replace:# Category & Tagdefault_category: uncategorizedcategory_map:tag_map:# Date / Time format 日期格式,不修改## Hexo uses Moment.js to parse and display date## You can customize the date format as defined in## http://momentjs.com/docs/#/displaying/format/date_format: YYYY-MM-DDtime_format: HH:mm:ss# Pagination 每页显示文章数,可以自定义,我将10改成了5## Set per_page to 0 to disable paginationper_page: 5pagination_dir: page# Disqus Disqus插件,我们会替换成“多说”,不修改disqus_shortname:# Extensions## Plugins: http://hexo.io/plugins/## Themes: http://hexo.io/themes/theme: spfk# 自动生成sitemapsitemap:path: sitemap.xmlbaidusitemap:path: baidusitemap.xml# Deployment 站点部署到github要配置,上一节中已经讲过## Docs: http://zespia.tw/hexo/docs/deploy.htmldeploy: type: git repository: [email protected]:luuman/luuman.github.io.git branch: master修改局部页面页面展现的全部逻辑都在每个主题中控制,源代码在hexo\themes\主题名称\中:hexo\themes\1234567891011121314151617├── languages #多语言| ├── default.yml#默认语言| └── zh-CN.yml #中文语言├── layout #布局,根目录下的*.ejs文件是对主页,分页,存档等的控制| ├── _partial #局部的布局,此目录下的*.ejs是对头尾等局部的控制| └── _widget#小挂件的布局,页面下方小挂件的控制├── source #源码| ├── css#css源码 | | ├── _base #*.styl基础css| | ├── _partial #*.styl局部css| | ├── fonts #字体| | ├── images #图片| | └── style.styl #*.styl引入需要的css源码| ├── fancybox #fancybox效果源码| └── js #javascript源代码├── _config.yml#主题配置文件└── README.md #用GitHub的都知道主题文档的配置hexo\themes/_config.yml123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657# Headermenu: 主页: / 所有文章: /archives # 随笔: /tags/随笔# SubNavsubnav: github: "#" weibo: "#" rss: "#" zhihu: "#" #douban: "#" #mail: "#" #facebook: "#" #google: "#" #twitter: "#" #linkedin: "#"rss: /atom.xml# Contentexcerpt_link: morefancybox: truemathjax: true# Miscellaneousgoogle_analytics: ''favicon: /favicon.png#你的头像urlavatar: ""#是否开启分享share: true#是否开启多说评论,填写你在多说申请的项目名称 duoshuo: duoshuo-key(http://duoshuo-key.duoshuo.com/)#若使用disqus,请在博客config文件中填写disqus_shortname,并关闭多说评论duoshuo: true#是否开启云标签tagcloud: true#是否开启友情链接#不开启——#friends: false#开启——friends: 奥巴马的博客: http://localhost:4000/ 卡卡的美丽传说: http://localhost:4000/ 本泽马的博客: http://localhost:4000/ 吉格斯的博客: http://localhost:4000/ 习大大大不同: http://localhost:4000/ 托蒂的博客: http://localhost:4000/#是否开启“关于我”。#不开启——#aboutme: false#开启——aboutme: 我是谁,我从哪里来,我到哪里去?我就是我,是颜色不一样的吃货…参考资料:hexo你的博客如何搭建一个独立博客——简明Github Pages与Hexo教程Hexo的使用介绍Hexo插件安装]]></content>
<categories>
<category>Hexo</category>
</categories>
<tags>
<tag>Hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[web前端职业规划]]></title>
<url>%2F2015%2F12%2F26%2FnewWeb%2F</url>
<content type="text"><![CDATA[** 自用笔记:**关于一个WEB前端的职业规划,其实是有各种的答案,没有哪种答案是完全正确的,全凭自己的选择,只要是自己选定了,坚持去认真走,就好。在这里,我只是简要说一下自己对于这块儿内容的理解。有一个观点想要分享给大家的是:任何规划和目标的实现都依赖于知识的积累,而知识的积累来源于学习及学习后大量的实践。我提供一个实践途径,我们可以在工作之余的时间在网上或外包公司那里接一些私单做,因为目标不是赚钱,我们可以用最低的价格来提升自身竞争力,获得大量订单就意味着获得大量的实践机会,同时,还有一些收入作为工作成就感之外的安慰奖,还是不错的。职业方向定位首先,只有确定好自己的职业方向,才能做好职业规划。在我看来,做WEB前端技术能够找到的职业方向有以下几种:资深WEB前端工程师这个方向算是一个WEB前端最基本的选择了,在国外,很多老外都能够把自己的专业做到极致,能一辈子就在一个专业领域不断学习和积累。主要在于内因和外因两方面,内因是老外通常思想比较简单直接,容易一直专注于一个领域;外因是国外的环境很好,能够良好的支撑这样的职业发展道路。反观国内,从内因来讲,WEB前端技术人员还是蛮浮躁的,通常会因为WEB前端知识的更新速度太快而觉得学习起来辛苦,最终转向后台或其他道路。从外因来讲,WEB前端人员没有获得公平的待遇,可能从HTML页面制作就开始并沿袭下来的,从来WEB前端人员都比后端人员低一等,貌似前端就是“浅显”的代名词、后端就是“深奥”的代名词,这也直接造就了前端人员的收入无法和后端人员媲美,同时直接影响到前端人才市场的活跃程度。另一方面,前端的技术入门较容易,造成另一个极端情况:人员泛滥、人才稀缺。我想对所有的WEB前端工程师说:面包总会有的,要耐得住寂寞!我个人比较推荐这个职业发展方向,因为,在这个方向下,只要足够耐心、厚积薄发,成功的概率是非常高的。同时,这是一条最单纯的路,我们更多的是花费精力在技术的钻研上,而不是办公室政治等其它琐事。资深WEB架构师说功利点儿,我喜欢这个方向,既兼顾了工作的单纯性、又能够减少实际Coding的工作量能腾出更多时间钻研技术。在国内,WEB前端工程师遇到较多的情况是总是反复编写着同样的代码,总是面对着同样的技术和产品,容易感觉枯燥。由于我们拥有最为广泛的WEB相关知识沉淀,使得我们更加容易成为一名架构师。这个职业发展方向不如第一种来得平滑,主要是作为一名架构师不得不学习:后端技术、DBA、Platform等内容,而这种学习通常需要实际操刀做项目,不是自己在家里写两个Demo就好的,这就势必会遭遇一段时间的阵痛期。虽然不是很平滑,但是,对于一个大局观好、悟性好、知识面广的前端工程师,我推荐你们努把力,走一条光荣的架构师之路吧。自己创业其实,自己创业是最好的道路、也是成功率最低的道路,挑战和机遇并存。这里,作为一个前端技术人员,需要将自己的视野更多放在行业的动态、产业链的动态、相关产品领域的动态,把关注细节的优势继续保持,同时,增强自己把控一个产品乃至一个公司命运的能力。但是,这条道路和技术之路稍有分歧,后续将不再赘述。转岗管理或其他由于这条职业道路和WEB前端技术之路关系不大,故而,这里不做过多讨论,但是,无论是否走上这条道路,我觉得对于任何技术之路,更好的大局观、更广泛的视野是良好发展的必备条件,拥有良好的大局观和更广泛的视野别无他法,只能不断的进行知识的横向拓展和积累,同时,多在横向拓展知识的时候进行实践,把知识变成技能。职业发展目标我都有一个最终的目标,在这个目标之上,我们需要给自己制定一系列学习和成长计划,制定的方法如下:梳理知识架构;梳理知识架构的目的在于,我们要了解清楚,哪些技术是前置、哪些技术是后继,那些技术是深度、哪些技术是广度,按照这两个维度梳理好知识架构之后,我们才能准确地制定清晰的成长目标、高效的成长计划。分解目标;我认为,大抵可分解为三个阶段,包括:起步阶段、提升阶段、成型阶段。这三个阶段分别对应着不同的目标:起步阶段:基本知识的掌握在我们梳理的知识架构中,按照我们分析的两个维度里最前置的、最浅显的部分,作为打基础的阶段,必须要在这个过程中更多投入到实践中去,我们通常做的多了、熟练了,就认为这部分知识和内容掌握了。常用工具的掌握对于常用工具的掌握应该掌握一些有大公司或专业团队背景的流行工具,这些工具的熟练掌握能够提升专业度、职业度,同时,能提升我们的工作效率。我们只有在检验自己对于知识和技能熟练程度的时候,才会自虐式的用Notepad去编写页面、css和脚本等内容。沟通技巧的掌握通常做技术的人会被定位为“不善沟通”的人,这是为什么呢?究其原因,主要是因为多跟程序和代码打交道,跟人的沟通较少导致。这种时候我们要特别注意增加和人沟通的机会,着重提升这块儿的能力。另一方面,我们通常被称为“不懂沟通技巧”的人。作为一个技术人员,包括我自己,似乎天生就有一些难以接受挑战的缺陷。在国内,我们的技术人员通常都是自己制定方案、自己执行方案,在执行过程中又缺乏相关产品、交互设计等人员的沟通,大多是在自己的思路贯彻下进行开发,久而久之,我们习惯于信任自己的观点、在自己的视角看问题,对于挑战总是百般地“据理”力争。我们需要更多提升的是,如何在对方的视角看问题、如何在用户的视角看问题。良好的开发习惯开发习惯是养成的,一旦有不好的习惯,对于将来去修正带来的将是很大的麻烦,我们在培养良好开发习惯一定要从起步时做起,例如:写代码之前先分析、先写文档、先写注释。定义变量最好能用直接可理解的语义,最好是拼音,别整英文,尤其是生僻单词,将来自己忘了还要开金山词霸。文件最好有有意义的文件夹命名来管理,文件名最好有意义,需要版本号的最好能和项目版本号一同更新……等等。提升阶段:高级技术的掌握在提升阶段对于知识和技能掌握,我们需要从梳理好的知识架构中选择更深一层次的技术进行学习,选择之前,我们先通过类比或预估的方法,衡量自身学习的难点,以学习难点和自己最不感兴趣的部分为主。这样推荐大家的原因是:这个阶段我们兴趣正浓,已经度过了苦涩的起步阶段,到达了兴奋的提升阶段,我们要用兴趣和兴奋去挑战最困难的部分,在我们信心受挫和兴趣浓厚之中找到平衡。同时,辅以其他的深层次知识一起学习和研究。产品思想的学习没有正确的产品思想,很难设计出良好的程序,无论从界面、交互,还是接口、逻辑,不能够理解产品、理解用户需求,我们会给自己造成很大的麻烦,例如:我们千辛万苦用最新技术、最复杂的实现做出的功能,却得不到使用者或领导、同事的认可。为了使我们的工作和学习更加有效率、避免无用功,我们需要不断的学习产品的思想,只有理解了产品的思路,我们才知道用我们的技术去输出什么。各种框架的学习框架是我们提高工作效率的优秀手段,对于框架的学习是成长必经之路。我们学习框架的路线通常应该是:使用——》分析——》个性化定制——》模仿编写自己的框架。只有大量的使用,才能明白设计框架者在设计背后的思路,只有了解到设计的思路,才能做正确全面的分析,只有正确全面的分析才能支撑我们去对其裁剪或扩展,只有经过实际分析、修改别人的框架,才有可能写出优秀的、自己的框架。学习通常的路线是:学习、理解、模仿、创造。富客户端应用的学习随着带宽和计算机性能的提升,以及WEB2.0的如火如荼,富客户端应用充斥着互联网,如果你不懂得富客户端应用,你就不能称之为一个合格的前端技术人员。可以按照:Flash动画——》Flash编程——》Flex——》——》Air——》Silverlight动画——》Silverlight编程的步骤学习,先学Flash后学Siverlight的原因,一来Silverlight还不太成熟,二来,实际Silverlight借鉴了很多 Flash的思想,最好在学习的时候不要本末倒置。各种网络协议的学习WEB前端技术就是云上的技术,云的协议有N种,我们应该着重学习:TCP/IP,UDP,HTTP,POP3,SMTP这几种协议,在开发WEB前端应用过程中,这些协议是我们的技术的载体,有时候决定了我们的应用是否能实现、有时候决定了我们的应用是否高性能,同时,这些协议还是我们和后端技术交互的重要手段,这些协议就像是密码字典,帮助我们把后端传输过来的密文解释成我们前端技术能够理解的明文。程序设计这个阶段我们需要学习OO、UML、设计模式、设计方法……,我们要让技术开发工作变成有目的性、有计划性,并且,这些目的和计划必须有理论的支持,这样,我们设计出来的程序才能够更优秀、我们的开发才更有效率,这样,我们的技术才能有所提升。为什么要学习程序设计呢?主要是,就算我们不用Flash的 ActionScript编写程序的前端逻辑,我们至少要把我们自己的Javascript函数、包的定义规划起来,避免将来自己或他人维护代码的时候出现问题。程序设计能力,在技术人员仍然被看作是程序员的这个年代,是灰常、灰常重要滴。成型阶段:到了这个阶段,我也没什么好说的了,如果能达到这个阶段,就证明后续的成长之路是异彩纷呈的,是成为一个资深WEB前端工程师,还是成为一个资深WEB架构师,亦或其他,都要具体分析自身的特点和兴趣所在。如果是资深的前端工程师,我觉得更重要的是去作新技术的研究,互联网技术发展速度日新月异,不断学习新技术,否则就被淘汰。此外,我建议在知识的广度、深度方面最好能挑选一个自己最擅长和最感兴趣的一两个领域深入钻研,不要挑太多,多而不精。如果是资深的WEB架构师之路,我建议要深入了解后台技术,这种深入了解一定要伴随着实际的项目开发,基本方法是:按照别人设计的架构实现几个Server——》自己设计并实现几个Server。来自于:]]></content>
<categories>
<category>Interview</category>
</categories>
<tags>
<tag>FrontPlan</tag>
</tags>
</entry>
<entry>
<title><![CDATA[电脑优化相关备份]]></title>
<url>%2F2015%2F12%2F26%2Fwin7Set%2F</url>
<content type="text"><![CDATA[** 自用笔记:**本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Whywindows系统装机必备软件把这个清单写下来,每次重装系统都可以按图索骥基本win7 64 sp3 操作系统 搜狗输入法 Microsoft Office 2010 qq 微信 360压缩 Abobe Reader Abobe Flash Player ADSafe 迅雷看看 photoshop cc 2015 360网盘 百度云网盘 有道词典前端开发firefox+firebug 浏览器 chrome + Proxy SwitchySharp 浏览器 sublime text(代码编辑器) Fiddler2 驱动LenovoDM(联想驱动) 魔方(优化美化) 驱动精灵万能网卡版工具8UFTP foxmail KeePass 密码管理工具 gow 命令行增强 everything 文件名搜索 SecureCRT ssh登录管理工具 MarkdownPad 写文档专用编辑器 .net framework 4.0 系统包工具XSkyWalker(外网浏览器) WVS网站扫描工具笔记本美化安装前准备1、应用软件:魔方2、素材:登陆界面背景、系统壁纸、系统主题、开机动画、开机关机铃声开机关机铃* 海贼王DEAR FRIEND 海贼王OST回忆 海贼王进行曲 海贼王圣诞歌 * 海贼王我当定了开机动画S.H.I.E.L.D activity(系统自带)如何设置 Windows 7 的休息提醒?直接使用cmd命令shutdown -s -t 7200,两个小时候右下方会提示将要关机,如果你还想继续玩,可以取消!USB ICON一、安装前准备U盘、电脑、ICON.ico(U盘图标)、autorun.inf(ICON)、desktop.inf(Bg)、background.jpg(背景图片)、1.bat(显示文件)、2.bat(隐藏文件)将文件存放在,U盘的根目录下即可,双击“2.bat”隐藏文件。autorun.inf[autorun] ICON=ICON.icodesktop.inf[ExtShellFolderViews] [{BE098140-A513-11D0-A3A4-00C04FD706EC}] InfoTip=hello IconArea_Image=background.jpg1.bat@echo off attrib ../desktop.ini +r +a +s +h attrib ../background.jpg +r +a +s +h attrib ../autorun.inf +r +a +s +h attrib ../ICON.ico +r +a +s +h2.bat@echo off attrib ../desktop.ini -r -a -s -h attrib ../background.jpg -r -a -s -h attrib ../autorun.inf -r -a -s -h attrib ../ICON.ico -r -a -s -hwin7开机动画DIY自己在做的时候没要找到一个完善的教程所以在此写一个,所有经验都来自互联网,我只是系统的整理一下。BY:zby1、首先制作FLASH,注意开机动画格式为【200像素X200像素】共【105】帧且前【60】帧为一次性播放后【45】帧为重复播放注:下面是我自己做的flash,保存的GIF动画2、flash制作完成后,影片导出时选择PNG序列格式,就得到了105张图片了。注:记得选择【完整文档大小】3、之后将105张图片在PS中合并,由于PS一次仅支持100张所以要分开合并。第一段5张,第二段100张。注:合并时请耐心等待,两次合并的初始文档大小分别为(1)宽【200像素X1000像素】(2)【200像素X20000像素】4、将得到的两段图片拼合,并保存为BMP格式即可注:最终文档大小为【200像素X21000像素】5、最后使用软媒魔方中的美化大师,将得到的BMP更改为新的开机动画即可END注意事项ps自动合并间距输入0.001即可得到0。如果想换回去,记得备份。如果想要将视频设置为开机动画可参考此处http://tieba.baidu.com/p/3139701776以上软件为CC 2014版,PS3已经有合并功能nkx2G��Ҟyg�PS CC 2015安装安装前准备,下载:Photoshop_16_LS20_win64、Adobe破解补丁等。安装PS,点击Setup进行安装。安装时需要账号,选择使用512@,Qq如链接失效 请自行搜索下载Adobe Photoshop CC 2014安装包及破解补丁64位下载 http://pan.baidu.com/s/1eQtNLRkAdobe Photoshop CC 2014安装包及破解补丁32位下载 http://pan.baidu.com/s/1dGW5w1、下载以上对应系统的安装包及破解补丁(教程以64位为例) 解压压缩文件得一个文件夹 右键“以管理员方式运行”里面的“Set-up”2、可能出现以下情况 不用管 点击“忽略”接下来点击“试用”3、接下来先不急着操作下一步 打开360流量防火墙找到“PDapp.exe”这个程序 右键“禁止访问网络”(其他安全软件也有类似功能,实在不行拔网线,简单粗暴)4、接下来就可以点击“登录”了 什么?没有网! 第三步的目的达到 “以后再说”5、接下来就是人人都会的了 “接受”即可 然后选择你要的安装路径 “安装”6安装时间几分钟左右 值得注意的是安装完毕后先不要打开 点击“关闭”7、复制破解补丁“amtlib.dll”粘贴至PS CC 2014安装目录下 选择“替换”8、打开软件 还有个协议 点击“接受”即可 请尽情使用吧插件:安装cuttermanC:\Users\UUhike\AppData\Roaming\Adobe\CEP\extensions插件安装的文件地址。]]></content>
<categories>
<category>Skill</category>
</categories>
<tags>
<tag>window 7</tag>
</tags>
</entry>
<entry>
<title><![CDATA[CSS小技巧收藏]]></title>
<url>%2F2015%2F12%2F25%2FCssTips%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyCSS动画以下是我积累的一些常用的css代码,会不断更新,最新的代码会显示在最前面,同时我也会提供最新更新日期以便查阅。居中对齐很多时候我们需要把一个元素在其父级容器里水平、垂直居中对齐。以下我列出了常用的几种方法:1.在知道子元素宽度与高度的情况下进行居中,采用位置定位:absolute + margin1234567891011.parent { position: relative;}.child { position: absolute; width: 100px; height: 60px; top: 50%; left: 50%; margin: -30px 0 0 -50px;}2.在不知道子元素高与宽的情况下,采用位置定位:absolute + transform.parent {position: relative;}.child {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);}3.采用flexbox进行居中对齐.parent {display: flex;justify-content: center;align-items: center;}.child {}选择某范围内的子元素选择5-10的子元素ul li:nth-child(n+5):nth-child(-n+10) {background-color: red;}最佳适应图片这段代码非常适用于给文章列表加缩略图的时候用,能最好的避免图片比例不协调的问题,统一排版。你可以随意更改width与height来查看效果。.thumbnail {width: 200px;height: 150px;background-image: url(“https://s.yimg.com/uy/build/images/sohp/inspiration/sage3.jpg");background-position: center;background-repeat: no-repeat;background-size: cover;}占满全屏.fullScreen {width: 100vw;height: 100vh;}演示效果:http://lab.liuxinyu.me/fullbg/index.html自动分章节文章正文里我们经常采用,,,这样的标签来分章,分节。这是一个非常不错的习惯,但常常只有字体粗细大小的不同,在这里我们为每个章节加上1,2,3这样的标注。以下代码在.document容器内有效。(其他需要计数的模块也可以用这样的方法)自适应视频播放器当在你自己的网站插入优酷这样的视频播放器后你会发现它的高宽都是固定的,而且你在用手机浏览的时候视频播放器还变形了,以下代码自动让播放器按16:9的比例显示并自适应各个设备。CSS代码:.media-wrap {position: relative;width: 100%;height: 0;padding-bottom: 56.25%;}.media-wrap iframe,.media-wrap embed,.media-wrap object {position: absolute;top: 0;left: 0;width: 100%;height: 100%;}HTML代码:]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[响应式布局]]></title>
<url>%2F2015%2F12%2F25%2Fmedia%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why响应式布局响应式布局麻烦之处就是每个尺寸的都要进行css定义,这个真的不是一般的蛋疼,下面有搜集到的各种尺寸css Media Query内容,搜集来源:media-queries-for-standard-devices好东西哦。看了之后是不是非常之蛋疼呢,那么只有使用工具来写这些玩意儿了,俺用得最爽的就是 stylus ,真的爽yy了,如果 stylus 不会玩耍请看这里 stylus入门使用方法stylus// Media queriesmq-mobile = “screen and (max-width: 479px)”mq-tablet = “screen and (min-width: 480px) and (max-width: 767px)”mq-iPhones4 = “only screen and (min-device-width: 320px) and (max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2)”mq-normal = “screen and (min-width: 768px)”.page-numberdisplay: inline-block@media mq-mobiledisplay: none@media mq-tabletcolor:red@media mq-iPhones4font-size:12px@media mq-normalbackground:yellow编译成.page-number { display: inline-block;}@media screen and (max-width: 479px) {.page-number { display: none; }}@media screen and (min-width: 480px) and (max-width: 767px) {.page-number { color: #f00; }}@media only screen and (min-device-width: 320px) and (max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2) {.page-number { font-size: 12px; }}@media screen and (min-width: 768px) {.page-number { background: #ff0; }}Phones and HandheldsiPhones/* ———– iPhone 4 and 4S ———– *//* Portrait and Landscape */@media only screen and (min-device-width: 320px) and (max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2) {}/* Portrait */@media only screen and (min-device-width: 320px) and (max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2) and (orientation: portrait) {}/* Landscape */@media only screen and (min-device-width: 320px) and (max-device-width: 480px) and (-webkit-min-device-pixel-ratio: 2) and (orientation: landscape) {}/* ———– iPhone 5 and 5S ———– *//* Portrait and Landscape */@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (-webkit-min-device-pixel-ratio: 2) {}/* Portrait */@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (-webkit-min-device-pixel-ratio: 2) and (orientation: portrait) {}/* Landscape */@media only screen and (min-device-width: 320px) and (max-device-width: 568px) and (-webkit-min-device-pixel-ratio: 2) and (orientation: landscape) {}/* ———– iPhone 6 ———– *//* Portrait and Landscape */@media only screen and (min-device-width: 375px) and (max-device-width: 667px) and (-webkit-min-device-pixel-ratio: 2) {}/* Portrait */@media only screen and (min-device-width: 375px) and (max-device-width: 667px) and (-webkit-min-device-pixel-ratio: 2) and (orientation: portrait) {}/* Landscape */@media only screen and (min-device-width: 375px) and (max-device-width: 667px) and (-webkit-min-device-pixel-ratio: 2) and (orientation: landscape) {}/* ———– iPhone 6+ ———– *//* Portrait and Landscape */@media only screen and (min-device-width: 414px) and (max-device-width: 736px) and (-webkit-min-device-pixel-ratio: 3) {}/* Portrait */@media only screen and (min-device-width: 414px) and (max-device-width: 736px) and (-webkit-min-device-pixel-ratio: 3) and (orientation: portrait) {}/* Landscape */@media only screen and (min-device-width: 414px) and (max-device-width: 736px) and (-webkit-min-device-pixel-ratio: 3) and (orientation: landscape) {}Galaxy Phones/* ———– Galaxy S3 ———– *//* Portrait and Landscape */@media screen and (device-width: 320px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 2) {}/* Portrait */@media screen and (device-width: 320px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait) {}/* Landscape */@media screen and (device-width: 320px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape) {}/* ———– Galaxy S4 ———– *//* Portrait and Landscape */@media screen and (device-width: 320px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) {}/* Portrait */@media screen and (device-width: 320px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait) {}/* Landscape */@media screen and (device-width: 320px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape) {}/* ———– Galaxy S5 ———– *//* Portrait and Landscape */@media screen and (device-width: 360px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) {}/* Portrait */@media screen and (device-width: 360px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait) {}/* Landscape */@media screen and (device-width: 360px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape) {}HTC Phones/* ———– HTC One ———– *//* Portrait and Landscape */@media screen and (device-width: 360px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) {}/* Portrait */@media screen and (device-width: 360px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait) {}/* Landscape */@media screen and (device-width: 360px) and (device-height: 640px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape) {}TabletsiPads/* ———– iPad mini ———– *//* Portrait and Landscape */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (-webkit-min-device-pixel-ratio: 1) {}/* Portrait */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: portrait) and (-webkit-min-device-pixel-ratio: 1) {}/* Landscape */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: landscape) and (-webkit-min-device-pixel-ratio: 1) {}/* ———– iPad 1 and 2 ———– // Portrait and Landscape */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (-webkit-min-device-pixel-ratio: 1) {}/* Portrait */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: portrait) and (-webkit-min-device-pixel-ratio: 1) {}/* Landscape */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: landscape) and (-webkit-min-device-pixel-ratio: 1) {}/* ———– iPad 3 and 4 ———– // Portrait and Landscape */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (-webkit-min-device-pixel-ratio: 2) {}/* Portrait */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: portrait) and (-webkit-min-device-pixel-ratio: 2) {}/* Landscape */@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: landscape) and (-webkit-min-device-pixel-ratio: 2) {}Galaxy Tablets/* ———– Galaxy Tab 10.1 ———– *//* Portrait and Landscape */@media (min-device-width: 800px) and (max-device-width: 1280px) {}/* Portrait */@media (max-device-width: 800px) and (orientation: portrait) {}/* Landscape */@media (max-device-width: 1280px) and (orientation: landscape) {}Nexus Tablets/* ———– Asus Nexus 7 ———– *//* Portrait and Landscape */@media screen and (device-width: 601px) and (device-height: 906px) and (-webkit-min-device-pixel-ratio: 1.331) and (-webkit-max-device-pixel-ratio: 1.332) {}/* Portrait */@media screen and (device-width: 601px) and (device-height: 906px) and (-webkit-min-device-pixel-ratio: 1.331) and (-webkit-max-device-pixel-ratio: 1.332) and (orientation: portrait) {}/* Landscape */@media screen and (device-width: 601px) and (device-height: 906px) and (-webkit-min-device-pixel-ratio: 1.331) and (-webkit-max-device-pixel-ratio: 1.332) and (orientation: landscape) {}Kindle Fire/* ———– Kindle Fire HD 7” ———– *//* Portrait and Landscape */@media only screen and (min-device-width: 800px) and (max-device-width: 1280px) and (-webkit-min-device-pixel-ratio: 1.5) {}/* Portrait */@media only screen and (min-device-width: 800px) and (max-device-width: 1280px) and (-webkit-min-device-pixel-ratio: 1.5) and (orientation: portrait) {}/* Landscape */@media only screen and (min-device-width: 800px) and (max-device-width: 1280px) and (-webkit-min-device-pixel-ratio: 1.5) and (orientation: landscape) {}/* ———– Kindle Fire HD 8.9” ———– // Portrait and Landscape */@media only screen and (min-device-width: 1200px) and (max-device-width: 1600px) and (-webkit-min-device-pixel-ratio: 1.5) {}/* Portrait */@media only screen and (min-device-width: 1200px) and (max-device-width: 1600px) and (-webkit-min-device-pixel-ratio: 1.5) and (orientation: portrait) {}/* Landscape */@media only screen and (min-device-width: 1200px) and (max-device-width: 1600px) and (-webkit-min-device-pixel-ratio: 1.5) and (orientation: landscape) {}Laptops/* ———– Non-Retina Screens ———– /@media screen and (min-device-width: 1200px) and (max-device-width: 1600px) and (-webkit-min-device-pixel-ratio: 1) {}/ ———– Retina Screens ———– /@media screen and (min-device-width: 1200px) and (max-device-width: 1600px) and (-webkit-min-device-pixel-ratio: 2) and (min-resolution: 192dpi) {}WearablesApple Watch/ ———– Apple Watch ———– */@media (max-device-width: 42mm) and (min-device-width: 38mm) {}Moto 360 Watch/* ———– Moto 360 Watch ———– */@media (max-device-width: 218px) and (max-device-height: 281px) {}]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>HTML</tag>
</tags>
</entry>
<entry>
<title><![CDATA[CSS学习计划]]></title>
<url>%2F2015%2F12%2F25%2FCSS%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How WhyCSS动画transitionInternet Explorer 9 以及更早版本的浏览器不支持 transition 属性transition 属性是一个简写属性,用于设置四个过渡属性:transition-property 规定设置过渡效果的 CSS 属性的名称。transition-duration 规定完成过渡效果需要多少秒或毫秒。transition-timing-function 规定速度效果的速度曲线。transition-delay 定义过渡效果何时开始。123456789101112-webkit-transition-duration: 0.5s;transition-duration: 0.5s;transition: property duration timing-function delay;transition:width 2s;/* Firefox 4 */-moz-transition:width 2s; /* Safari and Chrome */-webkit-transition:width 2s; /* Opera */-o-transition:width 2s;input:focus, select, textarea {outline: none;}CSS12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455/*首字母大写*/text-transform:capitalize;/*属性允许您以确切的方式定义适应某个区域的具体内容*/box-sizing:border-box;/* Firefox */-moz-box-sizing:border-box;/* Safari */-webkit-box-sizing:border-box;/* 清除所有a标签在点击时出现的特效:*/a{-webkit-tap-highlight-color:rgba(255,0,0,0);}/*删除线*/text-decoration: line-through;/* 内容将在边界内换行 */word-wrap: break-word;iframe无法全屏显示,html,设置高度100%。CSS a标签,移动端显示方框.f-img-light-wrap { overflow: hidden; position: relative}.f-img-light-wrap:after { content: ''; height: 100%; width: 100px; transform: skewX(-25deg) translate3d(0,0,0); background: -moz-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,.3) 50%,rgba(255,255,255,0) 100%); background: -webkit-gradient(linear,left top,right top,color-stop(0%,rgba(255,255,255,0)),color-stop(50%,rgba(255,255,255,.3)),color-stop(100%,rgba(255,255,255,0))); background: -webkit-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,.3) 50%,rgba(255,255,255,0) 100%); background: -o-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,.3)50%,rgba(255,255,255,0) 100%); background: linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,.3) 50%,rgba(255,255,255,0) 100%); position: absolute; left: -160%; top: 0; z-index: 9}.f-img-light-wrap:hover:after { transition: left 1s ease-in-out; left: 160%}123456789101112<iframe src="http://sandbox.runjs.cn/show_square/587" allowtransparency="true" frameborder="0" scrolling="no" style=""></iframe>iframe内联框架<iframe src="http://sandbox.runjs.cn/show_square/611" allowtransparency="true" frameborder="0" scrolling="no" style=""></iframe>scrolling规定是否在 iframe 中显示滚动条。name规定 iframe 的名称。name="main"<a href="https://www.baidu.com/" target="main">评论管理1</a>动画transform2D定位translate1234567891011121314.div{ transform:translate(X,Y); 设置:XY轴的距离,12px,12%,-12px 常用浏览器兼容: /* Safari 和 Chrome */ -webkit-transform:translate(X,Y); /* Firefox */ -moz-transform:translate(X,Y); /* IE 360 */ -o-transform:translate(X,Y); /* Opera */ -ms-transform:translate(X,Y);}旋转rotate123.div{ transform:rotate(180deg);/* 180度 */}变化scale123.div{ transform:scale(1,2);/* 宽度、高度 */}倾斜skew123.div{ transform:skew(1,2);/* X轴角度、 Y轴角度*/}矩阵matrix123.div{ transform:matrix();/* */}3D旋转rotateX/rotateY123.div{ transform:rotateX(100deg);/* 100度 */}动画过渡效果transitionInternet Explorer 10、Firefox、Chrome 以及 Opera 支持 transition 属性。Safari 需要前缀 -webkit-。注释:Internet Explorer 9 以及更早的版本,不支持 transition 属性。注释:Chrome 25 以及更早的版本,需要前缀 -webkit-。1234567.div{ width: 100px; height: 100px; background-color: blue; transition: width transition-delay: 2s;/* 延时执行 */}动画效果animation浏览器兼容性:Internet Explorer 10、Firefox 以及 Opera 支持 @keyframes 规则和 animation 属性。Chrome 和 Safari 需要前缀 -webkit-。注释:Internet Explorer 9,以及更早的版本,不支持 @keyframe 规则或 animation 属性。创建规则动画:规定动画时间、规定动画名称12345678910111213141516171819202122232425.div{ animation: name 5s infinite alternate; /* infinite alternate */}@keyframes name{ 0%{ background-color:#FFF; } 25%{ background-color:#FFF; } 50%{ background-color:#FFF; } 100%{ background-color:#FFF; }}@keyframes myfirst{ from {background:red;} to {background:yellow;}}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354@keyframes 规定动画animation所有动画属性的简写属性,除了 animation-play-state 属性animation: name duration timing-function delay iteration-count direction;animation-name规定 @keyframes 动画的名称animation-duration规定动画完成一个周期所花费的秒或毫秒。默认是 0animation-timing-function规定动画的速度曲线。默认是 "ease" linear 动画从头到尾的速度是相同的 ease 默认。动画以低速开始,然后加快,在结束前变慢 ease-in 动画以低速开始 ease-out 动画以低速结束 ease-in-out 动画以低速开始和结束 cubic-bezier(n,n,n,n) 在 cubic-bezier 函数中自己的值。可能的值是从 0 到 1 的数值。steps(n,[ start | end ] ]?)这个阶梯函数,这个函数可以把动画平均划分为基本相等的,这个n是一个自然数,意思就是把一个动画平均分成n等分,直到平均地走完这个动画,这个要跟linear区别开来,因为linear是把动画作为一个整体,中间没有断点,而steps是把动画分段平均执行开来。step-start等同于steps(1,start),动画分成1步,动画执行时为开始左侧端点的部分为开始;step-end等同于steps(1,end):动画分成一步,动画执行时以结尾端点为开始,默认值为end。animation-delay规定动画何时开始。默认是 0数值animation-iteration-count规定动画被播放的次数。默认是 "1"数值、"infinite"无限次播放animation-direction规定动画是否在下一周期逆向地播放。默认是 "normal"正常播放、"alternate"动画应该轮流反向播放animation-play-state规定动画是否正在运行或暂停。默认是 "running"正在运行的动画、"paused"暂停动画animation-fill-mode规定对象动画时间之外的状态CSS多列123456column-count多列的个数column-gap每一列间隔距离column-rule每一列间隔线CSS选择器:last-child]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Markdown使用指南]]></title>
<url>%2F2015%2F12%2F24%2FSublimemarkdown%2F</url>
<content type="text"><[简书][1]![简书slogan][2][1]:链接地址 "描述"[2]:链接地址 "描述"[无链接的链接][null-link][null-link]: chrome://not-a-link效果预览:简书简书[无链接的链接][null-link][null-link]: chrome://not-a-link添加表格12345678910111213Markdown语法:| ABCD | EFGH | IJKL || -----|:----:| ----:|| a | b | c || d | e | f || g | h | i |ABCD | EFGH | IGKL-----|------|----a | b | cd | e | fg | h | i预览效果:ABCDEFGHIJKLabcdefghiABCDEFGHIGKLabcdefghi添加代码123456Markdown语法:`字符`(简短文字添加代码框)`Tab`或 四个空格(大段文字添加代码框,每行前添加)预览效果:字符(简短文字添加代码框)Tab或四个空格(大段文字添加代码框,每行前添加)引用12345678910111213141516171819Markdown语法:> 引用的文字> 引用的文字> 引用的文字---> 引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字---> 引用的文字引用的文字引用的文字引用的文字引用的文字--- >> 引言内的引言引言内的引言引言内的引言---> 引用的文字引用的文字引用的文字引用的文字引用的文字预览效果:引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引用的文字引言内的引言引言内的引言引言内的引言引用的文字引用的文字引用的文字引用的文字引用的文字单行长文字12345Markdown语法:在需要以单行长文字显示的文字两段各加三个`~`,即`~~~`在需要以单行长文字显示的文字段落前加四个空格预览显示:1单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字单行长文字首行缩进123456789101112131415Markdown语法: 缩进一个字符缩进一个字符缩进一个字符缩进一个字符缩进一个字符缩进一个字符 缩进两个字符缩进两个字符缩进两个字符缩进两个字符缩进两个字符缩进两个字符 缩进四个字符缩进四个字符缩进四个字符缩进四个字符缩进四个字符缩进四个字符预览效果: 缩进一个字符缩进一个字符缩进一个字符缩进一个字符缩进一个字符缩进一个字符 缩进两个字符缩进两个字符缩进两个字符缩进两个字符缩进两个字符缩进两个字符 缩进四个字符缩进四个字符缩进四个字符缩进四个字符缩进四个字符缩进四个字符添加脚注123Markdown语法:添加脚注预览效果:A 1创建链接1234为输入的URL或邮箱自动创建链接,如[email protected]。Markdown语法:<[email protected]>预览效果:test@domain.com转义字符12345678910111213141516在特殊字符,如*、[、>等前面加\可使特殊格式字符转换为正常字符打出(有序列表符号如1.,须在. 前加\)。Markdown语法:\\\`\*\_\{\}\[\]\(\)\#\+\-\.\!预览效果:\`*_{}[]()#+-.!小型文本123Markdown语法:<small>文本内容</small>预览效果:文本内容markdown代码语言12345678910111213141516171819202122ApacheBashCoffeeScriptC++C#CSSDiffHTTPIniJavaJavaScriptJSONMakefileMarkdownNginxObjective-CPerlPHPPythonRubySQLHTML, XML参考资料:在线编辑gitbook新手指南Markdown入门学习小结Markdown 简明教程Markdown語法說明(繁體中文版)Markdown 语法说明(简体中文版)维基百科:Markdown词条hexo你的博客如何搭建一个独立博客——简明Github Pages与Hexo教程简书:献给写作者的 Markdown 新手指南Lawrence Li:为什么作家应该用 Markdown 保存自己的文稿阳志平:「Markdown写作浅谈」Casa Nova:為什麼文科生也該用markdown寫作?Gnat:Markdown 简明教程Gnat:Markdown 写作规范参考Te_Lee:Markdown——入门指南怀瑾握瑜:Markdown语法纪要唐衣可俊:MarkDown使用小技巧温谦:怎样使用MarkdownLeo Chin :Markdown 11种基本语法Equation 85:Markdown语法示例Markdown 免费编辑器在线编辑器MaHuaDillinger.ioMarkable.inmarxi浏览器插件MaDeWindows 平台GitHub AtomMarkdownPadMarkPadLinux 平台ReTextMac 平台Mou高级应用(Sublime Text 2 + MarkdownEditing 教程)Sublime Text 2MarkdownEditing教程12345Title: Here is a titleA->B: Normal lineB-->C: Dashed lineC->>D: Open arrowD-->>A: Dashed open arrowCmd Markdown 简明语法手册]]></content>
<categories>
<category>Tool</category>
</categories>
<tags>
<tag>Markdown</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Sublime Text历练]]></title>
<url>%2F2015%2F12%2F21%2FSublimebest%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why编辑器的选择(Editor Choices)Sublime Text是一款跨平台代码编辑器(Code Editor),从最初的Sublime Text 1.0,到现在的Sublime Text 3.0,Sublime Text从一个不知名的编辑器演变到现在几乎是各平台首选的GUI编辑器。官网地址从初学编程到现在,我用过的编辑器有EditPlus、UltraEdit、Notepad++、Vim、TextMate和Sublime Text,如果让我从中推荐,我会毫不犹豫的推荐Vim和Sublime Text,原因有下面几点:跨平台:Vim和Sublime Text均为跨平台编辑器(在Linux、OS X和Windows下均可使用)。作为一个程序员,切换系统是常有的事情,为了减少重复学习,使用一个跨平台的编辑器是很有必要的。可扩展:Vim和Sublime Text都是可扩展的(Extensible),并包含大量实用插件,我们可以通过安装自己领域的插件来成倍提高工作效率。互补:Vim和Sublime Text分别是命令行环境(CLI)和图形界面环境(GUI)下的最佳选择,同时使用两者会大大提高工作效率。优点:自动保存代码,代码高亮、语法提示、自动完成且反应快速。少用鼠标,多用键盘。编辑器(Editor) vs 集成开发环境(Integrated Development Environment,下文简称IDE)我经常看到一些程序员拿编辑器和IDE进行比较,诸如Vim比Eclipse强大或是Visual Studio太慢不如Notepad++好使之类的讨论比比皆是,个人认为这些讨论没有意义,因为编辑器和IDE根本是面向两种不同使用场景的工具:编辑器面向无语义的纯文本,不涉及领域逻辑,因此速度快体积小,适合编写单独的配置文件和动态语言脚本(Shell、Python和Ruby等)。IDE面向有语义的代码,会涉及到大量领域逻辑,因此速度偏慢体积庞大,适合编写静态语言项目(Java、C++和C#等)。我认为应当使用正确的工具去做有价值的事情,并把效率最大化,所以我会用Eclipse编写Java项目,用Vim编写Shell,用Sublime Text编写JavaScript/HTML/Python,用Visual Studio编写C#。前言到此结束,下面进入正题。界面1、概况:从上到下:标题栏Title、菜单栏Menu、标签栏Tab、编辑区Editing Area、控制台Console、状态栏Status Bar。从做到右:侧边栏(可关闭、文件、文件夹视图)、编辑区(代码编辑)、MiniMap(缩略图)。菜单栏:各种命令,各种设置。文件File:编辑Edit:选择Selection:查找Find:视图View:转到Goto:工具Tools:项目Project:首选项Preferences:个性化定制。帮助Help:标签栏:文件名的缩略图,文件编辑未保存,右上角有个小圆点,提示保存。如果未保存关了也不用害怕,自动保存。状态栏:ASCII编码、Line 6-Column 53(当前行列号)、Tab Size:4(Tab格式等信息)、HTML(当前语言)。控制台:使用Ctrl+`调出,它既是一个标准的Python REPL,也可以直接对Sublime Text进行配置。编辑区:这是我们主要的工作区域,ST2支持代码自动缩进,代码折叠功能。2、常见的功能:自动完成:自动完成的快捷键是Tab,如果在html文件中,输入cl按下tab,即可自动补全为class=””;加上zencoding后,更是如虎添翼,后面再讲到多列编辑:按住ctrl点击鼠标,会出现多个闪烁的光标,这时可同时修改多处,或者按住鼠标中键拖拽,代码注释功能:ctrl+/、ctrl+shift+/分别未行注释和块注释,再按一下就能去掉注释,ST2能够自动识别是html、css还是js文件,给出不同类型的注释。行操作:ctrl+alt+↑、ctrl+alt+↓向上或者向下交换两行,ctrl+enter,光标后插入空行,ctrl+d选择相似,可以参考后面的快捷键列表。右键功能:前3个,大家都知道,第4个,show unsaved changes,显示未保存的修改,红色减号表示删去的内容,绿色加号表示新增的内容Open Containing Folder…,打开包含此文件的文件夹,这个很方便找到相关的文件Copy File Path,复制文件路径,方便我们复制路径到浏览器中查看Auto-Format Tags on Selection 格式化选中的文档,方便我们更清晰的查看代码结构,虽然ST2有自动缩进功能,但是当我们粘贴进一段没有格式化过的代码,就需要这个能了,这个功能要安装了Tag这个插件才会出现。人性化设计:ST2虽然还是beta版中,但是有很多设计细节还是值得称赞的,比如点击一个标签或者括弧,会在起始处显示下划点线,方便看清代码结果,每一层嵌套代码间都有竖线,起到视觉辅助的作用。设置自定制,数据被保存在Preferences.sublime-settings,Default或User,user可以覆盖default。在配置文件,直接设置配置文件在:preferences-setting user。下面是一些可能有用但我很少用到的功能:宏(Macro):Sublime Text支持录制宏,但我在实际工作中并未发现宏有多大用处。其它平台(Other Platforms):本文只介绍了Windows平台上Sublime Text的使用,不过Linux和OS X上Sublime Text的使用方式和Windows差别不大,只是在快捷键上有所差异,请参考Windows/Linux快捷键和OS X快捷键。项目(Projects):Sublime Text支持简单的项目管理,但我一般只用到文件夹。Vim模式(Vintage):Sublime Text自带Vim模式。构建(Build):通过配置,Sublime Text可以进行源码构建。调试(Debug):通过安装插件,Sublime Text可以对代码进行调试。快捷键若稍有英文基础,则更建议打开Preferences->KeyBindings–Default,这里面是详细的快捷键配置。快捷键设置,ST2的快捷键很多,改的时候注意不要覆盖了。因为快捷键众多,所以有下面这种组合快捷键,先按下ctrl+k,松开k,再按下j就可以展开全部代码了。快捷键列表(Shortcuts Cheatsheet)我把本文出现的Sublime Text按其类型整理在这里,以便查阅。123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168### 通用(General) ↑↓←→:上下左右移动光标,注意不是不是KJHL! Alt:调出菜单### 整理(clear) Tab:缩进:自动完成 Shift+Tab:去除缩进 Ctrl+KT:折叠属性 Ctrl+K0:展开所有### 窗口(Window)### 移动(Move) Ctrl+←/→:进行逐词移动 Ctrl+Shift+←/→进行逐词选择 Ctrl+↑/↓移动当前显示区域 Ctrl+Shift+↑/↓移动当前行 Ctrl+D:选择当前光标所在的词并高亮该词所有出现的位置,再次Ctrl+D选择该词出现的下一个位置,在多重选词的过程中,使用Ctrl+K进行跳过,使用Ctrl+U进行回退,使用Esc退出多重### 编辑 Ctrl+Shift+L:将当前选中区域打散### 文件(File) Ctrl+N:在当前窗口创建一个新标签 Ctrl+O:打开文件 Ctrl+Shift+T:打开最近关闭的文件 Ctrl+S:保存 Ctrl+Shift+S:另存为 Ctrl+Shift+N:创建新窗口 Ctrl+Shift+W:关闭窗口 Ctrl+W:关闭当前标签,当窗口内没有标签时会关闭该窗口### 编辑(Edit) Ctrl+Z:撤销 Ctrl+Y:恢复### 取消选择(Undo Selection) Ctrl+U:智能撤销 Ctrl+ Shift+U:智能重做 Ctrl+ Shift+V:粘贴并缩进 Ctrl+K,Ctrl+V:### 行(Line) Ctrl +]:缩进 Ctrl +[:反缩进 Ctrl + Shift + Up:上移一行 Ctrl + Shift + Down:下移一行 Ctrl + Shift + D:复制行(加倍) Ctrl + Shift + K:删除行 Ctrl + J:连接行### 文本(Text) Ctrl+Shift+Enter:在当前行上面增加一行并跳至该行 Ctrl+Alt+Enter:替换所有关键字匹配 Ctrl+Enter:在当前行下面新增一行然后跳至该行 Ctrl+Delete:删除单词前部 Ctrl+Backspace:删除单词后部 Ctrl+K,Ctrl+K:从光标处删除至行尾 Ctrl+K+Backspace:从光标处删除至行首 Ctrl+T:前后调转### 注释(Comment) Ctrl+/:注释(如已选择内容,同“Ctrl+Shift+/”效果) Ctrl+Shift:/:块注释(注释已选择内容) Ctrl+Alt+/:块注释,并Focus到首行,写注释说明用的### 标签(Tag) Alt+.:闭合当前标签 Ctrl+Shift+A:选择标签(可重复) Ctrl+Shift+W:选择区域被标签包含### (Mark) Ctrl+K, Alt+Space:设置记号 Ctrl+K,Alt+A:选择到记号 Ctrl+K,Alt+W:删除到记号 Ctrl+K,Alt+S:交换(移动)记号 Ctrl+K,Alt+G:移除记号 Ctrl+K,Alt+Y:Yank Ctrl+K,Alt+J:取消所有折叠### 代码折叠(Code Folding) Ctrl+Shift+[:折叠代码 Ctrl+Shift+]:展开代码 (Convert Case) Ctrl+K,Ctrl+U:改为大写 Ctrl+K,Ctrl+L:改为小写### (Wrap) Alt+Q: Ctrl+Space:显示提示 F9:按行排序 Ctrl+F9:按行排序(区分大小写)### 选择(Selection) Ctrl+ Shift+L:分割为多光标(选择多行时) Ctrl+ Alt +Up:向上一行添加光标 Ctrl+ Alt +Down:向下一行添加光标 Escape单光标### 扩展(Expand) Ctrl+A:全选 Ctrl+L:选择整行(按住-继续选择下行) Ctrl+D:选词:(按住-继续选择下个相同的字符串) Ctrl+Shift+Space:快速选择当前作用域(Scope)的内容 Ctrl+Shift+M:快速选择括号间的内容{} Ctrl+Shift+J:快速选择同缩进的内容 Ctrl+Shift+A:选择光标位置父标签对儿### 查找(Find) Ctrl+F:进行标准查找 F3:跳至当前关键字下一个位置 Shift+F3:跳到当前关键字上一个位置 Ctrl +I: Ctrl +H:进行标准替换 Ctrl+Shift+H:替换当前关键字 Ctrl +F3:快速查询 Alt +F3:选中当前关键字出现的所有位置 Ctrl+D:快速查询下一个(多光标) Ctrl+K,Ctrl+D:快速查询跳过下一个(多光标) Ctrl+E:字 Ctrl+Shift+E:字 Ctrl+Shift+F:多文件搜索&替换### 视图(View) Ctrl+K,Ctrl+B:侧边栏开关Side Bar Ctrl+`:调出控制台 F11:切换普通全屏 Shift+F11:切换无干扰全屏 Alt+Shift+2:进行左右分屏 Alt+Shift+5:进行上下左右分屏 Alt+Shift+8:进行上下分屏。 分屏,使用Ctrl+数字键跳转到指定屏,使用Ctrl+Shift+数字键将当前屏移动到指定屏### 组(Group): Ctrl+K,Ctrl+Up: Ctrl+K,Ctrl+ Shift+ Up: Ctrl+K,Ctrl+Down:### 焦点小组(Focus Group): Ctrl+K,Ctrl+Right: Ctrl+K,Ctrl+ Left: Ctrl+1:组间切换焦点 Ctrl+ Shift +1:移动文件到组 Syntax语法和文件类型、indentation缩排、Line Endings行尾结束符号 F6:拼写检查 Ctrl + F6:下一个错误 Ctrl+Shift+ F6:上一个错误### 跳转(Goto) Ctrl+P:跳转到指定文件 Ctrl+R:跳转到指定符号 Ctrl+Shift+R: F12: Ctrl+G:跳转到指定行号 Alt+-:跳转到底部 Alt+Shift +-:### 文件开关(Switch File) Ctrl+Pagedown:下一个文件 Ctrl+Pageup:上一个文件 Ctrl+Tab:下一个文件(stack) Ctrl+Shift + Tab:上一个文件(stack) Alt+O: Alt+1:最近打开文件### 滚动(Scroll) Ctrl+K,Ctrl+C:滚动到光标处 Ctrl+Up:向上滚动一行(定光标) Ctrl+Down:向下滚动一行(定光标)### 书签(Boolmarks) Ctrl+F2:设置书签 F2:下一个书签 Shift+F2:上一个书签 Ctrl+Shift+F2:清除书签 Alt+F2:全选书签 Ctrl+M:在起始括号和结尾括号间切换### 工具(Tools) Ctrl+Shift+P:调出命令板(Command Palette) Ctrl +B: Ctrl+Shift+B: Ctrl +Break: F4: Shift+ F4: Ctrl +Q: Ctrl+Shift+Q:### 项目(Project) Ctrl+Alt+P:切换项目 #### 首选项(Preferences) Ctrl+ Keypad Plus: Ctrl+Shift+Keypad Plus: Help(帮助)总结:多行游标:12345方法一:利用查找替换功能:Ctrl + H方法二(推荐):Ctrl+D选中另一个,如果有某些不想添加新行的模式则按ctrl+K,ctrl+D跳过这个进入下一个符合条件的模式行。按Alt + F3快捷键,全选所有符合条件的单词。如果要在每行都加入光标,可以先ctrl+A然后ctrl+shift+L即可。如果在某个字符的多行后面加上光标,可以将光标放在这个字符后面,按住shift键,然后右键可以向下拖动产生多个光标。Goto anything:(模糊匹配)1234Ctrl+P:跳转到指定文件,输入文件名后可以:@ 符号跳转:输入@symbol跳转到symbol符号所在的位置# 关键字跳转:输入#keyword跳转到keyword所在的位置: 行号跳转:输入:12跳转到文件的第12行。命令快捷执行:12Ctrl+Shift+P:输入set syntax JavaScript进行文件类型更改。输入Minimap进行迷你地图切换。快速添加新行12Ctrl + Enter可以在当前行下新建一行。 Ctrl + Shift + Enter可以在当前行上面添加一行。最后购买:Sublime Text2或者3都没关系,3也只是作为2的beta版本,所以还是推荐3吧,支持新版嘛。2和3在使用方法功能上也有差异~你可以去官网下载对应版本,但可能需要输入序列号什么的。访问下载 2.x 版本。或从下载 3.x 版本。注册码(仅供个人非商业应用):12345678910111213----- BEGIN LICENSE ------AlexanderSingle User LicenseEA7E-81434551F47F09 4EAB1285 7827EFF0 8B1207DCA76A6EA3 E1A1CA7A DC1F2703 14,897,7848EDC1C82 3F2A58B9 1C0C8B24 67686432281245B3 6233DE5C ADC5C2F9 61FB8A04171B63EF 86BA423F 6AC884FD 3273A7AA5F50A6DB CE7859AE D62D2B37 AEEDD8C2078A8A20 70EEA791 84F48C1E 8ABA7DEB0B3907C0 C9A3523B 0091A045 6F67AED8------ END LICENSE ------12345678910111213----- BEGIN LICENSE -----Andrew WeberSingle User LicenseEA7E-855605813A03DD 5E4AD9E6 6C0EEB94 BC99798F942194A6 02396E98 E62C9979 4BB979FE91424C9D A45400BF F6747D88 2FB8807890F5CC94 1CDC92DC 8457107A F151657B1D22E383 A997F016 42397640 33F41CFCE1D0AE85 A0BBD039 0E9C8D55 E1B89D5D5CDB7036 E56DE1C0 EFCC0840 650CD3A6B98FC99C 8FAC73EE D2B95564 DF450523------ END LICENSE ------搜索3114注册码12345678910111213—– BEGIN LICENSE —–Anthony SansoneSingle User LicenseEA7E-87856328B9A648 42B99D8A F2E3E9E0 16DE076EE218B3DC F3606379 C33C1526 E8B58964B2CB3F63 BDF901BE D31424D2 082891B5F7058694 55FA46D8 EFC11878 0868F093B17CAFE7 63A78881 86B78E38 0F146238BAE22DBB D4EC71A1 0EC2E701 C7F9C6485CF29CA3 1CB14285 19A46991 E9A9867614FD4777 2D8A0AB6 A444EE0D CA009B54—— END LICENSE —汉化:可以网上找些中文包放进去就行了。Sublime Text 全程指南:插件:插件的选择:主题:blackboardSideBarEnhancements(侧边栏增强,添加浏览器)Zen CodingadvanceNewfileSyncedSideBartagJsFormat(javascript格式化)ColorPicker (调色盘)GBK to UTF8GBK Encoding Support(GBK中文编码)SublimeLinter(代码错误提示) 总体架构snippets(自定制代码补齐机制)快捷代码:跳到行首行尾的快捷键12345[ //跳到行首行尾的快捷键 { "keys": ["ctrl+k", "ctrl+h"], "command": "move_to", "args": {"to": "bol", "extend": false} }, { "keys": ["ctrl+k", "ctrl+e"], "command": "move_to", "args": {"to": "eol", "extend": false} }]先按ctrl+k,然后按ctrl+h(home首字母)光标移动到行首;先按ctrl+k,然后按ctrl+e(end首字母)光标移动到行尾。设置Setting12//Set Update false"update_check": false,延伸阅读(Further Reading):1、书籍(Books)Mastering Sublime Text:我读过的唯一一本关于Sublime Text的书籍,书中介绍的插件很实用,但对编辑技巧介绍不全。Instant Sublime Text Starter:另外一本关于Sublime Text的书,我没有读过。2、链接(Links)官方文档:官方论坛:Stack Overflow的Sublime Text频道:sublimetextsublimetext2sublimetext3非官方文档: 甚至比官方文档还要全面!Package Control: 大量的Sublime Text插件和主题。3、视频(Videos)Getting Started with SublimeText:Sublime Text Pefect Workflow:]]></content>
<categories>
<category>Tool</category>
</categories>
<tags>
<tag>Sublime</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Sublime插件]]></title>
<url>%2F2015%2F12%2F21%2FSublimePackage%2F</url>
<content type="text"><![CDATA[自用笔记:本文属于自用笔记,不做详解,仅供参考。在此记录自己已理解并开始遵循的前端代码规范。What How Why安装有两个办法:1、直接把插件放到它的安装路径对应文件包packages里面去,不知道在哪的可以直接打开 preferences->Browse packages,放进去之后软件会自动检测。2、使用命令方式直接让软件自己下载安装。(使用package control组件)(前提:先安装下面那个package control插件)按下Ctrl+Shift+P调出命令面板,输入install, 调出 Install Package 选项并回车,然后在列表中选中要安装的插件。下载拷贝:然后把它放到package文件包中。没用过Github的朋友不知道在哪里下载。Download ZIP。然后把它解压,把文件夹放进package文件包,然后它就能检测到包啦!代码安装:Ctrl+shift+p、输入install、选择package install 过几秒会弹出另一个框。然后在输入框中输入你想要的插件关键字安装吧!大致就是这样,简单明了。下面介绍其他常用插件,安装方式同理!package control(包裹组件)通过快捷键 ctrl+` 或者 View > Show Console 菜单打开控制台,然后粘贴对应的版本代码进去,然后回车让它安装。适用于 Sublime Text 3:1import urllib.request,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1548d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)适用于 Sublime Text 2:1import urllib2,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1548d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by = urllib2.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by) if dh == h else None; print('Error validating download (got %s instead of %s), please try manual install' % (dh, h) if dh != h else 'Please restart Sublime Text to finish installation')当然了,有些时候这样你安装不进去的,就只能自个去下载安装包放到package文件里边去了(就是上边我说的那个文件夹)如果在Preferences → Package Settings 中看到 Package Control 这一项,说明安装成功。插件整理代码整理:Tag(代码格式化)全选Ctrl+A,Ctrl+Alt+FHTMLBeautify()格式化HTML。HTML/CSS/JS Prettify(代码格式化)能够格式化css html和js。注意:格式化的文件路径中不能有中文,不然会报找不到node的错误(windows下)。YUI Compressor(压缩JS和CSS文件)PHPTidy(整理与排版PHP代码)JsFormat(JS格式化)很多网站的JS代码都进行了压缩,一行式的甚至混淆压缩,这让我们看起来很吃力。而这个插件能帮我们把原始代码进行格式的整理,包括换行和缩进等等,是代码一目了然,更快读懂1Ctrl+Alt+F JS格式化注释:DocBlockr(代码自动注释生成)标准的注释,包括函数名、参数、返回值等,并以多行显示,手动写比较麻烦1输入/*、/**然后回车,还有很多用法,请参照HtmlTidy(清理与排版你的HTML代码)AutoPEP8()格式化Python代码。Alignment安装案例Alignment(代码补齐)补齐就是补齐~就像这样代码简写:Emmet(Zen Coding 代码自动补齐) WikiEmmet作为zen coding的升级版,对于前端来说,可是必备插件。1ctrl+alt+enter:激发zencoding控制台123456789101112131415div#content>ul>li*3>a[href="javascript:void(0);"]{Links$}<div id="content"> <ul> <li><a href="javascript:void(0);">Links1</a></li> <li><a href="javascript:void(0);">Links2</a></li> <li><a href="javascript:void(0);">Links3</a></li> </ul></div>div.wrapper>div.header+div.main+div.footer:按下Tab,立刻变成<div class="wrapper"> <div class="header"></div> <div class="main"></div> <div class="footer"></div></div>SublimeCodeIntel(代码提示)自动提示我们,可能要输入HTML代码内容snippets(自定制代码补齐机制)自定制代码补齐机制,高亮显示:BracketHighlighterBracketHighlighter高亮显示匹配的括号、引号和标签,BracketHighlighter这个插件能在左侧高亮显示匹配的括号、引号和标签,能匹配的### ] , () , {} , “” , ‘’ ,等甚至是自定义的标签,当看到密密麻麻的代码分不清标签之间包容嵌套的关系时,这款插件就能很好地帮你理清楚代码结构,快速定位括号,引号和标签内的TrailingSpacer(高亮显示多余的空格和Tab)颜色:ColorPicker (调色盘)1ctrl+shift+c:需要输入颜色时,可直接选取颜色CSS:CSScomb(CSS属性排序)CSS3_Syntax(css语法高亮)对css语法高亮的支持,view-syntax-css3选中css3就能使用css3高亮了。必须每条属性都加上分号,并且属性必须小写,不然不会高亮,有点鸡肋啊。Prefixr(自动加-webkit前缀)写 CSS可自动添加 -webkit 等私有词缀,Ctrl+Alt+X触发。Autoprefixer(自动加前缀)可以给css自动加前缀功能Goto-CSS-Declaration(CSS文件跳转)跳转到css文件该class的声明处,方便修改查看,如图下所示,注意对应的css文件要同时打开才行。编码:GBK Encoding Support(GBK中文编码)这个插件还是非常有用的,因为sublime 本身 不支持gbk编码,在utf8如此流行的今天,我们整站还是gbk编码,o(︶︿︶)o 唉,所以全靠这个插件了。GBK to UTF8(编码转换)将文件编码从GBK转换成UTF8,菜单 – File里面找。文档管理:AdvancedNewFile(新建文件)1Ctrl+Alt+N:按路径自动创建文件AutoFileName(文件名索引)快捷输入文件名,输入”/”即可看到相对于本项目文件夹的其他文件。GotoRecent(历史文档记录)打开最近的文件,系统有这个功能,但只能看最近8个,有点不爽,按ctrl+e,选择即可。1ctrl+e:Nettus+ fetch (管理一些开源框架)配置文件修改,Ctrl+Shift+P输入Fetch Manage,配置文档。通过输入fetch file,搜索框架名进行导入。SideBarEnhancements(侧边栏增强)SyncedSideBar(侧边栏打开文件定位)支持当前文件在左侧面板中定位,不错。Hex-to-HSL-Color Hex(颜色模式转HSL颜色模式)advanceNewfile(面板随意添加文件)按Ctrl+Alt+N,下方输入A\B\test.css就好了,test.css这个文件出现在某个文件夹。SublimeTmpl (自定义新建文件)默认已经添加了html、css、js等常见类型的面板,按ctrl+alt+h/ctrl+alt+c/ctrl+alt+j可新建这 3钟类型的文件,快捷键在这里\Packages\SublimeTmpl\Default (Windows).sublime-keymap, 模板文件在这里\Packages\SublimeTmpl\templates,可修改。 比如下边简单的html文件语法识别:LESS(LESS语法识别)这是一个非常棒的插件,可以让sublime支持less的语法高亮和语法提示,对于搞less的同学灰常重要,不过多解释。SCSS(SCSS语法识别)支持scss的语法高亮,里面附带了好多CSS Snippet,无论现用或者改造成,都可节省不少时间。ejs(ejs语法识别)支持ejs的语法高亮,里面附带了好多CSS Snippet,无论现用或者改造成,都可节省不少时间。node(node语法识别)支持node的只能语法提示,很赞。jQuery(jQuery语法识别)支持jquery的只能语法提示,很赞。JavaScriptNext - ES6 Syntax(ES6语法识别)提供ES6的语法支持。WordPress(WordPress的函数)集成一些WordPress的函数,对于像我这种经常要写WP模版和插件的人特别有用Vintage(Vim模拟)如果你习惯使用vim,那么可以安装这个插件,这个插件可以让sublime像vim一样。Liquid(Liquid语法识别)提供Liquid语法支持,如果你也写博客的话不妨试试。Smarty(Smarty语法识别)提供smarty语法的支持。Smarty插件默认的分隔符是{},如果你使用的分隔符不同可以更改插件目录的Smarty.tmPreferences文件,找到其中的SMARTY_LDELIM和SMARTY_RDELIM,修改为你的分隔符即可。文件传输:git最后推荐一个同步插件,这个插件可以在不同的机器同步配置信息和插件,非常方便,但鉴于国内的墙太高,我都是直接把插件给手动备份了,然后直接拖进去,或者直接去github上下载对应的包。123456<!-- 昨天安装过Android Studio,之后就出现PATH问题。 -->> status```bashGit: status:查看改动的文件add123Git: add all:添加所有文件Git: add ...:添加制定文件Git: addcommit12Git: commit:提交描述Git: commithistroy:提交历史描述将会展示提交内容修改了那些内容。ctrl+w:关闭文件的同时,commit操作自动触发。SFTP(编辑 FTP 或 SFTP 服务器上的文件)Package Syncing其他:OmniMarkupPreviewerWindows, Linux:123Ctrl+Alt+O: Preview Markup in Browser.Ctrl+Alt+X: Export Markup as HTML.Ctrl+Alt+C: Copy Markup as HTML.OSX:123commond+control+O: Preview Markup in Browser.commond+control+X: Export Markup as HTML.Ctrl+Alt+C: Copy Markup as HTML.FileDiff(代码对比)右键标签页,出现FileDiffs Menu或者Diff with Tab…选择对应文件比较即可Bracket Highlighter(代码匹配)可匹配[], (), {}, “”, ”,,高亮标记,便于查看起始和结束标记Clipboard-history(粘贴板历史记录)可以保存粘贴的历史,很赞的功能,再也不用担心历史丢失了。ctrl+alt+v可打开历史面板,上下选择即可,安装后会和默认的ctrl+shift+v(粘贴缩进)冲突,干掉这个快捷键。1234Ctrl+alt+v:显示历史记录Ctrl+alt+d:清空历史记录Ctrl+shift+v:粘贴上一条记录(最旧)Ctrl+shift+alt+v:粘贴下一条记录(最新)CTags(函数跳转)需要安装CTagsTerminal(终端)1Ctrl+Shift+T:增加Open Terminal Here12345678910111213141516{ // window下终端路径 "terminal": "E:/Program Files/Git/git-bash.exe", // "terminal": "C:\\Program Files\\cmder_mini\\cmder.exe", // "parameters": ["/START", "%CWD%"] // window下终端参数 "parameters": [] // xterm on GNU/Linux // "terminal": "xterm" // iTerm on OS X // "terminal": "iTerm.sh" // iTerm on OS X with tabs // "terminal": "iTerm.sh", // iTerm2 v3 on OS X // "terminal": "iTerm2-v3.sh"}Gits(集成 GitHub)lint(语法校验):SublimeLinter(代码错误提示) 总体架构Jslint编程风格Tradsim(中文繁字体和简体字转换)Terminal可以sublime中,打开命令行,非常方便哦。AllAutocomplete自动完成插件,可在全部打开的文件中,自动完成。HexViewer提供十六进制文件查看功能。MultiEditUtils扩展多行编辑的功能。IMESupport(输入框不更随着光标)主题(Themes)Sublime Text有大量第三方主题:ayu Theme、sublime materialSublimeTextTrans(背景透明度)DownLoad1Ctrl+Shift+1-6 执行调节背景透明度。SideBarFolders打开的文件夹都太多了,再用这个来管理文件夹Sublime Merger]]></content>
<categories>
<category>Plug</category>
</categories>
<tags>
<tag>Sublime</tag>
</tags>
</entry>
<entry>
<title><![CDATA[CDN公共库]]></title>
<url>%2F2015%2F12%2F21%2FJQueryCDN%2F</url>
<content type="text"><![CDATA[CDN公共库是指将常用的JS库存放在CDN节点,以方便广大开发者直接调用。与将JS库存放在服务器单机上相比,CDN公共库更加稳定、高速。一般的CDN公共库都会包含全球所有最流行的开源JavaScript库,你可以在自己的网页上直接通过script标记引用这些资源。这样做不仅可以为您节省流量,还能通过CDN加速,获得更快的访问速度。百度静态资源公共库百度jquery地址公共库,百度jquery cdn引用地址稳定,快速由百度遍布全国各地100+个CDN节点提供加速服务。让开源库享受与百度首页静态资源同等待遇。全面,开源收录超过180+开源库,并且这个数字正在不断增加。百度静态资源公共库服务不仅在Github开源库上接受任何人的提交请求,同时实时同步国外如CDNJS上优秀的开源库。百度在之前推出了CDN公共库,同时最近google的公共库经常性的出现无法访问的问题,所以对自己站点的公共库文件进行了更新了。当然BAE的公共库也有几个问题,主要是一下两个问题:百度公共库目前还不支持 HTTPS 加密访问,如果有这个需求的话就需要考虑下了!百度公共库更新不是很即时,部分库的版本还是比较老,并没有提供最新版本的CDN。资源列表使用方法: 加载JS库,复制HTML代码片段(如下所示)到网页。例如,要加载jQuery,将如下所示的代码嵌入到你的网页中即可。1<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>backbone1234567加载地址:未压缩:<script src="http://libs.baidu.com/backbone/0.9.2/backbone.js"></script>压缩:<script src="http://libs.baidu.com/backbone/0.9.2/backbone-min.js"></script>官网:http://documentcloud.github.com/backbone/支持的版本:0.9.2Bootstrap123456789加载地址:未压缩:<script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.js"></script><link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.css" rel="stylesheet">压缩:<script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js"></script><link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">官网:https://github.com/twitter/bootstrap/支持的版本:2.0.4 ,2.0.3 ,2.0.2 ,2.1.1,2.2.1,2.3.1,2.3.2, 3.0.3dojo12345加载地址:压缩:<script src="http://libs.baidu.com/dojo/1.8.0/dojo.js"></script>官网:http://dojotoolkit.org/支持的版本:1.8.3, 1.8.2, 1.8.1, 1.8.0, 1.7.4, 1.7.3, 1.7.2, 1.7.1, 1.7.0, 1.6.1, 1.6.0, 1.5.2, 1.5.1, 1.5.0, 1.4.4, 1.4.3, 1.4.1, 1.4.0, 1.3.2, 1.3.1, 1.3.0, 1.2.3, 1.2.0, 1.1.1ext-core12345加载地址:压缩:<script src="http://libs.baidu.com/ext-core/3.1.0/ext-core.js "></script>官网:http://www.sencha.com/products/extjs/支持的版本:3.1.0,3.0.0Highcharts12345加载地址:压缩:<script src="http://libs.baidu.com/highcharts/2.2.5/highcharts.js"></script>官网:http://www.highcharts.com/支持的版本:2.3.5, 2.2.5Highstock12345加载地址:压缩:<script src="http://libs.baidu.com/highstock/1.2.5/highstock.js"></script>官网:http://www.highcharts.com/支持的版本:1.2.5jqMobi12345加载地址: 压缩:<script src="http://libs.baidu.com/jqmobi/1.0.0/jq.ui.min.js "></script><script src="http://libs.baidu.com/jqmobi/1.0.0/jq.mobi.min.js "></script>官网:http://www.jqmobi.com/支持的版本:1.0.0jQuery1234567加载地址:未压缩:<script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>压缩:<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>官网: http://jquery.com/支持的版本: 2.0.3, 2.0.2, 2.0.1, 2.0.0, 1.10.2, 1.10.1, 1.10.0, 1.9.1, 1.9.0, 1.8.3, 1.8.2, 1.8.1, 1.8.0, 1.7.2, 1.7.1, 1.7.0, 1.6.4, 1.6.3, 1.6.2, 1.6.1, 1.6.0, 1.5.2, 1.5.1, 1.5.0, 1.4.4, 1.4.3, 1.4.2, 1.4.1, 1.4.0, 1.3.2, 1.3.1, 1.3.0, 1.2.6, 1.2.3jQuerymobile1234567加载地址:未压缩:<script src="http://libs.baidu.com/jquerymobile/1.3.0/jquery.mobile-1.3.0.js"></script>压缩:<script src="http://libs.baidu.com/jquerymobile/1.3.0/jquery.mobile-1.3.0.min.js"></script>官网:http://jquerymobile.com/支持的版本:1.3.0, 1.1.1, 1.0.1jQuerytools12345加载地址:压缩:<script src="http://libs.baidu.com/jquerytools/1.2.7/jquery.tools.min.js"></script>官网:http://jquerytools.org/支持的版本:1.2.7jQueryui12345加载地址:压缩:<script src="http://libs.baidu.com/jqueryui/1.8.22/jquery-ui.min.js "></script>官网:http://jqueryui.com/支持的版本:1.10.2, 1.10.1, 1.10.0, 1.9.2, 1.9.1, 1.9.0, 1.8.24, 1.8.23, 1.8.22, 1.8.21, 1.8.20, 1.8.19, 1.8.18, 1.8.17, 1.8.16, 1.8.15, 1.8.14, 1.8.13, 1.8.12, 1.8.11, 1.8.10, 1.8.9, 1.8.8, 1.8.7, 1.8.6, 1.8.5, 1.8.4, 1.8.2, 1.8.1, 1.8.0, 1.7.3, 1.7.2, 1.7.1, 1.7.0, 1.6.0, 1.5.3, 1.5.2JSON12345加载地址:未压缩:<script src=" http://libs.baidu.com/json/json2/json2.js"></script>官网:https://github.com/douglascrockford/JSON-js支持的版本:json2lesscss12345加载地址:压缩:<script src="http://libs.baidu.com/lesscss/1.3.0/less.min.js"></script>官网:http://www.lesscss.net/支持的版本:1.3.0mootools12345加载地址:压缩:<script src="http://libs.baidu.com/mootools/1.4.5/mootools-yui-compressed.js"></script>官网:http://mootools.net/支持的版本:1.4.5, 1.4.4, 1.4.3, 1.4.2, 1.4.1, 1.4.0, 1.3.2, 1.3.1, 1.3.0, 1.2.5, 1.2.4, 1.2.3, 1.2.2, 1.2.1, 1.1.2, 1.1.1prototype12345加载地址:未压缩:<script src="http://libs.baidu.com/prototype/1.7.1.0/prototype.js"></script>官网:http://prototypejs.org/支持的版本:1.7.1.0, 1.7.0.0, 1.6.1.0, 1.6.0.3, 1.6.0.2QUnit12345加载地址:未压缩:<script src="http://libs.baidu.com/quint/1.9.0/qunit.js"></script>官网:http://docs.jquery.com/QUnit支持的版本:1.4.0,1.5.0,1.6.0,1.7.0,1.8.0,1.9.0scriptaculous12345加载地址:未压缩:<script src="http://libs.baidu.com/scriptaculous/1.9.0/scriptaculous.js "></script>官网:http://script.aculo.us/支持的版本:1.9.0, 1.8.3swfobject12345加载地址:压缩:<script src="http://libs.baidu.com/swfobject/2.2/swfobject.js"></script>官网:http://code.google.com/p/swfobject/支持的版本:2.1,2.2UNDERSCORE1234567加载地址:未压缩:<script src="http://libs.baidu.com/underscore/1.3.3/underscore.js"></script>压缩:<script src="http://libs.baidu.com/underscore/1.3.3/underscore-min.js"></script>官网:http://underscorejs.org/支持的版本:1.3.3webfont12345加载地址:压缩:<script src="http://libs.baidu.com/webfont/1.0.28/webfont.js"></script>官网:https://developers.google.com/webfonts/docs/webfont_loader支持的版本: 1.3.0, 1.1.2, 1.1.1, 1.1.0, 1.0.31, 1.0.30, 1.0.29, 1.0.28, 1.0.27, 1.0.26, 1.0.25, 1.0.24, 1.0.23, 1.0.22, 1.0.21, 1.0.19, 1.0.18, 1.0.17, 1.0.16, 1.0.15, 1.0.14, 1.0.13, 1.0.12, 1.0.11, 1.0.10, 1.0.9, 1.0.6, 1.0.5, 1.0.4, 1.0.3, 1.0.2, 1.0.1, 1.0.0yui1234567加载地址:未压缩:<script src="http://libs.baidu.com/yui/3.4.1/yui.js"></script>压缩:<script src="http://libs.baidu.com/yui/3.4.1/yui-min.js"></script>官网:http://yuilibrary.com/支持的版本:3.4.1,3.3.0zepto12345加载地址:压缩:<script src="http://libs.baidu.com/zepto/0.8/zepto.min.js"></script>官网:http://zeptojs.com/支持的版本:0.8,1.0rcFont Awesome123456789加载地址:压缩:<link href="//libs.baidu.com/fontawesome/4.0.3/css/font-awesome.min.css" rel="stylesheet">未压缩:<link href="//libs.baidu.com/fontawesome/4.0.3/css/font-awesome.css" rel="stylesheet">官网:http://fontawesome.io/]]></content>
<categories>
<category>Induce</category>
</categories>
<tags>
<tag>CDN</tag>
</tags>
</entry>
<entry>
<title><![CDATA[前端资源导航]]></title>
<url>%2F2015%2F12%2F21%2FFrontEndGuide%2F</url>
<content type="text"><![CDATA[网址提交的格式:标题:JS秘密花园说明:JavaScript秘密花园是一个不断更新,主要关心JavaScript一些古怪用法的文档(用以说明这个网址资源的介绍)链接:http://bonsaiden.github.io/JavaScript-Garden/zh/分类:JavaScript > 技巧/教程]]></content>
</entry>
<entry>
<title><![CDATA[Busy前端工作室]]></title>
<url>%2F2015%2F12%2F11%2FBusyFront%2F</url>