-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathatom.xml
1562 lines (985 loc) · 110 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
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"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[博客 SPRABBIT 超科学兔耳中队]]></title>
<link href="http://blog.sprabbit.com/atom.xml" rel="self"/>
<link href="http://blog.sprabbit.com/"/>
<updated>2014-09-03T16:30:19+08:00</updated>
<id>http://blog.sprabbit.com/</id>
<author>
<name><![CDATA[火雾宗师]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[IOS Safari 浏览器的点击事件问题]]></title>
<link href="http://blog.sprabbit.com/blog/2014/09/03/onclick-ios-safari/"/>
<updated>2014-09-03T16:11:00+08:00</updated>
<id>http://blog.sprabbit.com/blog/2014/09/03/onclick-ios-safari</id>
<content type="html"><![CDATA[<p>今天碰到一个问题,在IOS的Safari浏览器中,一个网页的div元素在绑定了click事件后点击时有变暗的闪烁。在其他浏览器均无出现此现象,即使是桌面的Safari也没有。</p>
<p>我于是清空了click事件中的所有代码,仍然会出现此状况,但是直接去掉时间绑定则不会变暗,于是确定是因为绑定click事件引起的变暗。</p>
<p>后面我又在事件处理中写了个alert(),发现在提示框弹出的时候,那个div已经变暗了,也就是说在处理事件之前,浏览器已经给div附加了变暗效果。那基本上可以确定是IOS Safari的默认样式效果了。</p>
<p>于是StackOverflow了一下问题迎刃而解:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'><span class="nt">html</span> <span class="p">{</span>
</span><span class='line'> <span class="o">-</span><span class="n">webkit</span><span class="o">-</span><span class="n">tap</span><span class="o">-</span><span class="n">highlight</span><span class="o">-</span><span class="k">color</span><span class="o">:</span><span class="k">transparent</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>参考:<a href="http://stackoverflow.com/questions/2355154/iphone-darkens-div-on-click">http://stackoverflow.com/questions/2355154/iphone-darkens-div-on-click</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Javascript备忘]]></title>
<link href="http://blog.sprabbit.com/blog/2013/08/22/javascript-memo-1/"/>
<updated>2013-08-22T20:21:00+08:00</updated>
<id>http://blog.sprabbit.com/blog/2013/08/22/javascript-memo-1</id>
<content type="html"><![CDATA[<p>这个系列只是一个备忘录,主要是讲述平时编程遇到的一些奇怪的问题。
本来标题叫做Javascript奇技淫巧系列,但是现在我又被掉往服务端开发了,所以这个系列可能会不再更新,于是改回Javascript备忘。
其实这种奇怪的问题一般都出在IE上,所以重点就放在IE上了。</p>
<p>这次的主题是图片拖拽的问题,主要情景有几种,第一种是可以在网页上面拖拽的图片,另一种是在可拖动的元素下面有一张图。
当然还有一种是浏览器默认的图片拖拽,使用浏览器默认的图片拖拽可以直接将图片拖出浏览器,在新网页中打开,或者拖到其他软件中处理。
但是,往往我们都不希望出现默认的情况,尤其是想制造出前面两种效果的时候。</p>
<!--more-->
<h2>可以在网页上面拖拽的图片</h2>
<p>下面这里有一个例子:</p>
<div class="photo">
<img class="photo_drag" src="http://blog.sprabbit.com/images/jsmemo/enako.jpg" alt="enako" />
</div>
<p>点击图片可以拖动,如果你在IE之外支持canvas的浏览器中打开,还会有旋转的效果。
但是,如果只添加了拖动相关的代码的话,一开始会是下面这样:</p>
<div class="photo">
<img src="http://blog.sprabbit.com/images/jsmemo/enako.jpg" alt="enako" />
</div>
<p>没错,就跟没添加没什么区别(实际上我懒得再写一份没做处理的javascript了,所以上面这个确实没添加-_-|||,嘛效果是一样的)。</p>
<p>好了,区别在于前者在处理在图片上的<code>mousedown</code>事件时,做了如下操作:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'><span class="nx">e</span><span class="p">.</span><span class="nx">stopPropagation</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>
<p><code>e</code>是传进jQuery事件处理函数的jQuery事件参数,前者阻止了浏览器使用默认方法对事件的处理,后者阻止事件冒泡。
于是事件传递到此结束,浏览器也就不会产生拖拽图片的操作。
其他浏览器事件都支持preventDefault()方法,IE是比较奇淫的,通过返回值来判断是否执行默认操作。
所以jQuery事件的preventDefault()方法类似下面:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">e</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">originalEvent</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">this</span><span class="p">.</span><span class="nx">isDefaultPrevented</span> <span class="o">=</span> <span class="nx">returnTrue</span><span class="p">;</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="nx">e</span> <span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">return</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// If preventDefault exists, run it on the original event</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span> <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span> <span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Support: IE</span>
</span><span class='line'><span class="c1">// Otherwise set the returnValue property of the original event to false</span>
</span><span class='line'><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">e</span><span class="p">.</span><span class="nx">returnValue</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>而停止冒泡基本就是方法名不一样了。</p>
<h2>可以在图片上面拖拽的元素</h2>
<p>上面的解决方案可能很多人都知道。
不过在图片上拖拽元素这个可能就比较少实现。
一个比较常见的应用就是截图插件:</p>
<div id="photo">
<img id="scene" src="http://blog.sprabbit.com/images/jsmemo/scene.jpg" alt="scene"/>
</div>
<p>如果你想做出来选中内容跟未选中内容表现得不一样的效果,如上面的模糊与清晰的差别,那么很幸运,你将不会遇到奇怪的问题。
一旦你选择做出下面这种没有差别的效果,那就跪了,在IE你几乎无法移动那个小框(点小框的边框就可以)。</p>
<div id="photo2">
<img id="scene2" src="http://blog.sprabbit.com/images/jsmemo/scene.jpg" alt="scene"/>
</div>
<p>一开始我百思不得其解,因为点选框内,却产生了默认拖拽图片的操作,于是按上面的方法来修改onmouse事件,却无效。
最令人想不明白的是,明明小框显示在图片之上,为什么图片反而拦截到了点击事件?</p>
<p>其实答案却非常简单,只要仔细想想为什么点小框的边框就可以移动就明白了,点小框可以移动,证明小框获取消息的等级确实是比背景图要高。
而点击中间部分却无法移动,因为我们没有点到小框上的任何东西!是真的没有任何东西,直接穿透了小框,点到了图片上。
然后你就会发现,在IE中,原来元素里面没有任何东西,包括背景的话,点击的消息传递时是会直接跳过这个元素的。
IE在这里耍了点小聪明,以为这样可以方便消息的穿透,谁知道却适得其反。
不过好在解决方法是简单的,希望保持透明的话,加一层透明的背景就行了,这就不是没内容,而只是内容看不见而已。</p>
<div id="photo3">
<img id="scene3" src="http://blog.sprabbit.com/images/jsmemo/scene.jpg" alt="scene"/>
</div>
<p>而第一个效果分离的截图插件之所以不会遇到问题是因为这种效果一般是在小框内再包含一幅图像来实现的,就不再是透明的小框了。</p>
<h2>总结</h2>
<p>其实这里还有一个技巧,就是实现模糊效果的方法。
目前只有Chrome支持高斯模糊滤镜,为了在其他浏览器实现模糊效果,只能进行模拟。
我们知道高斯模糊可以通过横向模糊加纵向模糊叠加实现,于是我们就可以用多张半透明图像进行错位叠加实现。</p>
<p>总而言之,在做前端开发中会遇到很多神奇的问题,以后我将一一记录在这里。另外吐槽一下,IE你为什么那么傲娇啊,看到IE就想哭啊有木有啊。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Dust.js语法简介(三)]]></title>
<link href="http://blog.sprabbit.com/blog/2013/08/19/introduction-dustjs-3/"/>
<updated>2013-08-19T15:53:00+08:00</updated>
<id>http://blog.sprabbit.com/blog/2013/08/19/introduction-dustjs-3</id>
<content type="html"><![CDATA[<p><a href="http://blog.sprabbit.com/blog/2013/08/17/introduction-dustjs-2/">上一篇</a>介绍了Dust的最基本的语法,已经足够应付一般的模板翻译。这一章将介绍一些涉及逻辑的Dust语法以及介绍如何在前端应用模板。</p>
<!--more-->
<h2>逻辑区段</h2>
<h3>?标签</h3>
<p>用<code>?</code>来代替区段标签中的<code>#</code>时,仅当<code>name</code>的值为真时,才执行区段主体部分。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{?name} body {/name}
</span></code></pre></td></tr></table></div></figure>
<h3>^标签</h3>
<p>用<code>^</code>来代替<code>#</code>时,仅当<code>name</code>的值为假时,才执行区段主体部分。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{^name} body {/name}
</span></code></pre></td></tr></table></div></figure>
<h3>{:else}标签</h3>
<p>当一个区段标签(包括<code>#</code>、<code>?</code>、<code>^</code>、以及逻辑标签等)的值为假时,若区段主体中包含{:else}标签,则执行<code>{:else}</code>标签以及区段结束标签之间的内容,否则忽略这些内容。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><ul></span>
</span><span class='line'>{#friends}
</span><span class='line'> <span class="nt"><li></span>{name}, {age}{~n}<span class="nt"></li></span>
</span><span class='line'>{:else}
</span><span class='line'> <span class="nt"><p></span>You have no friends!<span class="nt"></p></span>
</span><span class='line'>{/friends}
</span><span class='line'><span class="nt"></ul></span>
</span></code></pre></td></tr></table></div></figure>
<p>若friend为空,则仅仅输出:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><ul></span>
</span><span class='line'> <span class="nt"><p></span>You have no friends!<span class="nt"></p></span>
</span><span class='line'><span class="nt"></ul></span>
</span></code></pre></td></tr></table></div></figure>
<h3>值的真假</h3>
<p>在区段中判断标签的真假的方法与Javascript本身稍有不同,Dust将以下值判断为假:</p>
<ul>
<li>空字符串<code>’’</code>、<code>””</code></li>
<li>布尔<code>false</code></li>
<li><code>null</code></li>
<li><code>undefined</code></li>
<li>空列表<code>[]</code></li>
</ul>
<p>其余值均为真值,包括数字“0”,空对象<code>{}</code>。</p>
<h2>拆分(Partials)</h2>
<p>拆分是一种将重复使用的模板抽取出来,并在使用到这段模板的模板中直接导入该模板,避免重复劳动的方法。在服务端,一个名为“xxx”的Dust模板通常通常保存在一个名为xxx.dust的模板文件中。我们可以利用模板名来在模板中插入一段来自其他模版文件的模板:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{>name /}
</span></code></pre></td></tr></table></div></figure>
<p>以上是一个自封闭的区段标签,代表将name.dust中的模版插入到当前位置。若文件包含路径,则用双引号包裹:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{>”dust/name” /}
</span></code></pre></td></tr></table></div></figure>
<p>标签中也可以填写参数:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{>”dust/name” foo=”Hello” bar=” World”/}
</span></code></pre></td></tr></table></div></figure>
<p>甚至可以使用动态路径:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{>”dust/{pathName}” /}
</span></code></pre></td></tr></table></div></figure>
<h2>区块(Blocks)</h2>
<p>通过拆分可以重用一个模版,但是用这种方法来派生模版有一个缺点,就是你需要记得需要在什么位置插入哪个模版,并且对每一个派生出来的模版都要重新布局一次。区块可以解决这个问题,在父模板中使用区块可以方便地在子模板中替换区块中的内容。区块也是一种特殊的区段,定义方法如下:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{+name /}
</span></code></pre></td></tr></table></div></figure>
<p>或者在区段中填写默认内容,当区块没有被替换时,将显示默认内容:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{+name}default Content{/name}
</span></code></pre></td></tr></table></div></figure>
<p>使用区块替换需要在子模板中使用拆分区段(<code>></code>)导入父模板,并使用替换区段(<code><</code>)进行替换:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{>father/}
</span><span class='line'>{<span class="nt"><name</span><span class="err">}</span><span class="na">Content</span><span class="err">{/</span><span class="na">name</span><span class="err">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>比如一个父模板可以写成这样:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><div</span> <span class="na">class=</span><span class="s">"page"</span><span class="nt">></span>
</span><span class='line'> <span class="nt"><h1></span>{+pageHeader}PayPal{/pageHeader}<span class="nt"></h></span>
</span><span class='line'> <span class="nt"><div</span> <span class="na">class=</span><span class="s">"bodyContent"</span><span class="nt">></span>
</span><span class='line'> {+bodyContent/}
</span><span class='line'> <span class="nt"></div></span>
</span><span class='line'> <span class="nt"><div</span> <span class="na">class=</span><span class="s">"footer"</span><span class="nt">></span>
</span><span class='line'> {+pageFooter}Contact Us {/pageFooter}
</span><span class='line'> <span class="nt"></div></span>
</span><span class='line'><span class="nt"></div></span>
</span></code></pre></td></tr></table></div></figure>
<p>然后保存为shared/base_template.dust文件,然后定义子模板:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{! 首先导入父模板 !}
</span><span class='line'>{>"shared/base_template"/}
</span><span class='line'>
</span><span class='line'>{! 然后定义对应的部分 !}
</span><span class='line'>{<span class="nt"><bodyContent</span><span class="err">}</span>
</span><span class='line'><span class="err"><</span><span class="na">p</span><span class="nt">></span>These are your current settings:<span class="nt"></p></span>
</span><span class='line'><span class="nt"><ul></span>
</span><span class='line'> <span class="nt"><li></span>xxxx<span class="nt"></li></span>
</span><span class='line'> <span class="nt"><li></span>yyy<span class="nt"></li></span>
</span><span class='line'><span class="nt"></ul></span>
</span><span class='line'>{/bodyContent}
</span><span class='line'>{<span class="nt"><pageFooter</span><span class="err">}</span>
</span><span class='line'> <span class="err"><</span><span class="na">hr</span><span class="nt">></span>
</span><span class='line'> <span class="nt"><a</span> <span class="na">href=</span><span class="s">"/contactUs"</span><span class="nt">></span>About Us<span class="nt"></a></span> |
</span><span class='line'> <span class="nt"><a</span> <span class="na">href=</span><span class="s">"/contactUs"</span><span class="nt">></span>Contact Us<span class="nt"></a></span>
</span><span class='line'>{/pageFooter}
</span></code></pre></td></tr></table></div></figure>
<h2>应用Dust模板</h2>
<p>至此,Dust自带的基本功能语法已经介绍完毕,目前大家可能只在测试器中使用过模板,以下将介绍如何直接在前端中应用模板。</p>
<h3>编译</h3>
<p>之前也介绍过,Dust是编译型模板,意思则是若需应用模板,首先要将模板可执行化,即将模板变成可执行的代码。如果你使用过Dust测试器,那么你会发现在你输入模板后,会在2号框中显示一个函数定义,那就是编译生成的代码。使用编译型模板有一个好处,就是当模板编译好之后,若需要重复使用模板,不需要每次都对模板重新进行分析,加快模板解析的速度,而且,模板可以预先编译好保存在服务器,甚至让前端连第一次编译的时间都节省了。</p>
<p>因此Dust库有两种发行版本:</p>
<ul>
<li>dust-core-2.0.2.js</li>
<li>dust-full-2.0.2.js</li>
</ul>
<p>前者为核心(Core)版本,其只包含模板解析的相关代码,大小只有十几k,而完全版(Full)则包含Dust的所有代码,包括编译器,大小有一百多k。对于不需要在前端进行编译的项目,仅仅需要使用核心版本即可,这也是速度比较快的做法。但是对于需要在前端动态编译的项目,则只能使用包含编译器的完全版。</p>
<p>编译模板的方法很简单,使用完全版的dust.compile()方法:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">compiled</span> <span class="o">=</span> <span class="nx">dust</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="s2">"Hello {name}!"</span><span class="p">,</span> <span class="s2">"intro"</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>其中第一个参数为模板字符串,第二个参数为模板名,函数将返回包含编译好的可执行代码的字符串。这个操作不会注册这个模板,仅进行编译,此时仍不可通过模板名来调用这段代码。</p>
<h3>注册</h3>
<p>如果直接执行一遍compiled中的代码,则模板会按之前指定的名字注册到dust,从而可以通过模板名来调用该模板。但若compiled代码未被执行过,则需要在渲染前手动将其注册到dust中,注册的方法很简单:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">dust</span><span class="p">.</span><span class="nx">loadSource</span><span class="p">(</span><span class="nx">compiled</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<h3>渲染</h3>
<p>通过编译注册可以让多套模板处于就绪状态,对于这些模板,我们可以直接用它将JSON对象渲染成HTML文本,通过调用dust.render()方法。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">dust</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="s2">"intro"</span><span class="p">,</span> <span class="p">{</span><span class="nx">name</span><span class="o">:</span> <span class="s2">"Fred"</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">out</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">out</span><span class="p">);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>
<p>这个方法接受3个参数,第一个为模板名,第二个为JSON对象,第三个是一个接受两个参数的回调函数。执行这个方法后Dust会使用注册好的对应模板对JSON对象进行处理,得出一个渲染结果字符串,然后调用回调函数,其中第一个参数包含了在处理过程中出现的错误信息,第二个参数就是渲染结果字符串。一般会在回调函数中将渲染结果插入到当前的DOM结构中,以便在浏览器中显示渲染结果。</p>
<h3>区块和拆分</h3>
<p>一般使用文件来保存模板并且使用区块和拆分是让Dust作为服务端模板时应用的技术,因为在客户端Javascript中无法很方便地对分布式文件进行操作。但是我们可以通过在本地部署模板数据,编译成可执行代码并用一个js文件来保存的方式来使用区块和拆分。</p>
<p>若在Linux平台则直接在终端安装npm和dust并使用dustc命令编译成代码,得到js文件。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nv">$ </span>npm install dustjs-linkedin
</span><span class='line'><span class="nv">$ </span>dustc input.dust output.js
</span></code></pre></td></tr></table></div></figure>
<p>或者在js引擎中使用dust.compile(),将模板复制到第一个参数,指定第二参数为其不带后缀的文件名,并将结果输出到js文件。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">output1</span> <span class="o">=</span> <span class="nx">dust</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">partialStr</span><span class="p">,</span> <span class="s2">"partial"</span><span class="p">);</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">output2</span> <span class="o">=</span> <span class="nx">dust</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">baseStr</span><span class="p">,</span> <span class="s2">"base"</span><span class="p">);</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">output3</span> <span class="o">=</span> <span class="nx">dust</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">childStr</span><span class="p">,</span> <span class="s2">"child"</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>最后在HTML中导入所有生成的js文件即可使用。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"partial.js"</span><span class="nt">></script></span>
</span><span class='line'><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"base.js"</span><span class="nt">></script></span>
</span><span class='line'><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"child.js"</span><span class="nt">></script></span>
</span></code></pre></td></tr></table></div></figure>
<p>注意此时不再需要使用dust.loadSource()来注册,因为script标签将js文件执行了一次,已经将模板注册好了。此时已可使用dust.render()进行渲染。</p>
<h2>结语</h2>
<p>至此,我们已经可以在前端中使用模板了,但是还有一些高级功能这里并未涉及,包括<code>@</code>辅助标签以及自定义扩展标签,如果有动力写Dust.js语法简介(四)的话,我将会在那介绍。除此之外,这里只提供了在Linux编译模板的一些官方方法,若需要在Windows下编译模板,则比较麻烦,有机会再写一篇如何在Windows下编译模板的教程吧。</p>
<h2>文章链接</h2>
<ul>
<li><a href="http://blog.sprabbit.com/blog/2013/08/16/introduction-dustjs-1">Dust.js语法简介(一)</a></li>
<li><a href="http://blog.sprabbit.com/blog/2013/08/17/introduction-dustjs-2">Dust.js语法简介(二)</a></li>
<li><a href="http://blog.sprabbit.com/blog/2013/08/19/introduction-dustjs-3">Dust.js语法简介(三)</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Dust.js语法简介(二)]]></title>
<link href="http://blog.sprabbit.com/blog/2013/08/17/introduction-dustjs-2/"/>
<updated>2013-08-17T16:26:00+08:00</updated>
<id>http://blog.sprabbit.com/blog/2013/08/17/introduction-dustjs-2</id>
<content type="html"><![CDATA[<p>从这篇文章开始我将介绍Dust的语法,其实内容基本上和Dust的<a href="https://github.com/linkedin/dustjs/wiki/Dust-Tutorial">Tutorial</a>差不多,可能还要简化一点。</p>
<!--more-->
<h2>Dust在线测试器</h2>
<p>首先要介绍一下Dust项目中的一个<a href="http://linkedin.github.io/dustjs/test/test.html">在线测试器</a>,在了解Dust语法的同时,在这个测试器上尝试应用学到的语法,既可以验证语法是否正确,也可以加强对语法的记忆。进入测试器后可以见到四个框,从左上、左下、右上、右下分别编号为1、2、3、4。测试时在1号框中填入一个Dust模板,然后2号框将显示该模板编译后的结果,再在3号框填入一个JSON对象,4号框中将显示最终的渲染结果。</p>
<h2>标签(Tag)</h2>
<p>Dust模板以一种嵌入到HTML中的标签的形式存在。Dust标签使用一对花括号包裹,类似于HTML标签使用一对尖括号包裹:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{name}
</span></code></pre></td></tr></table></div></figure>
<h2>注释</h2>
<p>以下标签将不会产生任何内容,即可用作注释(感叹后之间):</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{! Comment syntax !}
</span></code></pre></td></tr></table></div></figure>
<h2>键(Key)</h2>
<p>一般Dust标签的表示只有两种形式,一种是键,另一种是区段。键是一个最简单的Dust标签,其中包含的花括号中的值称之为键,对应于JSON对象的属性名,对应的属性值一般为简单类型,比如字符串,渲染后将直接以属性值代替整个标签。如果搜索不到任何匹配值,则不会返回任何数据。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{name}
</span></code></pre></td></tr></table></div></figure>
<p>在键名后面可以跟随过滤器,使用竖线分隔,一般用于选择处理“<”,“>”等特殊符号的转义:</p>
<ul>
<li>{name|s} 禁用自动转码</li>
<li>{name|h} 强制使用HTML转码</li>
<li>{name|j} 强制使用Javascript转码</li>
<li>{name|u} 使用encodeURI编码</li>
<li>{name|uc} 使用encodeURIComponent编码</li>
<li>{name|js} 将JSON对象转换为字符串</li>
<li>{name|jp} 将JSON 字符串转换为JSON对象</li>
</ul>
<p>过滤器也可以进行组合:</p>
<pre><code>{name|jp|h}
</code></pre>
<p>一些特殊字符也可以键的形式直接取值输出:</p>
<ul>
<li>{~n} 换行</li>
<li>{~r} CR换行</li>
<li>{~lb} 左花括号</li>
<li>{~rb} 右花括号</li>
<li>{~s} 空格</li>
</ul>
<h2>区段(Section)</h2>
<p>以下两个标签及其包裹的部分称之为区段,用于循环显示数据。其中“#”为开始标签,“/”为结束标签,其后的键值同样对应于JSON对象的属性名,对应的属性值一般为数组或单个对象,单个对象将被当做一个只有一个元素的数组来对待。模板会按下标对数组中的每个元素调用一次区段包裹着的模板。上一篇中的例子就是利用了区段来循环输出列表元素。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{#names}....{/names}
</span></code></pre></td></tr></table></div></figure>
<p>在区段中可以使用两个特殊的键:</p>
<ul>
<li>{$idx} 表示当前迭代的序号(从0开始)</li>
<li>{$len} 表示数组长度</li>
</ul>
<h2>上下文(Context)</h2>
<p>Dust对键或区段值的查询与javascript中对作用域链中变量值的查询类似,换而言之使用区段时会临时改变当前的上下文。</p>
<p>例如一个嵌套的JSON对象:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="s2">"name"</span><span class="o">:</span> <span class="s2">"root"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"anotherName"</span><span class="o">:</span> <span class="s2">"root2"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"A"</span><span class="o">:</span><span class="p">{</span>
</span><span class='line'> <span class="s2">"name"</span><span class="o">:</span><span class="s2">"Albert"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"B"</span><span class="o">:</span><span class="p">{</span>
</span><span class='line'> <span class="s2">"name"</span><span class="o">:</span><span class="s2">"Bob"</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>使用区段索值:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{#A}{name}{/A}
</span></code></pre></td></tr></table></div></figure>
<p>则会得到这个对象的<code>A.name</code>的值:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>Albert
</span></code></pre></td></tr></table></div></figure>
<p>因为使用区段时将上下文转移到A属性对应的对象中。</p>
<p>而使用以下区段索值:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{#A}{anotherName}{/A}
</span></code></pre></td></tr></table></div></figure>
<p>因为在对象A的属性中不存在“anotherName”属性,于是Dust会向上查询A所处的上下文,发现存在“anotherName”属性,于是得到:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>root2
</span></code></pre></td></tr></table></div></figure>
<p>若往上查找到JSON对象根部间的所有的上下文均无对应属性时将返回空白,索值不会向下查找。</p>
<h2>路径(Path)</h2>
<p>若使用不带路径的区段索值,那么相当于从JSON对象的根部开始定位区段上下文。而使用路径可以指定开始搜索的位置。路径使用标志“.”来标记标签,跟javascript语法类似。依然是这个JSON对象:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="s2">"name"</span><span class="o">:</span> <span class="s2">"root"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"anotherName"</span><span class="o">:</span> <span class="s2">"root2"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"A"</span><span class="o">:</span><span class="p">{</span>
</span><span class='line'> <span class="s2">"name"</span><span class="o">:</span><span class="s2">"Albert"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"B"</span><span class="o">:</span><span class="p">{</span>
</span><span class='line'> <span class="s2">"name"</span><span class="o">:</span><span class="s2">"Bob"</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>若我们需要取A属性下的B属性的name则可以表达成这样:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{A.B.name}
</span></code></pre></td></tr></table></div></figure>
<p>或者使用路径标记区块:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{#A.B}{name}{/A.B}
</span></code></pre></td></tr></table></div></figure>
<p>或者使用单个“.”表示当前上下文对象(当前为字符串):</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{#A.B.name}{.}{/A.B.name}
</span></code></pre></td></tr></table></div></figure>
<p>规定路径后,首先在指定的上下文进行查找name的值,找不到时不会向上追溯,而是从根部开始查找。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{#A.B}{A.name}{/A.B}
</span></code></pre></td></tr></table></div></figure>
<p>上面这个模板将会在A.B中搜索A,因为B并无A属性,所以从JSON对象根部开始找到A属性,从而找到A.name,返回“Albert”,若从根部也无法找到,则返回空白。</p>
<h2>修改上下文</h2>
<p>我们也可以在一定程度上修改上下文的关系。通过使用冒号“:”可以用冒号后面的键值代替前面的键值的父级上下文:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{#A:A2} ... {/A}
</span></code></pre></td></tr></table></div></figure>
<p>以上这个区段会屏蔽掉A的父级上下文,临时将A2作为A的父级上下文,即在A中找不到目标时不会往上回溯,而去搜索A2下的属性。</p>
<h2>区段参数</h2>
<p>在区段中可以设置参数:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span><span class="err">#</span><span class="nx">A</span><span class="p">.</span><span class="nx">B</span> <span class="nx">foo</span><span class="o">=</span><span class="s2">"Hi"</span> <span class="nx">bar</span><span class="o">=</span><span class="s2">" Good to see you"</span><span class="p">}</span>
</span><span class='line'> <span class="p">{</span><span class="nx">foo</span><span class="p">}</span> <span class="p">{</span><span class="nx">name</span><span class="p">}</span> <span class="p">{</span><span class="nx">bar</span><span class="p">}</span>
</span><span class='line'><span class="p">{</span><span class="err">/A.B}</span>
</span></code></pre></td></tr></table></div></figure>
<p>模板会将参数值替代键值标签,结果为:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>Hi Bob Good to see you
</span></code></pre></td></tr></table></div></figure>
<p>参数也可以是键名,但是赋值时的上下文在区段之外:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span><span class="err">#</span><span class="nx">A</span><span class="p">.</span><span class="nx">B</span> <span class="nx">foo</span><span class="o">=</span><span class="nx">A</span><span class="p">.</span><span class="nx">name</span> <span class="nx">bar</span><span class="o">=</span><span class="nx">anotherName</span><span class="p">}</span>
</span><span class='line'> <span class="p">{</span><span class="nx">foo</span><span class="p">}</span> <span class="p">{</span><span class="nx">name</span><span class="p">}</span> <span class="p">{</span><span class="nx">bar</span><span class="p">}</span>
</span><span class='line'><span class="p">{</span><span class="err">/A.B}</span>
</span></code></pre></td></tr></table></div></figure>
<h2></h2>
<p>至此,我们已经可以简单地将模板付诸应用了。下一节将介绍一些逻辑相关的语法。</p>
<h2>文章链接</h2>
<ul>
<li><a href="http://blog.sprabbit.com/blog/2013/08/16/introduction-dustjs-1">Dust.js语法简介(一)</a></li>
<li><a href="http://blog.sprabbit.com/blog/2013/08/17/introduction-dustjs-2">Dust.js语法简介(二)</a></li>
<li><a href="http://blog.sprabbit.com/blog/2013/08/19/introduction-dustjs-3">Dust.js语法简介(三)</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Dust.js语法简介(一)]]></title>
<link href="http://blog.sprabbit.com/blog/2013/08/16/introduction-dustjs-1/"/>
<updated>2013-08-16T09:44:00+08:00</updated>
<id>http://blog.sprabbit.com/blog/2013/08/16/introduction-dustjs-1</id>
<content type="html"><![CDATA[<p><a href="http://blog.sprabbit.com/blog/2013/08/15/introduction-client-template/">经过一轮挣扎</a>,我作出了与LinkedIn一样的选择,使用Dust.js作为模板,但是因为Dust.js缺少中文文档,导致在国内的普及率比较低。于是我决定在这里对Dust的语法进行一些必要的介绍。</p>
<!--more-->
<h2>为什么要用前端模板?</h2>
<p>在静态页面中,包括已经从后台生成的HTML中,一般很少需要应用到模板,但是随着AJAX技术的发展,不刷新页面而动态更新内容的需求越来越高。为了降低通讯成本,这种通讯技术传输的一般是一个JSON对象,而不是一整串HTML字符串,所以在前端接受JSON数据之后,还要经过处理才能按要求显示在浏览器上。若只是用纯javascript进行拼接处理,将是一个比较繁琐的过程,而且写出来的代码不直观,可读性比较低。比如如果一个JSON对象<code>people</code>是下面这样的:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="s2">"title"</span><span class="o">:</span> <span class="s2">"Famous People"</span><span class="p">,</span>
</span><span class='line'> <span class="s2">"names"</span><span class="o">:</span> <span class="p">[{</span> <span class="s2">"name"</span><span class="o">:</span> <span class="s2">"Larry"</span> <span class="p">},</span> <span class="p">{</span> <span class="s2">"name"</span><span class="o">:</span> <span class="s2">"Curly"</span> <span class="p">},</span> <span class="p">{</span> <span class="s2">"name"</span><span class="o">:</span> <span class="s2">"Moe"</span> <span class="p">}]</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>我们要把他渲染成一个HTML列表如下:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>Famous People
</span><span class='line'><span class="nt"><ul></span>
</span><span class='line'> <span class="nt"><li></span>Larry<span class="nt"></li></span>
</span><span class='line'> <span class="nt"><li></span>Curly<span class="nt"></li></span>
</span><span class='line'> <span class="nt"><li></span>Moe<span class="nt"></li></span>
</span><span class='line'><span class="nt"></ul></span>
</span></code></pre></td></tr></table></div></figure>
<p>使用纯粹的javascript将是这样的:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">people</span><span class="p">.</span><span class="nx">title</span> <span class="o">+</span> <span class="s1">'\n'</span><span class="p">;</span>
</span><span class='line'><span class="nx">result</span> <span class="o">+=</span> <span class="s1">'<ul>'</span> <span class="o">+</span> <span class="s1">'\n'</span><span class="p">;</span>
</span><span class='line'><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">people</span><span class="p">.</span><span class="nx">names</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">result</span> <span class="o">+=</span> <span class="s1">'<li>'</span> <span class="o">+</span> <span class="nx">people</span><span class="p">.</span><span class="nx">names</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">name</span> <span class="o">+</span> <span class="s1">'</li>'</span> <span class="o">+</span> <span class="s1">'\n'</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nx">result</span> <span class="o">+=</span> <span class="s1">'</ul>'</span>
</span></code></pre></td></tr></table></div></figure>
<p>当然了这只是一个比较简单的例子,而且代码具有专用性且不是最简形式,但是为了兼顾可读性和简介性这样写是比较好的。而使用dust模板将只需要一个模板:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{title}
</span><span class='line'><span class="nt"><ul></span>
</span><span class='line'>{#names}
</span><span class='line'> <span class="nt"><li></span>{name}<span class="nt"></li></span>{~n}
</span><span class='line'>{/names}
</span><span class='line'><span class="nt"></ul></span>
</span></code></pre></td></tr></table></div></figure>
<p>然后将<code>people</code>传给编译好的模板则可生成所需要的结果,非常直观。</p>
<h2>什么是Dust.js?</h2>
<p>Dustjs、dust.js或者直接叫Dust,是一种模板,一开始是由<a href="https://github.com/akdubya">Aleksander</a> 编写并于2010发布第一个版本<a href="https://github.com/akdubya/dustjs">于Github</a>。因为后台编译使用 Node.js 所以延续了在插件名后加.js的传统。Aleksander 很喜欢胡子模板 Mustache 的语法。但是Mustache缺少了Aleksander想要的特性,比如模板块和高性能。</p>
<p>从<a href="http://akdubya.github.io/dustjs/">dust.js的导引页面</a>看来,这个模板制作者还是很有诚意的。可惜这个项目已于两年前停止更新,版本停留在0.3.0。好消息是大型职业社交网<a href="http://www.linkedin.com">LinkedIn</a>也了解到了这个模板的优点和潜力,并接手了Dust.js的后续开发,最终出来的就是现在的<a href="http://linkedin.github.io/dustjs/">Dust.js(LinkedIn)</a>,为了简便起见后面继续称之为Dust。经过不断地更新,Dust目前已经到了2.0版本了。</p>
<h2></h2>
<p>由于时间关系,我还是决定将真正的语法介绍留到下一篇文章了,敬请期待。</p>
<h2>文章链接</h2>
<ul>
<li><a href="http://blog.sprabbit.com/blog/2013/08/16/introduction-dustjs-1">Dust.js语法简介(一)</a></li>
<li><a href="http://blog.sprabbit.com/blog/2013/08/17/introduction-dustjs-2">Dust.js语法简介(二)</a></li>
<li><a href="http://blog.sprabbit.com/blog/2013/08/19/introduction-dustjs-3">Dust.js语法简介(三)</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[前端模板的选择]]></title>
<link href="http://blog.sprabbit.com/blog/2013/08/15/introduction-client-template/"/>
<updated>2013-08-15T20:01:00+08:00</updated>
<id>http://blog.sprabbit.com/blog/2013/08/15/introduction-client-template</id>
<content type="html"><![CDATA[<p>最近接到一个任务,让我选一个前端模板。但是我其实连js模版实战经验都没有,为什么要让我选呢。不过接到任务就得照办了。首先得先知道什么是前端模板呢,稍微查了些百科,简单来说就是利用内嵌于HTML中的一些标记,来直观迅速生成HTML字符串的工具了,类似于后台用PHP标记<?=xxx>来生成HTML这样,而不需要繁琐的字符串拼接操作。需要在前端用javascript来使用,所以叫做前端模板。那么类似后台有多种语言,前端模板也有多种多样,以至于有人在github上做了一个应用方便大家选择前端模板:<a href="http://garann.github.io/template-chooser/">TemplateChooser</a></p>
<!--more-->
<p>虽然其中没有包括所有的模板,但是人们最常用的都在里面了,点开左边的标签设置选项,右面剩下的模板名就是符合要求的了。</p>
<p>第一项 Is this for use on the client or the server,就是模板需要运行在前端还是后台,对于前端模板当然选前台,但是不少模板是可以运行在前后端的。</p>
<p>第二项 How much logic should it have,表明你需要模板中可以包含多少逻辑处理。其中 the entirety of JS 选项代表模板中需要可以运行JS代码;just the basics 则代表模板中仅包含基本的逻辑,比如判断这类的;none at all 则表示模板中不包含任何逻辑,换而言之几乎只能做变量替换的操作。</p>
<p>第三项 Does it need to be one of the very fastest,表示你是否对速度有特别严苛的要求,yes or no。选完yes后会发现只剩三种doT.js、Microtemplating、Underscore templates,这是由一个应用来判定的:<a href="http://jsperf.com/javascript-templating-shootoff-extended">jsPerf</a>。这三种在测试中是排行前三的。但是我们发现里面评测的模板并不完全,所以其实这项并没有太大的参考价值。</p>
<p>第四项 Do you need to pre-compile templates,表示你是否需要可以预编译的模板。首先要解释一下编译的意思,对于一般编程语言,编译就是让代码转换并优化成机器可以识别的机器码,从而机器可以直接运行。这里的编译意思类似,一个模板只是一个直观的数据字符串,我们需要让他变得可执行,那么我们就要让他转变成一个可以执行的函数对象,虽然这个对象一般也是以字符串的形式存在的。是否可以预编译的差别在于,如果你的模板是固定不变的,那么如果预先编译好并将编译结果保存起来,要使用的时候就不需要再动态编译,可以减少你分析模板的时间。</p>
<p>第五项 Do you need compile-time partials,表示你是否需要在编译时的模板拆分。这里的拆分其实并不是准确的表达,但是我找不到一个更好的词来形容了。实际上这个概念很简单,就是模块化的思想,可以将多个模板中重复使用的部分拆分出来单独存成一个模板文件,而让其他需要使用这个部分的模板导入这个模板文件。这种操作一般只在服务端模板中进行,因为在前端难以动态读取后台的分布式拆分文件。但是对于可以预编译的模板,则可以预先将分布式的文件编译好,然后在前台一一导入后使用。</p>
<p>第六项 Do you want a DOM structure, or just a string,那是问你的模板是一个字符串还是一个DOM结构。关于这点我也不太清楚,因为在我的印象中模板就是一个字符串,而里面包含了所渲染的HTML字符串的直观表示。选了DOM之后,同样只剩下三种模板dom.js、pure.js、Transparency。我简单地查看了一下pure.js模板(他同时也是一个不包含逻辑的模板),发现他并不是将一个模板保存为字符串,而是直接在HTML文件中为标签添加一些特殊的类,然后渲染的时候再用选择器出这个DOM对象进行渲染,换而言之他的模板是直接内嵌在HTML文件中的!那么确实如果希望应用逻辑是不大可能的,因为必须保证模板符合XHTML规范。</p>
<p>第七项 Aside from template tags, should it be the same language before and after rendering,这项比较好理解,除了模板标签之外,模板的语法要和模板渲染后的语法一样,那么在这里我们要渲染出HTML语言,结果是显然易见的,就是模板是一种在HTML语言中内嵌标签的语言。或许你会觉得很奇怪,难道还有什么除了插入标签外的神奇的语法吗?选No之后又再一次出现了三种模板dom.js、Jade templates、Microtemplating。我再一次简单的看了下dom.js,因为他同时也是一个使用DOM结构的模板。结果发现DOM是一种完全使用Javascript的模板!他的语法还是非常直观的:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">header</span><span class="p">(</span>
</span><span class='line'> <span class="nx">h1</span><span class="p">(</span><span class="s1">'Heading'</span><span class="p">),</span>
</span><span class='line'> <span class="nx">h2</span><span class="p">(</span><span class="s1">'Subheading'</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'><span class="nx">nav</span><span class="p">(</span>
</span><span class='line'> <span class="nx">ul</span><span class="p">({</span> <span class="s1">'class'</span><span class="o">:</span> <span class="s1">'breadcrumbs'</span> <span class="p">},</span>
</span><span class='line'> <span class="nx">li</span><span class="p">(</span><span class="nx">a</span><span class="p">({</span> <span class="nx">href</span><span class="o">:</span> <span class="s1">'/'</span> <span class="p">},</span> <span class="s1">'Home'</span><span class="p">)),</span>
</span><span class='line'> <span class="nx">li</span><span class="p">(</span><span class="nx">a</span><span class="p">({</span> <span class="nx">href</span><span class="o">:</span> <span class="s1">'/section/'</span><span class="p">},</span> <span class="s1">'Section'</span><span class="p">)),</span>
</span><span class='line'> <span class="nx">li</span><span class="p">(</span><span class="nx">a</span><span class="p">(</span><span class="s1">'Subject'</span><span class="p">))));</span>
</span><span class='line'>
</span><span class='line'><span class="nx">article</span><span class="p">(</span>
</span><span class='line'> <span class="nx">p</span><span class="p">(</span><span class="s1">'Lorem ipsum...'</span><span class="p">));</span>
</span><span class='line'>
</span><span class='line'><span class="nx">footer</span><span class="p">(</span><span class="s1">'Footer stuff'</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>
<p>明白了上面的含义的话,其实还是很好选择的。关于选项中的第二项可能有点争议,到底模板需要多少逻辑呢。如果从模板的出发点来看的话,其实答案是显然易见的。有些人可能觉得功能越强大的模板越好,但是事实恰好相反,人们发明了模板就是为了直观地设计输出数据的表现形式,让显示与逻辑数据分离。此时若为了让模板支持更强大的功能而硬是往里面添加复杂的逻辑,甚至让其支持javascript,是本末倒置的,这些明明可以直接在javascript中操作的东西又何必硬塞到模板里面让其可读性降低呢。然而不包含任何逻辑毕竟不现实,因此大多数模板都提供了最基本的逻辑能力,比如遇到空对象的特殊处理方法。所以这里一般选择just the basics。</p>
<p>最后剩下来的模板也只剩6个,但是到底要如何取舍,还是不能简单的决定。经过一些对比评测[1],大家普遍认为以下三种是综合评分最高的:Mustache.js、Handlebars.js、dust.js。</p>
<p><a href="https://github.com/janl/mustache.js/">Mustache</a> 应该是最流行的模版了,显示与逻辑分离,模板语法清晰,但是逻辑功能太过缺乏,代码庞大而且效率比较低,已经停止维护超过两年。他的语法如下:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{ {#stooges} }
</span><span class='line'><span class="nt"><b></span>{ {name} }<span class="nt"></b></span>
</span><span class='line'>{ {/stooges} }
</span></code></pre></td></tr></table></div></figure>
<p><a href="https://github.com/wycats/handlebars.js/">Handlebars</a>
是Mustache的改进,显示与逻辑分离,语法兼容Mustache,可以编译成代码,改进Mustache对路径的支持,但是若需要在服务端运行需要使用服务端Javascript引擎如Node.js。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{ {#each comments} }
</span><span class='line'><span class="nt"><div</span> <span class="na">class=</span><span class="s">"body"</span><span class="nt">></span>{ {body} }<span class="nt"></div></span>
</span><span class='line'>{ {/each} }
</span></code></pre></td></tr></table></div></figure>
<p></p>
<p><a href="https://github.com/linkedin/dustjs">Dust</a>
也是显示与逻辑分离,语法比Mustache更清晰简便(少写一对花括号{}!),可以编译成代码,比Mustache提供更好的路径支持,支持更多的扩展功能,异步渲染,执行效率更高。但是若需要在服务端运行需要使用服务端Javascript引擎如Node.js。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>{#names}
</span><span class='line'><span class="nt"><li></span>{name}<span class="nt"></li></span>{~n}
</span><span class='line'>{/names}
</span></code></pre></td></tr></table></div></figure>
<p>以上三种都是最优秀的模板了,语法可以说是比较类似,但是无论从结果还是过程看Dust都有着无比强大的优势。目前Dust.js是由LinkedIn团队维护的,最近已更新到2.0版本,相比以前有更大的优化,所以我觉得选用dust.js作为模版是比较合适的。只可惜Dust.js毕竟没有胡子Mustache家族势力广泛,尤其在我大天朝,少有见到关于dust的技术文章。下次我打算尽我微薄之力,为大家介绍一下Dust的使用方法,普及一下dust这个LinkedIn推荐的模板。</p>
<p>参考:</p>
<p>[1] <a href="http://engineering.linkedin.com/frontend/client-side-templating-throwdown-mustache-handlebars-dustjs-and-more">The client-side templating throwdown: mustache, handlebars, dust.js, and more</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[从游戏服务端到Web前端]]></title>
<link href="http://blog.sprabbit.com/blog/2013/08/13/game-server-to-front-end/"/>
<updated>2013-08-13T16:03:00+08:00</updated>
<id>http://blog.sprabbit.com/blog/2013/08/13/game-server-to-front-end</id>
<content type="html"><![CDATA[<p>虽然这个标题看起来很厉害,但是其实只是我的一篇随笔,没有很大的技术参考价值,况且我无论哪个方面也没有很高的造诣。这里只是抒发一下我开始工作后的感受,在这个公司提前下班的七夕里。</p>
<p>怀着对游戏的满腔热情,我拿到了一个主营网络游戏的公司的Offer,心想,迎合我的兴趣和特长,我一定能成就一番事业。于是我在几个月前开始了实习,刚开始是一段自学期,因为公司用python作为游戏脚本,而且推荐教材是《Python核心编程》,于是前两周便都在啃那本书。然后是一个考核,决定我们这帮新来的程序猿将进入哪个项目组。我灰常荣幸地进入了公司最赚钱的游戏的服务端,顺便说一下在公司里对程序猿的划分从牛掰到水逼是服务端>客户端>应用软件>移动平台游戏>WEB,当然这只是由公司文化决定的。</p>
<!--more-->
<p>然而我的想象很快就被扑灭了,作为一个服务端的程序员,你要做的只有根据策划提出的要求,写逻辑写逻辑写逻辑。如果这是一个独立游戏,我想最有趣的地方就是写逻辑了吧,然而对于网游来说却并不是这样的。</p>
<p>这是一个已经完全引擎化的东西,基本上公司所有游戏都是用的同一个引擎,服务器引擎基本上只定义了客户端与服务端通信的方法以及数据库存储的抽象化。因此逻辑与显示被完全分离了,显示完全就是客户端做的事情,逻辑完全属于服务端,两者之间只是通过socket来相互传递命令。如果只是这样的话还不错的,逻辑与显示分离一直是很多框架所追求的,然而基本的脚本框架也都基本是从一个游戏拷贝到另一个游戏中的,所以程序员能做的基本上只是往框架里面填东西。明明可以使用更好的设计模式,更好的结构,但是为了让你从一个项目组调到另一个项目组时能很快进入状态,这些都是不允许你去改的。</p>
<p>于是随着功能的添加,局部代码只能越来越臃肿,甚至臃肿到可读性已经基本没有的程度。最后只好不再给你将一些通用的功能添加到父类里,而在子类里特殊地实现,目的只是不再降低通用部分的可读性。他们对“代码即文档”这句话痴迷到近乎疯狂的地步,甚至不允许你多写注释。</p>
<p>那么,所谓的写逻辑,就只能是一些很简单的往框架里填的逻辑,比如某人到某地触发一些什么对白,触发什么战斗,战斗后有什么奖励,收集一些什么物品,或者将这些东西组合起来做成一个任务或者活动。尽管你可以将这些东西写得很面向对象,然而这只是脚本,你写得面向对象并不是因为可扩展性好,而是可读性好,让别人更能读懂你的代码,当然这减少了你的代码量,也是一件好事。底层引擎你是不可能去接触到的,对所有普通员工来说都是闭源的,所以你只要掌握了这个写一般脚本的能力,你可以很轻松,不需要再学什么新技术,也能在这里呆个10年左右,因为技术以及架构都几乎不可能再更新了。作为一门脚本,除了bug的修复,也不需要什么更新。当然,首先你要去读懂那些没有文档,也没有注释的只能祈祷他不再用拼音命名的“即文档”的代码。</p>
<p>尽管在公司里面认为在越能赚钱的项目做越牛掰,而且公司也会将提升的程序员调往更赚钱的项目,而将更有资历的程序员调往新项目,然而一个游戏能否赚钱,实际上跟他的技术甚至程序员没有绝对的联系。因为每个游戏的技术基本是一样的!从引擎到框架,也许只有战斗系统和技能系统有所不同,但是这并不是由程序猿决定的事情,而是策划。换而言之决定一个游戏赚不赚钱是由策划决定的,而你在这样一个最赚钱的项目组里做,你面对的挑战只是更多更多更多的策划需求,而不是运用更好的技术。</p>
<p>很多业内人士都觉得游戏行业不是IT行业,一开始我很鄙视这种说法,凭什么我们运用程序设计的技术来创造虚拟世界就不是IT了呢。然而,我终于体会到,网游这种东西只是刚好用到编程的营销而已,不但技术落后,而且不思进取。我当然可以选择在这里干上十年,到时我也能成为一个富裕的人吧,仅仅是金钱上的,没有业余爱好,没有技术,没有时间,没有妹纸。。。一旦这个行业被淘汰,我必将失业,因为我只会写一定逻辑范围内的脚本,而这种技能除了在本公司之外几乎没有用武之地。</p>
<p>然而实习期间,我也没啥怨念的,仅仅是用来长经验的,越来越多同期的实习生被往下调到其他项目、客户端、还有WEB。最后我成为了基本被组长认同的实习生之一。但是正式入职第二天我想到我的将来,提出了转职,转往网站部从事网站开发。这当然是个令组长甚至主管都震惊的决定,没有资格留下来的人被调往网站部,而一个及格个人却主动申请调往网站部。他们甚至因此而添加了一条入职未满一年的人禁止提出转职的规定。他们用来挽留我的理由除了钱、还是钱,但是我知道有很多东西是无法用钱来衡量的。我花了九牛二虎之力东拉西扯两天后终于让他们让我转职了。</p>
<p>衡量之后,我发现做网站是比较符合我的情况,而且可以直接接触到最新的技术。比起后端也是基本逻辑加数据操作,我还是觉得比较有设计感的前端更适合我这个游戏制作人,于是我选择了做前端JS。我觉得这个职位还是比较多元化的,虽然只写JS,但是涉及的方面也可以很广泛,从页面逻辑,到页面特效,从前端JS到后台也可以用JS(Node),从PC到移动端,从数据交换到数据渲染,从页面功能到用户体验,JS能做到的东西比我想象中要多很多。可惜JS程序员在公司的地位没有得到重视,专注于前端的程序员不多,也没有统一规范,不过好消息是公司将越来越重视这一方面,将前端JS从后台人员自己编写中分离出来,我转职后不久便要我起草一份Javascript编程规范,包括命名、语法、文档注释、面向对象、前端模板等的规范。所以我还是觉得能转到前端还是挺不错的。</p>
<p>最重要的一点是,我有了自己的时间,有了外网机!在服务端为了防止泄密,是没有外网机的,用一台内网机你甚至见不到机箱,所以除了工作之外,你在公司几乎干不了别的事情,技术不会更新,只要懂了基本语法,基本不需要到网上查资料,加班即使没事干,也只能玩自己的游戏项目。为了坚持我的同人创作,我觉得外网机是基本的条件。</p>
<p>以后可能会陆续发些关于前端的文章吧,虽然以前我也没发过什么技术文章,主要是技术太烂拿不出手,今后就以学习交流的态度来写些东西吧。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Sicily Android 小应用]]></title>
<link href="http://blog.sprabbit.com/blog/2013/01/17/android-moe-sicily/"/>
<updated>2013-01-17T15:46:00+08:00</updated>
<id>http://blog.sprabbit.com/blog/2013/01/17/android-moe-sicily</id>
<content type="html"><![CDATA[<p>蹬蹬,我是来报告<a href="http://www.sprabbit.com/sicily/">Sicily</a>的进展的,在密锣紧鼓的制作下,Sicily终于有幸在今年内推出了(PIA~到底要等到什么时候啊!</p>
<p>好吧,稍安勿躁,在游戏推出之前先让茜茜酱在手机里安抚一下大家的心灵吧。</p>
<p><img src="http://blog.sprabbit.com/images/android_sicily_widget.jpg" alt="Sicily Widget" /></p>
<p><img src="http://blog.sprabbit.com/images/android_sicily_main.jpg" alt="Sicily Main" /></p>
<!--more-->
<p>这是一个灰常简单的卖萌Android程序,基于Android2.1以上系统,主程序打开后点任何地方可以让茜茜酱换对白,按菜单键可以做一下简单的设置,包括换称呼等。程序包括一个桌面小部件,跟主程序有相同的卖萌功能。点击小部件中的卖萌按钮可以换对白,点击茜茜莉可以打开主程序。</p>
<p>注意要安装在手机上才能看到桌面小部件哦。目前只有简单的卖萌功能,说不定以后可以添加闹钟,定时提醒等功能呢,敬请期待吧。。</p>
<p>另外吐槽一下Google Play的开发者认证,好麻烦啊,又没钱,所以没放到上面,只能这样发布了。</p>
<p>程序:宗师</p>
<p>美术:林卯</p>
<p>立绘:Penslip</p>
<p>下载地址: <a href="http://pan.baidu.com/share/link?shareid=166768&uk=872546290">百度网盘</a></p>
]]></content>
</entry>