<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
> <channel><title>笨活儿 &#187; 前端开发</title> <atom:link href="http://blog.benhuoer.com/category/web-technology/web-apps-development/feed" rel="self" type="application/rss+xml" /><link>http://blog.benhuoer.com</link> <description>请用力生活</description> <lastBuildDate>Mon, 02 Jan 2012 16:05:26 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /> <item><title>浅谈前端新人的职业规划</title><link>http://blog.benhuoer.com/posts/career-plans-of-front-end-newbies.html</link> <comments>http://blog.benhuoer.com/posts/career-plans-of-front-end-newbies.html#comments</comments> <pubDate>Sun, 06 Dec 2009 14:56:17 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[生活琐碎]]></category> <category><![CDATA[职业规划]]></category> <guid
isPermaLink="false">http://blog.benhuoer.com/?p=1858</guid> <description><![CDATA[拿到淘宝offer已经有一段时间，西湖、百淘、D2、实习、各位前端牛人的亲身指导，美好的生活正向我招手。本来决定12月7号报道，但因为一些不可抗力，行程有变（事实上能否进入淘宝工作尚有变数）。在这焦急的等待过程中，还是静下心来，整理一下最近关于职业规划方面的诸多思考，希望能对和我一样的前端新人们有所帮助。 淘宝一面时，与一舟的谈话中很大一部分内容和自己的职业规划有关，二面时也和小马谈及许多关于前端未来的东西。后来试玩Google Wave，又心血来潮发起了一个《重构是否有必要单独作为一项职业》的问题。我承认，这个问题很讨打，尤其是对“重构界”的各位大大来说。想来也真是好笑，我实在太小心眼儿了，当初还在庆幸腾讯有一个专门的页面重构职位（因为我编程基础很差，只会CSS），被他们鄙视后，发觉了这职位其实大有学问，反而开始怀疑起它的必要性来。不过这个不是重点，重点是在这个怀疑的过程中，我对自己在前端领域该如何发展，有了更为理性和系统的认识。 前端新人哪里来？ 我想相对于其他技术职位来说，前端算是最不挨踢的IT职位了。我注意到很多校招进来的“页面重构师”、“前端开发工程师”等等都是非计算机相关专业的（像我，木材科学&#8230;. 扯蛋~）。这当然是因为互联网行业吸引人以及html和CSS入门起点低，大学里尚能全民考C（计算机二级），全民做网页有什么不可以？而且，因为职位所处位置的交叉性，注定有很多前端人员是转行而来： 1. 设计师转前端 这个最常见。小公司里的“美工”至今还干着这样的工作 —— 出图（Photoshop） -&#62; 切图（HTML/CSS）。我本人也是因为帮我姐（设计师+代码盲）切图才踏上前端这个道路的。搞设计出身的前端有一个优势是能更好地把握设计稿的表现重点，对于某些视觉设计师不合规范的操作能轻松地化解。劣势也很明显，缺乏数理基础，写出的代码不够严谨，JavaScript基础也普遍较差，不能做真正的“前端开发”。 2. 后台程序员转前端 淘宝的第一位前端工程师本身是写Java的，今年校招也有一位同学面Java结果被推到前端然后被录取的（哇，复杂的中文句式）。之所以现在前端有很多非计算机专业的人，还有一大原因是学计算机的都“不屑于”来搞前端。你说学四年计算机，结果跑去切图写CSS，丢不丢人？所以从后台转战前端的，一般也要去搞所谓的Web Apps，基于Ajax和各种复杂架构的Web运用。而这一技术方向，其实才是前端的大势所趋（下文再议）。 3. 网虫转前端 现在很多小孩，特喜欢上网，老打游戏也没意思，所以想学点互联网相关的东西，首选自然是前端了！（因为简单嘛。）有兴趣搞这些的90后，个个成了全才：Photoshop能玩，CSS能玩，php也能玩…… 包括奶瓶嘴作者在内的几位Twitter名人就是其中的典型…… 作为“互联网重度用户”，有一大优势，那就是对网页结构、交互需求的直观理解，懂得网民需要些什么，写出的程序也往往有更佳的易用性。当然，易用性要靠所谓“交互设计师”，不过，交互设计不也是前端的一部分么？ 此外，还有很多在实践中成长起来的站长，也还是有一定的“前端修养”。可能他们最初就只是想搞几个站玩玩，在不断建站的过程中学到一些前端技术。有些人在前端方面精专下去，有些人则持续地做着重复性的工作或一直坐吃山空。此是题外话，不表。 前端新人何处去？ 从不同渠道接触前端的同学自然会走不同的道路，而前端作为联系服务器数据与用户的纽带，作为视觉设计与程序逻辑的碾钵，也发散出很多不同的分支。 面试前准备自我介绍时我写过一些要点（后来因为紧张没有用上）： 我认为平常做网页时，我能获得的心理满足包括： 设计中的美学体验 同时作为用户和设计师，完成一项交互产品时的参与感 coding时的逻辑性对自己的锻炼 debugging完成后的成就感 这其实大致描述了在前端领域可能面对的挑战——视觉，交互，前端开发。这也正是大部分互联网公司UED部门的职位划分。平常所说的前端，一般指狭义的“前端开发”，此文标题里所说的“前端新人”，也是指作为程序员的各位刚入行的前端开发者。程序员有什么成长轨迹，前端新人自然也八九不离十——一日千行代码，钻研细节成为技术大拿，自写程序贡献开源社区，出书立著；学习管理经验，负责团队项目架构，跳槽或创业，当老板赚大钱…… 有一些搞前端的同学，投身这个职位时并没有意识到自己是名程序员（说实话，我本人现在对“程序员”这个称谓的认同感也不强）。他们进入这个行业的初期，就是一“做网页的”，或出于个人兴趣，或出于工作需求（传奇的网络工作部），可以说是在一种“全民有个站”的浪潮中成长起来的。他们什么都会一点儿，设计、交互、SEO、站点架构，都是在潜移默化中进行着无意识实践（或有意识的浅实践）。而一旦决定把“做网页”当做自己赖以谋生的职业，这样模糊的定位肯定行不通了。你要自信地对自己说：“其实，我是一名前端工程师（or 交互设计师 / 视觉设计师）。” 不然你就只能吃青春饭，干一些“笨活儿”，走不出一条可持续发展之路。 避免成为“死做网页的” 如果你一定要说我是做网页的，可不可以不要在前面加‘死’字。 个人觉得，现在搞前端的确是要什么都会，什么都要了解。在这种“大前端”的趋势下，先有一个明确的目标职业比较重要。你是更爱设计还是代码？亦或者用户研究更对你味？小公司（小项目）里没有那么明确的职能划分，要求你什么都会，这无可厚非，而且对你的成长很有帮助。但做到一定程度，确立一个能力重点，是十分有必要的。 拿“前端开发”这一块来说，有重视视觉的展示类站点，有重视交互的应用型站点，前端开发也自然地划分出两个方向—— 普通应用和RIA。普通应用只需单纯的psd2html，把psd文件转化成html。而RIA则需要和“广义前端”的各个部门分工协作，同时又兼具较高的程序员素养（算法、逻辑严密性，etc&#8230;）。话说回来，psd转html的过程也大有学问，很多CSS tricks让人抓狂，页面重构的细节多多，而且别忘了，它还是RIA的前期准备。考虑到将来Web应用的复杂性（交互越傻瓜化，支撑交互的脚本就越复杂），互联网产品的迭代周期越来越短，分工合作乃大势所趋。要避免成为“死做网页的”，就要理解这个“分工”与“合作”的过程，并在某一方面有所精专（要么CSS，要么JS，要么Flash），同时不断学习其他相关技能。 在这一点上，我坚持着两个信条： 不轻易重复自己 不断学习 不论做设计还是写代码，我都不喜欢重复自己。新鲜的布局往往让我激动万分。只要看到新的技巧，就要在下一个项目里亲自实践。这也是为什么我只做过五六个站（一些小练习不算），却能面上淘宝的原因（好吧，其实是因为运气，哈哈）。 而怎么选择自己的能力重点，也是一个问题。在面试前，我如此帮自己分析： 平时做整套网页，前端coding所花时间最多。项目需求、学习条件所限，导致我在网页视觉设计和交互设计上的学习，不及前端开发深入，可能还不能满足融入一个大公司团队的需求。而且前两者需要很强的沟通能力，相对来说，写代码的活儿独立性更强，应该更适合我一些。 现在想来也不无道理，但随着工作的深入，自身能力的提高，兴趣点发生转移也不是不可能。总之，无论如何选择职业，都以能实现自己已有长处，同时不埋没自己的潜能为准。 追随职业的发展需求 互联网瞬息万变，前端行业发展喜人，Web 2.0网站风光无限，同时也给从业者提出很多新的要求。而你跟随时代的脚步有多紧，很大程度上决定了你将来会有多成功。前端开发这一职位，将来会怎么发展；如果还有新人转过来，会是程序员们更适合，还是设计师们更适合？把这个问题想通了，也就预知了前端的未来。 HTML5/CSS3会带来什么？ HTML5新增了很多方便富应用的标签，CSS3新增了很多方便视觉设计的属性，这即能简化开发，也提供了功能实现上的更多可能。更强大的Web应用，更灵活而方便的构建方式，更需要前端人员具有“大前端”的思维。是理性的程序员更容易大起来，还是感性的设计师更容易呢？ [...]<div
class="related-post"> 咱再换个话题？&rarr;&nbsp;《<a
href="http://blog.benhuoer.com/posts/a-small-survey.html" rel="bookmark">一个小调查</a>》</div> ]]></description> <content:encoded><![CDATA[<p>拿到淘宝offer已经有一段时间，西湖、<a
href="http://ued.taobao.com/blog/2008/05/16/baitao26/" target="_blank">百淘</a>、<a
href="http://www.d2forum.org" target="_blank">D2</a>、实习、各位前端牛人的亲身指导，美好的生活正向我招手。本来决定12月7号报道，但因为一些不可抗力，行程有变（事实上能否进入淘宝工作尚有变数）。在这焦急的等待过程中，还是静下心来，整理一下最近关于职业规划方面的诸多思考，希望能对和我一样的<strong>前端新人</strong>们有所帮助。</p><p>淘宝一面时，与一舟的谈话中很大一部分内容和自己的职业规划有关，二面时也和<a
href="http://ued.taobao.com/blog/author/zhaozexin/" target="_blank">小马</a>谈及许多关于前端未来的东西。后来试玩Google Wave，又心血来潮发起了一个《<a
href="https://wave.google.com/wave/#restored:wave:googlewave.com!w%252BXkAj6LwSP" target="_self">重构是否有必要单独作为一项职业</a>》的问题。我承认，这个问题很讨打，尤其是对“重构界”的各位大大来说。想来也真是好笑，我实在太小心眼儿了，当初还在庆幸腾讯有一个专门的<strong>页面重构</strong>职位（因为我编程基础很差，只会CSS），被他们鄙视后，发觉了这职位其实大有学问，反而开始怀疑起它的必要性来。不过这个不是重点，重点是在这个怀疑的过程中，我对自己在前端领域该如何发展，有了更为理性和系统的认识。<br
/> <span
id="more-1858"></span></p><h3>前端新人哪里来？</h3><p>我想相对于其他技术职位来说，前端算是<strong>最不挨踢的IT职位</strong>了。我注意到很多校招进来的“页面重构师”、“前端开发工程师”等等都是非计算机相关专业的（像我，木材科学&#8230;. 扯蛋~）。这当然是因为互联网行业吸引人以及html和CSS入门起点低，大学里尚能全民考C（计算机二级），全民做网页有什么不可以？而且，因为职位所处位置的交叉性，注定有很多前端人员是转行而来：</p><h4>1. 设计师转前端</h4><p>这个最常见。小公司里的“美工”至今还干着这样的工作 —— 出图（Photoshop） -&gt; 切图（HTML/CSS）。我本人也是因为帮我姐（设计师+代码盲）切图才踏上前端这个道路的。搞设计出身的前端有一个优势是能更好地把握设计稿的表现重点，对于某些视觉设计师不合规范的操作能轻松地化解。劣势也很明显，缺乏数理基础，写出的代码不够严谨，JavaScript基础也普遍较差，不能做真正的“前端<strong>开发</strong>”。</p><h4>2. 后台程序员转前端</h4><p>淘宝的第一位前端工程师本身是写Java的，今年校招也有一位同学面Java结果被推到前端然后被录取的（哇，复杂的中文句式）。之所以现在前端有很多非计算机专业的人，还有一大原因是学计算机的都“不屑于”来搞前端。你说学四年计算机，结果跑去切图写CSS，丢不丢人？所以从后台转战前端的，一般也要去搞所谓的Web Apps，基于Ajax和各种复杂架构的Web运用。而这一技术方向，其实才是前端的大势所趋（下文再议）。</p><h4>3. 网虫转前端</h4><p>现在很多小孩，特喜欢上网，老打游戏也没意思，所以想学点互联网相关的东西，首选自然是前端了！（因为简单嘛。）有兴趣搞这些的90后，个个成了全才：Photoshop能玩，CSS能玩，php也能玩…… 包括奶瓶嘴作者在内的几位Twitter名人就是其中的典型…… 作为“互联网重度用户”，有一大优势，那就是对网页结构、交互需求的直观理解，懂得网民需要些什么，写出的程序也往往有更佳的易用性。当然，易用性要靠所谓“交互设计师”，不过，交互设计不也是前端的一部分么？</p><p>此外，还有很多在实践中成长起来的站长，也还是有一定的“前端修养”。可能他们最初就只是想搞几个站玩玩，在不断建站的过程中学到一些前端技术。有些人在前端方面精专下去，有些人则持续地做着重复性的工作或一直坐吃山空。此是题外话，不表。</p><h3>前端新人何处去？</h3><p>从不同渠道接触前端的同学自然会走不同的道路，而前端作为联系服务器数据与用户的纽带，作为视觉设计与程序逻辑的碾钵，也发散出很多不同的分支。</p><p>面试前准备自我介绍时我写过一些要点（后来因为紧张没有用上）：</p><blockquote><p>我认为平常做网页时，我能获得的心理满足包括：</p><ol><li>设计中的美学体验</li><li>同时作为用户和设计师，完成一项交互产品时的参与感</li><li>coding时的逻辑性对自己的锻炼</li><li>debugging完成后的成就感</li></ol></blockquote><p>这其实大致描述了在前端领域可能面对的挑战——视觉，交互，前端开发。这也正是大部分互联网公司UED部门的职位划分。平常所说的前端，一般指狭义的“前端开发”，此文标题里所说的“前端新人”，也是指<a
title="《关于前端开发这份工作》- 土豆网 小麦" href="http://www.mikkolee.com/261" target="_blank"><strong>作为程序员</strong></a>的各位刚入行的前端开发者。程序员有什么成长轨迹，前端新人自然也八九不离十——一日千行代码，钻研细节成为技术大拿，自写程序贡献开源社区，出书立著；学习管理经验，负责团队项目架构，跳槽或创业，当老板赚大钱……</p><p>有一些搞前端的同学，投身这个职位时并没有意识到自己是名程序员（说实话，我本人现在对“程序员”这个称谓的认同感也不强）。他们进入这个行业的初期，就是一“<strong>做网页的</strong>”，或出于个人兴趣，或出于工作需求（传奇的<em>网络工作部</em>），可以说是在一种“全民有个站”的浪潮中成长起来的。他们什么都会一点儿，设计、交互、SEO、站点架构，都是在潜移默化中进行着无意识实践（或有意识的<strong>浅</strong>实践）。而一旦决定把“做网页”当做自己赖以谋生的职业，这样模糊的定位肯定行不通了。你要自信地对自己说：“其实，我是一名<strong>前端工程师</strong>（or 交互设计师 / 视觉设计师）。” 不然你就只能吃青春饭，干一些“笨活儿”，走不出一条可持续发展之路。</p><h4>避免成为“死做网页的”</h4><blockquote><p>如果你一定要说我是做网页的，可不可以不要在前面加‘死’字。</p></blockquote><p>个人觉得，现在搞前端的确是要什么都会，什么都要了解。在这种“<strong>大前端</strong>”的趋势下，先有一个明确的目标职业比较重要。你是更爱设计还是代码？亦或者用户研究更对你味？小公司（小项目）里没有那么明确的职能划分，要求你什么都会，这无可厚非，而且对你的成长很有帮助。但做到一定程度，<strong>确立一个能力重点</strong>，是十分有必要的。</p><p>拿“前端开发”这一块来说，有重视视觉的<strong>展示类站点</strong>，有重视交互的<strong>应用型站点</strong>，前端开发也自然地划分出两个方向—— 普通应用和<a
title="维基百科对“RIA”的定义" href="http://zh.wikipedia.org/zh-cn/RIA" target="_self">RIA</a>。普通应用只需单纯的<a
title="把psd转化成html文件" href="http://www.psd2html.com/" target="_blank">psd2html</a>，把psd文件转化成html。而RIA则需要和“广义前端”的各个部门分工协作，同时又兼具较高的程序员素养（算法、逻辑严密性，etc&#8230;）。话说回来，psd转html的过程也大有学问，很多CSS tricks<a
href="http://www.99css.com/?p=206" target="_blank">让人抓狂</a>，页面重构的细节多多，而且别忘了，它还是RIA的前期准备。考虑到将来Web应用的复杂性（交互越傻瓜化，支撑交互的脚本就越复杂），互联网产品的迭代周期越来越短，分工合作乃大势所趋。<strong>要避免成为“死做网页的”，就要理解这个“分工”与“合作”的过程，并在某一方面有所精专（要么CSS，要么JS，要么Flash），同时不断学习其他相关技能。</strong></p><p>在这一点上，我坚持着两个信条：</p><ol><li>不轻易重复自己</li><li>不断学习</li></ol><p>不论做设计还是写代码，我都不喜欢重复自己。新鲜的布局往往让我激动万分。只要看到新的技巧，就要在下一个项目里亲自实践。这也是为什么我只做过五六个站（一些小练习不算），却能面上淘宝的原因（好吧，其实是因为运气，哈哈）。</p><p>而怎么选择自己的能力重点，也是一个问题。在面试前，我如此帮自己分析：</p><blockquote><p>平时做整套网页，前端coding所花时间最多。项目需求、学习条件所限，导致我在网页视觉设计和交互设计上的学习，不及前端开发深入，可能还不能满足融入一个大公司团队的需求。而且前两者需要很强的沟通能力，相对来说，写代码的活儿独立性更强，应该更适合我一些。</p></blockquote><p>现在想来也不无道理，但随着工作的深入，自身能力的提高，兴趣点发生转移也不是不可能。总之，无论如何选择职业，都以<strong>能实现自己已有长处，同时不埋没自己的潜能</strong>为准。</p><h3>追随职业的发展需求</h3><p>互联网瞬息万变，前端行业发展喜人，Web 2.0网站风光无限，同时也给从业者提出很多新的要求。而你跟随时代的脚步有多紧，很大程度上决定了你将来会有多成功。<strong>前端开发</strong>这一职位，将来会怎么发展；如果还有新人转过来，会是程序员们更适合，还是设计师们更适合？把这个问题想通了，也就预知了前端的未来。</p><h4>HTML5/CSS3会带来什么？</h4><p><a
href="http://blog.benhuoer.com/tag/html5" target="_blank">HTML5</a>新增了很多方便富应用的标签，CSS3新增了很多方便视觉设计的属性，这即能简化开发，也提供了功能实现上的更多可能。更强大的Web应用，更灵活而方便的构建方式，更需要前端人员具有“大前端”的思维。是理性的程序员更容易<strong>大</strong>起来，还是感性的设计师更容易呢？</p><h4>IE6什么时候能死？</h4><p>浏览器兼容一直是前端开发的重中之重。既是最费时也最无趣的部分，也是需要前端开发作为独立职位的一大原因。既有人抱怨“<a
href="http://blog.benhuoer.com/posts/ie6-must-die.html" target="_blank">IE6去死吧！</a>”，也有人说“IE6死了，我们就没工作啦”（当然，后者目光比较短浅）。IE6已经活了整整10年，上个月淘宝的访客还有70%是IE6用户。IE6一日不死，HTML5/CSS3这些新东西就一日不能全面部署。</p><p>不过，IE6生命力再顽强，它总归是会死的（浏览器标准会越发统一）。是否能把握先机，决定了你将来的竞争力。</p><h4>跨平台，跨设备的前端</h4><p>互联网前所未有地慎入移动设备。君不见，<a
href="http://space.tv.cctv.com/page/PAGE1258358922938572" target="_blank">手机黄祸</a>的影响力已经大道让家长们个个如坐针毡。作为前端开发人员，这些社会问题我们无力过问，但我们至少能看出，手机等移动设备上的开发潜力是非常大的。淘宝已经新成立了无限事业部，联通“<a
href="http://v.youku.com/v_show/id_XMTMyNjk0MjA4.html" target="_blank">iPhone拥有各种应用程序</a>”的广告铺天盖地袭来，你还在等什么呢？</p><h4>前端和后台同质化，交互与视觉何去何从？</h4><p>所谓Web App被大力提倡，很多前端程序已经比某些后台程序还要复杂。当你投身于复杂的JavaScript海洋时，心中对交互和视觉还能保有多少敬畏？嗯，这个问题比较悬了，还待我真的能写得出复杂程序时再议。</p><h4>安全、性能，你不可不知之事</h4><p>这些东西，就是“专业”和“半罐水”的区别。互联网上有很多渠道可以接触这些新热点，我不再赘言。</p><h4>算法，Geek的乐趣</h4><p>JavaScript游戏，JavaScript绘图，酷炫的ActionScript动画，你能写出来几个？</p><h3>你的意见呢？</h3><p>我是不想再在前端方面干“笨活儿”了，所以我打算把技术文章都转移到 <a
title="千吨泥的前端博客" href="http://blog.ktmud.com/" target="_blank">亲泥巴 &#8211; Kiss The Mud</a> ，本文将是笨活儿博客上最后一篇前端技术相关的文章。各位大大，各位新人们，你对这个问题有什么看法？想听听你的意见。</p><div
class="related-post"><p>咱再换个话题？&rarr;&nbsp;《<a
href="http://blog.benhuoer.com/posts/britains-got-talent-callum-francis.html" rel="bookmark">[Britain's Got Talent]英国达人 &#8211; 快乐小少年 Callum Francis</a>》</p></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>, <a
href="http://blog.benhuoer.com/category/personal-life" title="查看 生活琐碎 中的全部文章" rel="category tag">生活琐碎</a>        标签: <a
href="http://blog.benhuoer.com/tag/%e5%89%8d%e7%ab%af%e5%bc%80%e5%8f%91" rel="tag">前端开发</a>, <a
href="http://blog.benhuoer.com/tag/%e8%81%8c%e4%b8%9a%e8%a7%84%e5%88%92" rel="tag">职业规划</a></div><p><small>©2009 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/career-plans-of-front-end-newbies.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/career-plans-of-front-end-newbies.html#comments" target="_blank">已经有23条评论了</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/career-plans-of-front-end-newbies.html&title=浅谈前端新人的职业规划&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/career-plans-of-front-end-newbies.html/feed</wfw:commentRss> <slash:comments>23</slash:comments> </item> <item><title>淘宝开源编辑器KISSY Editor试用报告</title><link>http://blog.benhuoer.com/posts/try-out-report-of-kissy-editor.html</link> <comments>http://blog.benhuoer.com/posts/try-out-report-of-kissy-editor.html#comments</comments> <pubDate>Thu, 29 Oct 2009 11:57:57 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[RTE]]></category> <category><![CDATA[淘宝]]></category> <guid
isPermaLink="false">http://blog.benhuoer.com/?p=1834</guid> <description><![CDATA[前几天淘宝发布了自己的富文本编辑器KISSY Editor，主要开发者是TaobaoUED的前端工程师玉伯，网上的可视化富文本编辑器众多，本人前段时间也因为要做一个论坛，尝试过在网页中整合这些已有的编辑器（因为自己实在写不出来啊…… =.= ）。网上已有的编辑器基本试了个遍，最后选定了人人网的实现方式——自写插件整合TinyMCE。不仅参考了他们的源代码，而且很无耻地盗链了xnimg.cn上的 js 文件（示例 发布后又发现了一些bug，还没来得及修正）。咳咳，只是学习学习而已，还望淫淫的同学不要来追究我的责任。 作为行业标杆的淘宝前端放出自己的开源编辑器，当然要关注一下。 首先简要评价一下我用过的一些编辑器（比较八卦，技术牛人请自动跳过）： CKEditor 以前的FCKEditor，最老牌的JavaScript RTE之一，换名字后的新网站很漂亮，但是皮肤比较丑，所以我自己做站肯定不会用他。目前在用CKEditor或FCKEditor的网站包括译言、cnBeta、百度空间等&#8230; TinyMCE 界面很优雅，最出名的应用就是WordPress后台的文章编辑页面了&#8230; 文档完善，自定义插件也相当容易。这大概也是人人网选用TinyMCE的一大原因。 Google Docs的编辑器 岂可用“强大”二字形容。必须说“很好很强大”&#8230;. 不过我辈只有观瞻的分，人家没有开源，开了源你也用不上&#8230; QQ邮箱的编辑器 小巧而强大，但用户体验欠佳。而且英文版的时候，在Firefox下是一塌糊涂……（不知道现在修正过来没有） QQ空间的编辑器 一些交互细节值得称道，但可用性不敢恭维。 搜狐白社会的编辑器 简单的功能造就了迅猛的加载速度。icon有点丑。=.= Discuz的编辑器 完全就是一个怪物。 此外，还有NicEdit、openwysiwyg等独立js编辑器，和一些基于类库的编辑器。jQuery有jwysiwyg (读作/dʒei&#8217;wiziwig/)，YUI有YUI RTE，mootools也有wysiwyg插件，不过好像都缺少后续更新。还是TinyMCE和CKEditor比较活跃啊~ 淘宝此次发布的编辑器，基于YUI构建，而且是YUI 2.x，诚如“摇滚肉包子”所言，这多多少少会给编辑器的推广带来一些阻碍。但到底好不好用呢？还是试过之后才知道： 1. 界面 现在这款皮肤，和Google Docs很接近，字体颜色拾取器也是借鉴了Google Docs，很好用。总体来说清新舒爽，不油不腻，简洁实用&#8230;  不过不太喜欢字体下拉菜单的蓝色： 这是绝对的链接色。这种菜单，用黑色就很好： （弹出层和按钮左侧有两个像素的距离，我不知道作者是不是故意不对齐的。） 期待淘宝UED的视觉设计达人们能加入到后续版本的开发中，设计出一套更加漂亮的皮肤来。感觉淘宝整站的这种“外凸渐变”实在太多了，不够elegant&#8230; 据说插入链接/图片的浮动层样式参考了搜狐白社会，十分紧凑，适合这种小巧的社区发帖编辑器。 2. 功能 目前只实现了一些常用的编辑器功能，字体样式、图片和链接插入、缩进和对齐等。没有清除样式的按钮，直接添加标题（h1~h6）、引用（blockquote）等语义化标签的按钮也没有，从Word中复制内容得到的html源码也十分混乱。不过通过查看js源码，可以看出作者预留了很多接口，底层代码也算是博采众长，插件和皮肤和的自定义还算方便。 作者透露的开发计划是： 紧接着的二期里，将进一步完善基础架构和插件体系，并提供 Undo/Redo, 插入Flash, 表格编辑和预置模板等功能。 另外一些细节，比如说插入图片时URL没有基本的正则验证，当没有p标签包裹时按回车键只会出现br换行，字体的样式和颜色是使用的font标签来设置，等等…… 可能会让一些细节控/语义控觉得受不了。 更多bug和改进建议可以参考updates list。（话说淘宝影响力就是大啊，发布不过一周，提交的bug已经近80个了&#8230;） 3. [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p>前几天淘宝发布了自己的富文本编辑器<a
href="http://ued.taobao.com/blog/2009/10/26/kissy-editor/" target="_blank">KISSY Editor</a>，主要开发者是<a
href="http://ued.taobao.com" target="_blank">TaobaoUED</a>的前端工程师<a
href="http://lifesinger.org/" target="_blank">玉伯</a>，网上的可视化富文本编辑器众多，本人前段时间也因为要做一个论坛，尝试过在网页中整合这些已有的编辑器（因为自己实在写不出来啊…… =.= ）。网上已有的编辑器基本试了个遍，最后选定了人人网的实现方式——自写插件整合TinyMCE。不仅参考了他们的源代码，而且很无耻地盗链了xnimg.cn上的 js 文件（<a
href="http://dididadi.com/post.php?action=newthread&amp;fid=8&amp;editmode=1" target="_blank">示例</a> <em>发布后又发现了一些bug，还没来得及修正</em>）。咳咳，只是学习学习而已，还望淫淫的同学不要来追究我的责任。</p><p>作为行业标杆的淘宝前端放出自己的开源编辑器，当然要关注一下。<span
id="more-1834"></span></p><p>首先简要评价一下我用过的一些编辑器（比较八卦，技术牛人请<a
href="#skip001">自动跳过</a>）：</p><ol><li><a
href="http://ckeditor.com/" target="_self">CKEditor</a> 以前的FCKEditor，最老牌的JavaScript RTE之一，换名字后的新网站很漂亮，但是皮肤比较丑，所以我自己做站肯定不会用他。目前在用CKEditor或FCKEditor的网站包括译言、cnBeta、百度空间等&#8230;</li><li><a
href="http://tinymce.moxiecode.com/" target="_blank">TinyMCE</a> 界面很优雅，最出名的应用就是WordPress后台的文章编辑页面了&#8230; 文档完善，自定义插件也相当容易。这大概也是人人网选用TinyMCE的一大原因。</li><li><a
href="https://docs.google.com">Google Docs的编辑器</a> 岂可用“强大”二字形容。必须说“很好很强大”&#8230;. 不过我辈只有观瞻的分，人家没有开源，开了源你也用不上&#8230;</li><li><a
href="http://mail.qq.com">QQ邮箱的编辑器</a> 小巧而强大，但用户体验欠佳。而且英文版的时候，在Firefox下是一塌糊涂……（不知道现在修正过来没有）</li><li><a
href="http://qzone.qq.com">QQ空间的编辑器</a> 一些交互细节值得称道，但可用性不敢恭维。</li><li><a
href="http://bai.sohu.com/app/blog/entry/edit.do" target="_self">搜狐白社会的编辑器</a> 简单的功能造就了迅猛的加载速度。icon有点丑。=.=</li><li><a
href="http://www.discuz.net">Discuz的编辑器</a> 完全就是一个怪物。</li></ol><p>此外，还有<a
href="http://nicedit.com/demos.php" target="_blank">NicEdit</a>、<a
href="http://www.openwebware.com/wysiwyg/demo.shtml" target="_self">openwysiwyg</a>等独立js编辑器，和一些基于类库的编辑器。jQuery有<a
href="http://code.google.com/p/jwysiwyg/" target="_blank">jwysiwyg</a> (读作/dʒei&#8217;wiziwig/)，YUI有<a
href="http://developer.yahoo.com/yui/editor/" target="_self">YUI RTE</a>，mootools也有<a
href="http://www.efectorelativo.net/laboratory/wysiwyg/" target="_blank">wysiwyg</a>插件，不过好像都缺少后续更新。还是TinyMCE和CKEditor比较活跃啊~</p><p><a
name="skip001"></a><br
/> 淘宝此次发布的编辑器，基于YUI构建，而且是YUI 2.x，诚如“摇滚肉包子”<a
href="http://ued.taobao.com/blog/2009/10/26/kissy-editor/#comment-52888" target="_blank">所言</a>，这多多少少会给编辑器的推广带来一些阻碍。但到底好不好用呢？还是试过之后才知道：</p><h3>1. 界面</h3><p>现在这款皮肤，和Google Docs很接近，字体颜色拾取器也是借鉴了Google Docs，很好用。总体来说清新舒爽，不油不腻，简洁实用&#8230;  不过不太喜欢字体下拉菜单的蓝色：</p><p><a
rel="attachment wp-att-1836" href="http://blog.benhuoer.com/posts/try-out-report-of-kissy-editor.html/kissy01"><img
class="size-full wp-image-1836 alignnone" title="kissy01" src="http://blog.benhuoer.com/wp-content/uploads/2009/10/kissy01.png" alt="kissy01" width="301" height="274" /></a></p><p>这是绝对的链接色。这种菜单，<strong>用黑色就很好</strong>：</p><p><a
rel="attachment wp-att-1837" href="http://blog.benhuoer.com/posts/try-out-report-of-kissy-editor.html/kissy02"><img
class="size-full wp-image-1837 alignnone" title="kissy02" src="http://blog.benhuoer.com/wp-content/uploads/2009/10/kissy02.png" alt="kissy02" width="272" height="263" /></a></p><p>（弹出层和按钮左侧有两个像素的距离，我不知道作者是不是故意不对齐的。）</p><p>期待淘宝UED的视觉设计达人们能加入到后续版本的开发中，设计出一套更加漂亮的皮肤来。感觉淘宝整站的这种“外凸渐变”实在太多了，不够elegant&#8230;</p><p>据说插入链接/图片的浮动层样式参考了搜狐白社会，十分紧凑，适合这种小巧的社区发帖编辑器。</p><h3>2. 功能</h3><p>目前只实现了一些常用的编辑器功能，字体样式、图片和链接插入、缩进和对齐等。没有清除样式的按钮，直接添加标题（h1~h6）、引用（blockquote）等语义化标签的按钮也没有，从Word中复制内容得到的html源码也十分混乱。不过通过查看js源码，可以看出作者预留了很多接口，底层代码也算是博采众长，插件和皮肤和的自定义还算方便。</p><p>作者透露的开发计划是：</p><blockquote><p>紧接着的二期里，将进一步完善基础架构和插件体系，并提供 Undo/Redo, 插入Flash, 表格编辑和预置模板等功能。</p></blockquote><p>另外一些细节，比如说插入图片时URL没有基本的正则验证，当没有p标签包裹时按回车键只会出现br换行，字体的样式和颜色是使用的font标签来设置，等等…… 可能会让一些细节控/语义控觉得受不了。</p><p>更多bug和改进建议可以参考<a
href="http://code.google.com/p/kissy/updates/list" target="_blank">updates list</a>。（话说淘宝影响力就是大啊，发布不过一周，提交的bug已经近80个了&#8230;）</p><h3>3. 浏览器兼容</h3><p>稍微测试了一下，发现的问题有：</p><ol><li>ie和ff之外的浏览器不能使用图片大小重设</li><li>opera里缩进按钮失效</li><li>ie中把图片右对齐，会出现烦人的横向滚动条</li><li>&#8230;</li></ol><p>更多兼容性问题，请继续参考<a
href="http://code.google.com/p/kissy/updates/list" target="_blank">updates list</a>&#8230;..</p><h3>4. 大小</h3><p>KISSY以“小巧灵活，简洁实用”为开发理念，功能实现上遵循着实用主义，但是又保持了相当高的灵活性和可扩展性。</p><p>KISSY Editor依赖于YUI的yahoo-dom-event，两者压缩到一个文件后的大小为94k，而TinyMCE在同样的压缩规则下大小为162k。相比于TinyMCE强大的功能，KISSY的尺寸似乎略显臃肿&#8230; 对广大站长的号召力似乎不是很大。yahoo-dom-event占到总代码量的近2/3，不知道如果让KISSY独立起来，总代码量会减少多少？</p><p>很早以前我就想要一个jQuery版的TinyMCE，因为那得节省多少代码啊~  KISSY Editor还这么新，不知道有没有可能从一开始就整一系列基于多类库的版本？（哇&#8230; 类库，内裤，这个词好&#8230;.）同步开发应该好维护些，不然以后代码庞大起来，要转移内裤就更难搞了。</p><h3>5. 性能</h3><p>把插件弹出层的HTML代码写到js里，真是一个好idea&#8230; 非常受不了WordPress后台那基于远程HTML文档的模态窗口，网速慢的时候，插入链接这么简单的操作，都要等十秒以上……</p><p>至于KISSY这个编辑器的内存占用、代码洁净程度等需要高强度测试的高科技问题，就还是等其他牛人来搞啦&#8230; 笔者没有这个水平。</p><p><strong>报告完毕！</strong>&#8212;&#8212;&#8212;~&#8212;~&#8211;~&#8211;~-~&#8211;妖艳的分割线&#8211;~-~&#8211;~&#8211;~&#8212;&#8212;&#8211;</p><p><a
href="http://kissyteam.github.com/docs/html/editorguide/" target="_blank">即刻试用KISSY Editor</a> |  <a
href="http://code.google.com/p/kissy/" target="_blank">在Google Code上的项目主页</a> <a
href="http://kissyteam.github.com/" target="_blank">在 GitHub 上的KISSY项目主页</a> |  <a
href="http://lifesinger.org/blog/" target="_blank">开发者博客</a></p><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/javascript" rel="tag">JavaScript</a>, <a
href="http://blog.benhuoer.com/tag/rte" rel="tag">RTE</a>, <a
href="http://blog.benhuoer.com/tag/%e6%b7%98%e5%ae%9d" rel="tag">淘宝</a></div><p><small>©2009 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/try-out-report-of-kissy-editor.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/try-out-report-of-kissy-editor.html#comments" target="_blank">已经有9条评论了</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/try-out-report-of-kissy-editor.html&title=淘宝开源编辑器KISSY Editor试用报告&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/try-out-report-of-kissy-editor.html/feed</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>即刻提升jQuery性能的十个技巧[TUTS+]</title><link>http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html</link> <comments>http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html#comments</comments> <pubDate>Fri, 10 Jul 2009 05:54:37 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[CSS]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[TutsPlus]]></category> <category><![CDATA[教程]]></category> <guid
isPermaLink="false">http://blog.benhuoer.com/?p=1569</guid> <description><![CDATA[本文提供即刻提升你的脚本性能的十个步骤。不用担心，这并不是什么高深的技巧。人人皆可运用！ 这些技巧包括： 使用最新版本 合并、最小化脚本 用for替代each 用ID替代class选择器 给选择器指定前后文 建立缓存 避免DOM操作 避免使用concat()，利用join()处理长字串 返回false值 利用小抄和参考文档 1. 使用最新版本 jQuery一直处于不断的开发和改进过程中。 John 和他的团队不断研究着提升程序性能的新方法。 一点题外话，几个月前他还发布了Sizzle，一个据说能在Firefox中把程序性能提升3倍的JS选择器库。 如果你不想时刻关注是否有新版本，然后再花时间下载上传，Google 就又能帮你一把了。他们的服务器上存储了大量Ajax库供您选择。 &#60;!-- 利用一个简单的script标签调用API --&#62; &#60;script type="text/javascript" src="http://www.google.com/jsapi"&#62;&#60;/script&#62; &#60;script type="text/javascript"&#62; /* 加载 jQuery v1.3.2 */ google.load ("jquery", "1.3.2", {uncompressed: false}); /* 加载完成后弹出消息 */ function onLoad () { alert ("jQuery + Google API!"); } google.setOnLoadCallback (onLoad); &#60;/script&#62; 编辑按：另一个更为简单快速的方法是直接使用脚本链接。如果要使用特定版本的jQuery，你可以使用上面的方法；如果想直接使用最新版，下面这句代码就够了： [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html" rel="bookmark">正则表达式高级技巧背后的关键概念[SM]</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p>本文提供即刻提升你的脚本性能的十个步骤。不用担心，这并不是什么高深的技巧。人人皆可运用！<br
/> 这些技巧包括：</p><ol><li> 使用最新版本</li><li>合并、最小化脚本</li><li>用for替代each</li><li>用ID替代class选择器</li><li>给选择器指定前后文</li><li>建立缓存</li><li>避免DOM操作</li><li>避免使用concat()，利用join()处理长字串</li><li>返回false值</li><li>利用小抄和参考文档</li></ol><p> <span
id="more-1569"></span><br
/><h3>1. 使用最新版本</h3><div><img
style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://nettuts.s3.amazonaws.com/359_jqueryTips/j2.png" alt="jQueryTips-Use_Latest" /></div><p>jQuery一直处于不断的开发和改进过程中。 <a
href="http://ejohn.org/" target="_blank">John</a> 和他的团队不断研究着提升程序性能的新方法。</p><p>一点题外话，几个月前他还发布了<a
href="http://sizzlejs.com/" target="_blank">Sizzle</a>，一个据说能在Firefox中把程序性能提升3倍的JS选择器库。</p><p>如果你不想时刻关注是否有新版本，然后再花时间下载上传，Google 就又能帮你一把了。他们的服务器上存储了大量<a
href="http://code.google.com/apis/ajaxlibs/" target="_blank">Ajax库</a>供您选择。</p><pre class="brush:jscript">&lt;!-- 利用一个简单的script标签调用API --&gt;
&lt;script type="text/javascript" src="http://www.google.com/jsapi"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
/* 加载 jQuery v1.3.2 */
google.load ("jquery", "1.3.2", {uncompressed: false});
/* 加载完成后弹出消息 */
function onLoad () {
alert ("jQuery + Google API!");
}
google.setOnLoadCallback (onLoad);
&lt;/script&gt;</pre><p><strong>编辑按：</strong>另一个更为简单快速的方法是直接使用脚本链接。如果要使用特定版本的jQuery，你可以使用上面的方法；如果想直接使用最新版，下面这句代码就够了：</p><pre class="brush:jscript">&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"&gt;&lt;/script&gt;</pre><p><strong>笨活儿</strong>：特定版本的还可以这样加载：</p><pre class="brush:jscript">&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt;</pre><h3>2. 合并、最小化脚本</h3><p
style="text-align:center;"><img
src="http://nettuts.s3.amazonaws.com/359_jqueryTips/jquery.png" alt="Minify" width="460" height="147" /></p><p>大部分浏览器都不能同时处理多个脚本文件，所以它们都是排队加载——加载时间也相应地延长了。</p><p>考虑到你网站的每个页面都会加载这些脚本，你应该考虑把它们放到单个文件中，然后利用压缩工具（比如 <a
href="http://dean.edwards.name/packer/" target="_blank">Dean Edwards</a> 的<a
href="http://dean.edwards.name/packer/" target="_blank">这款</a>）把它们最小化。更小的文件无疑将带来更快的加载速度。</p><blockquote><p>JavaScript和CSS压缩的目的是在保持脚本的执行性能的同时，减少数据传递的字节数（可以通过减小原始文件，也可以利用gzip。大多数产品级的网络服务器都把gzip作为HTTP协议的一部分）。</p><p>— 引自 <a
href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUI compressor</a>，一款 <strong>jQuery官方推荐</strong>的压缩脚本的工具。</p></blockquote><h3>3. 用for替代each</h3><p>原生函数总是比辅助组件更快。</p><p>如果遇到需要遍历对象的情况（如从远程接收的JSON对象），你最好<strong>重写</strong>你的（JSON）对象为一个数组，数组的循环处理要容易些。</p><p>利用<a
href="http://getfirebug.com/" target="_blank">Firebug</a>，我们能测定每个函数的执行时间。</p><pre class="brush:jscript">var array = new Array ();
for (var i=0; i&lt;10000; i++) {
array[i] = 0;
}
console.time('native');  //原生for函数
var l = array.length;
for (var i=0;i</pre><p
style="text-align:center;"><img
src="http://chartgizmo.com/GenerateChart?id=6757" alt="a chart" /></p><p>上面的结果显示原生代码只需2毫秒就做到的事，利用jQuery的each方法需要26毫秒。而且这还只是我在本机上测试一个基本上啥也没做的函数的结果，当遇到更复杂的情况，例如设置css属性或DOM操作时，时间差异肯定更大。</p><h3>4. 用ID替代class选择器</h3><p>利用ID选择对象要好得多，因为这时jQuery会使用浏览器的原生函数getElementByID()来获取对象，查询速度很快。</p><p>因此，比起利用那些方便的css选择技巧，使用更为复杂的选择器也是值得的（jQuery也为我们提供了复杂选择器）。你也可以手工书写自己的选择器（其实比你想象中简单），或者为你想要选择的元素指定一个有ID的容器。</p><pre class="brush:jscript">//下例创建一个列表并且填充条目内容
//然后每个条目都被选择一次
//首先使用class选择
console.time('class');
var list = $('#list');
var items = '
<ul>';
for (i=0; i&lt;1000; i++) {
items += '
<li>item</li>
';
}
items += '</ul>
';
list.html (items);
for (i=0; i&lt;1000; i++) {
var s = $('.item' + i);
}
console.timeEnd('class');
//然后利用ID选择
console.time('id');
var list = $('#list');
var items = '
<ul>';
for (i=0; i&lt;1000; i++) {
items += '
<li id="item' + i + '">item</li>
';
}
items += '</ul>
';
list.html (items);
for (i=0; i&lt;1000; i++) {
var s = $('#item' + i);
}
console.timeEnd('id');</pre><p>上面的例子很好地说明了不同选择方式之间的显著性能差异。请看下图，利用class来做选择，时间无限增大，甚至超过了五秒：</p><p
style="text-align:center;"><img
src="http://chartgizmo.com/GenerateChart?id=6758" alt="" /></p><h3>5. 给选择器指定前后文</h3></p><p><a
href="http://docs.jquery.com/Core/context" target="_blank">jQuery的参考文档</a>里说：</p><blockquote><p>传递给jQuery() 原始DOM节点的前后文（如果没有东西被传递，则前后文为整个文档）。</p><p>目的是连同选择器一起，实现更为准确的查询。</p></blockquote><p>所以，如果你一定要利用class来指定目标，至少为选择器<a
href="http://docs.jquery.com/Core/context" target="_blank">指定上下文</a>，以免jQuery费精力去遍历整个DOM文档：</p><p>与其这样写：</p><pre class="brush:jscript">$('.class').css ('color' '#123456');</pre><p>为选择器加上前后文比较好（expression: 目标选择器；context: 前后文）：</p><pre class="brush:jscript">$(expression, context)</pre><p>也就是说：</p><pre class="brush:jscript">$('.class', '#class-container').css ('color', '#123456');</pre><p>这样做要快得多，因为它不用遍历整个DOM。只要找到#class-container就好了。</p><h3>6. 建立缓存</h3><p>不要犯不断重新选择同一个东西的错误。你应该把你要处理的元素缓存为一个变量。</p><p><strong>更不要</strong>在一个循环里重复选择同一个元素！这样做十分影响速度！</p><pre class="brush:jscript">$('#item').css('color', '#123456');
$('#item').html('hello');
$('#item').css('background-color', '#ffffff');
// 这样写更好
$('#item').css('color', '#123456').html('hello').css('background-color', '#ffffff');
// 甚至这样
var item = $('#item');
item.css('color', '#123456');
item.html('hello');
item.css('background-color', '#ffffff');
// 遇到循环,这样做非常不好
console.time('no cache');
for (var i=0; i&lt;1000; i++) {
$('#list').append(i);
}
console.timeEnd('no cache');
// 下面这样要好得多
console.time('cache');
var item = $('#list');
for (var i=0; i&lt;1000; i++) {
item.append (i);
}
console.timeEnd('cache');</pre><p>如下图所示，即使是相对较短的迭代，缓存的效果还是很明显的。</p><p
style="text-align:center;"><img
src="http://chartgizmo.com/GenerateChart?id=6759" alt="" /></p><h3>7. 避免DOM操作</h3><p>DOM操作应该越少越好，因为诸如<a
href="http://docs.jquery.com/Manipulation/prepend" target="_blank">prepend()</a>，<a
href="http://docs.jquery.com/Manipulation/append" target="_blank">append()</a>，<a
href="http://docs.jquery.com/Manipulation/after" target="_blank">after()</a>的插入动作都很费时。</p><p>上面的例子如果用<a
href="http://docs.jquery.com/Html" target="_blank">html()</a>会更快：</p><pre class="brush:jscript">var list = '';
for (var i=0; i&lt;1000; i++) {
list += '
<li>'+i+'</li>
';
}
('#list').html (list);</pre><h3>8. 避免使用concat()，利用join()处理长字串</h3><p>听起来可能挺奇怪，不过这样做真的能提升速度，尤其是当连接特别长的字串时。</p><p>先建立一个数组，放入你想要串联的东西。join()方法比字符串的concat()函数要快得多。</p><pre class="brush:jscript">var array = [];
for (var i=0; i< =10000; i++) {
array[i] = '
<li>'+i+'';
}
$('#list').html(array.join (''));</pre><p>近期一项由<a
href="http://www.sitepen.com/blog/2008/05/09/string-performance-an-analysis/" target="_blank">Tom Trenka</a>发起的测试中，得出了下表的结果：</p><div><img
style="width: 600px; display: block; float: none; margin-left: auto; margin-right: auto;" src="http://www.sitepen.com/blog/wp-content/uploads/2008/05/stringperf.png" alt="" /></div><blockquote><p>“ += 操作符更快——比把字串片段放到数组中然后join起来还要快”，“作为字串缓冲（string buffer）的数组在大部分浏览器中都比string.prototype.concat.apply方法效率更高，Windows下的Firefox 2.0.0.14例外。”</p><p>— Tom Trenka</p></blockquote><h3>9. 返回false值</h3><p>您可能已经注意到，如果函数执行后不返回false，你就会被跳转到页面顶部。</p><p>如果页面较长，这种反应是很烦人的。</p><p>所以，与其这样：</p><pre class="brush:jscript">$('#item').click (function () {
// stuff here
});</pre><p>不如多加一句：</p><pre class="brush:jscript">$('#item').click (function () {
// stuff here
return false;
});</pre><h3>10. 额外小贴士 &#8211; 小抄和参考文档</h3><p
style="text-align:center;"><img
src="http://nettuts.s3.amazonaws.com/359_jqueryTips/cheatsheet.png" alt="" /></p><p>这条建议并不直接提升函数的执行速度，不过如果你肯花时间在这上面，研究研究这些<a
href="http://colorcharge.com/jquery/" target="_blank">小抄</a>和<a
href="http://docs.jquery.com/" target="_blank">参考文档</a>，你将来定能节约很多时间。</p><p>请在手边随时放一张小抄以作快速参考。</p><blockquote><p>英文原文来自NetTut+：<a
href="http://net.tutsplus.com/tutorials/javascript-ajax/10-ways-to-instantly-increase-your-jquery-performance/" target="_blank">10 Ways to Instantly Increase Your jQuery Performance</a></p><p>译文原文来自笨活儿：<a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html">十种方式即刻提升您的jQuery代码性能[TUTS+]</a>。</p><p>©请尊重作者和译者。若需转载，务必保留原文链接。</p></blockquote><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html" rel="bookmark">正则表达式高级技巧背后的关键概念[SM]</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/css" rel="tag">CSS</a>, <a
href="http://blog.benhuoer.com/tag/javascript" rel="tag">JavaScript</a>, <a
href="http://blog.benhuoer.com/tag/jquery" rel="tag">jQuery</a>, <a
href="http://blog.benhuoer.com/tag/tutsplus" rel="tag">TutsPlus</a>, <a
href="http://blog.benhuoer.com/tag/%e6%95%99%e7%a8%8b" rel="tag">教程</a></div><p><small>©2009 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html#comments" target="_blank">已经有3条评论了</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html&title=即刻提升jQuery性能的十个技巧[TUTS+]&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html/feed</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>给JavaScript新手的24条实用建议[TUTS+]</title><link>http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html</link> <comments>http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html#comments</comments> <pubDate>Sat, 20 Jun 2009 02:43:41 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[TutsPlus]]></category> <category><![CDATA[入门]]></category> <category><![CDATA[教程]]></category> <guid
isPermaLink="false">http://blog.benhuoer.com/?p=1532</guid> <description><![CDATA[为JavaScript做一点性能小提升吧！ 本文列出了24条能让你的代码编写过程更为轻松高效的建议。也许您还是JavaScript初学者，刚刚写完自己的Hello World，那这里有很多对您的工作将十分有用的小贴士；也许有些技巧您已经知道，那就试试快速浏览一下，看能不能发现一点新东西吧！ 注：本文多次用到Firebug的console对象，请参考Firebug Console API 。关于firebug的更详细介绍，请猛击这里。 1. 用 === 代替 == JavaScript里有两种不同的相等运算符：===&#124;!== 和==&#124;!=。相比之下，前者更值得推荐。请尽量使用前者。 “如果两个比较对象有着同样的类型和值，===返回true，!==返回false。” - JavaScript: The Good Parts 不过，如果使用==和!=，在操作不同数据类型时, 你可能会遇到一些意想不到的问题。在进行相等判断前，JavaScript会试图将它们转换为字符串、数字或 Boolean量。 2. 避免使用Eval函数 Eval函数把一个字串作为参数，并把字串作为JavaScript语句执行，返回结果（参考）。 此函数不仅会降低你脚本的执行效率，而且还大大增加了安全风险，因为它赋予了作为文本的参数太大的权利。千万别用！ 3. 不要使用快速写法 技术上说，你可以省略掉大部分花括弧和句尾分号，绝大多数浏览器都能正确执行以下语句： if(someVariableExists) x = false 不过，如果是这样的呢： if(someVariableExists) x = false anotherFunctionCall(); 你可能会认为它和下面的语句相等： if(someVariableExists) { x = false; anotherFunctionCall(); } 不幸的是，事实并非如此。现实情况是它等价于： if(someVariableExists) { x = false; } [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html" rel="bookmark">正则表达式高级技巧背后的关键概念[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p>为JavaScript做一点性能小提升吧！</p><p>本文列出了24条能让你的代码编写过程更为轻松高效的建议。也许您还是JavaScript初学者，刚刚写完自己的Hello World，那这里有很多对您的工作将十分有用的小贴士；也许有些技巧您已经知道，那就试试快速浏览一下，看能不能发现一点新东西吧！</p><p> <span
id="more-1532"></span><p
class="attention">注：本文多次用到Firebug的console对象，请参考<a
href="http://getfirebug.com/console.html" target="_blank">Firebug Console API</a> 。关于firebug的更详细介绍，请<a
title="IBM开发者中心上的文章" href="http://www.ibm.com/developerworks/cn/web/wa-aj-firebug/" target="_blank">猛击这里</a>。</p><h3>1. 用 === 代替 ==</h3><p>JavaScript里有两种不同的相等运算符：<code>===|!==</code> 和<code>==|!=</code>。相比之下，前者更值得推荐。请尽量使用前者。</p><blockquote><p>“如果两个比较对象有着同样的类型和值，===返回true，!==返回false。”</p><p>- JavaScript: The Good Parts</p></blockquote><p>不过，如果使用<code>==</code>和<code>!=</code>，在操作不同数据类型时, 你可能会遇到一些意想不到的问题。在进行相等判断前，JavaScript会试图将它们转换为字符串、数字或 Boolean量。</p><h3>2. 避免使用Eval函数</h3><p>Eval函数把一个字串作为参数，并把字串作为JavaScript语句执行，返回结果（<a
title="W3School里的介绍" href="http://www.w3school.com.cn/js/jsref_eval.asp" target="_blank">参考</a>）。</p><p>此函数不仅会降低你脚本的执行效率，而且还大大增加了安全风险，因为它赋予了作为文本的参数太大的权利。千万别用！</p><h3>3. 不要使用快速写法</h3><p>技术上说，你可以省略掉大部分花括弧和句尾分号，绝大多数浏览器都能正确执行以下语句：</p><pre class="brush:jscript">if(someVariableExists)
 x = false
</pre><p>不过，如果是这样的呢：</p><pre class="brush:jscript">if(someVariableExists)
 x = false
 anotherFunctionCall();
</pre><p>你可能会认为它和下面的语句相等：</p><pre class="brush:jscript">if(someVariableExists) {
 x = false;
 anotherFunctionCall();
}
</pre><p>不幸的是，事实并非如此。现实情况是它等价于：</p><pre class="brush:jscript">if(someVariableExists) {
 x = false;
}
anotherFunctionCall();
</pre><p>如您注意到的，再漂亮的缩进也不能代替这华丽的花括弧。在所有情况下都请写清楚花括号和句尾分号。在只有一行语句的时候能偶尔省略掉，虽然下这么做也是极度不被推荐的：</p><pre class="brush:jscript">if(2 + 2 === 4) return 'nicely done';
</pre><h4>多考虑下将来吧，孩子</h4><p>假设，在将来的开发过程中，你需要为这个 if 语句添加更多的命令呢？到时候你还不是得把括号给加上？</p><h3>4. 好好利用JS Lint</h3><p><a
href="http://www.jslint.com/" target="_blank">JSLint</a> 是由 Douglas Crockford 编写的一个调试器。你只需要贴上你的代码，它就能快速为您扫描出任何明显的错误和问题。</p><blockquote><p>“JSLint 扫描接收的代码。发现问题，描述问题，并给出其在源码中的大概位置。可发现的问题包括但不限于语法错误，虽然语法错误确实是最常见的。JSLint也会用约定俗成的习惯检查代码的格式化风格，以及结构错误。通过JSLint的扫描并不能保证你的程序就完全正确。它只是为您提供了额外一双发现错误的眼睛。”</p><p>- JSLint 文档</p></blockquote><p>完成代码之前，把它放到JSLint里检查一下，快速消灭你的无心之过。</p><h3>5. 在页面底部加载脚本</h3><p>正如下图所示：</p><div><img
style="width: 600px;" src="http://nettuts.s3.amazonaws.com/327_30Musts/javascriptButton.png" alt="Place JS at bottom" /></div><p>请记住—— 我们要千方百计保证客户端的页面载入速度尽可能的快。而脚本没载入完成，浏览器就没法加载页面的剩余部分。</p><p>如果你的JS文件只是添加一些额外功能——例如，为点击某链接绑定事件——那大可以等页面加载基本完成后再做。把JS文件放到页面最后，body的结束标签之前，这样做最好了。</p><h4>更好的写法是</h4><pre class="brush:jscript">&lt;p&gt;超哥是世界上最帅的人。benhuoer.com是世界上最好看的博客。&lt;/p&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;path/to/file.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;path/to/anotherFile.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre><h3>6. 在 For 语句外部声明变量</h3><p>当需要执行冗长的for语句时，不要让JavaScript引擎每次都重复那些没有必要的操作。例如：</p><h4>这样不好</h4><pre class="brush:jscript">for(var i = 0; i &lt; someArray.length; i++) {
 var container = document.getElementById('container');
 container.innerHtml += 'my number: ' + i;
 console.log(i);
}
</pre><p>这段代码每次都重新定义数组长度，每次都在遍历DOM寻找container元素 —— 太傻了！</p><h4>这样好多了</h4><pre class="brush:jscript">var container = document.getElementById('container');
for(var i = 0, len = someArray.length; i &lt; len;  i++) {
 container.innerHtml += 'my number: ' + i;
 console.log(i);
}
</pre><p>我要给留言改进这段代码的人额外惊喜！欢迎大家留言讨论！</p><h3>7. 快速构建字串</h3><p>要对一个数组或对象做循环操作时，不要老惦记着一表人才的for语句，拿点创意出来嘛！明明就还有很多更快的办法：</p><pre class="brush:jscript">var arr = ['item 1', 'item 2', 'item 3', ...];
var list = '&lt;ul&gt;&lt;li&gt;' + arr.join('&lt;/li&gt;&lt;li&gt;') + '&lt;/li&gt;&lt;/ul&gt;';</pre><blockquote><p>“没那么多繁文缛节来烦你；你就信我一次好了（或者你也可以自己试一试）—— 这真的是迄今能找到的最快办法了！</p><p>用点土办法，也别管它背后究竟发生了什么抽象的东西，通常土办法都比那些优雅的办法要快捷得多！”</p><p>- James Padolsey, james.padolsey.com</p></blockquote><h3>8. 减少全局变量</h3><blockquote><p>“把你踩在全局的那些乱七八糟的脚印都归于一人名下，能显著降低与其他应用、小工具或JS库冲突的可能性。”</p><p>- Douglas Crockford</p></blockquote><pre class="brush:jscript">var name = 'Jeffrey';
var lastName = 'Way';
function doSomething() {...}
console.log(name); // Jeffrey -- or window.name
</pre><h4>更好的写法</h4><pre class="brush:jscript">var DudeNameSpace = {
 name : 'Jeffrey',
 lastName : 'Way',
 doSomething : function() {...}
}
console.log(DudeNameSpace.name); // Jeffrey
</pre><p>注意看，我们是如何戏剧化地把“乱七八糟的脚印”都归到“DudeNameSpace”这对象之下的。</p><h3>9. 写好注释</h3><p>可能一开始你会觉得并无必要，但相信我，你将来会<strong>主动想</strong>要尽可能写好代码的注释的。当你几个月后再回看某项目时，结果却发现很难想起当时写某句东西时脑子在想的什么了，是不是很让人沮丧呢？或者，如果有同事要修订你的代码呢？一定，一定要为你代码里的重要部分加上注释。</p><pre class="brush:jscript">// 遍历数组，输出各自名称
for(var i = 0, len = array.length; i &lt; len; i++) {
 console.log(array[i]);
}
</pre><h3>10. 试试渐进增强</h3><p>一定要记得为未启用JavaScript的情况提供替代方案。大家可能会认为，“大部分我的访客都启用了JavaScript的，我才不用担心”。这样的话，你可就大错特错了！</p><p>你有没有试过看看禁用JavaScript后你那漂亮的滑动器都成啥样了？（你可以下载 <a
href="https://addons.mozilla.org/en-US/firefox/addon/60" target="_blank">Web Developer ToolBar</a> 轻松完成这项任务。）禁用之后你的网站可能就彻底失去了可用性！经验之谈：开发初期总是按照没有JavaScript来设计你的网站，之后再进行<strong>渐进地功能增强</strong>，小心翼翼地改变你地布局。</p><h3>11. 不要传递字串给 “setInterval” 或 “setTimeout”</h3><p>看看下面的代码：</p><pre class="brush:jscript">setInterval(
&quot;document.getElementById('container').innerHTML += 'My new number: ' + i&quot;, 3000
);
</pre><p>不仅执行不高效，而且和 eval 函数有着同样的高风险。千万不要把字串传递给 setInterval 和 setTimeout。恰当的做法是，传递一个函数名：</p><pre class="brush:jscript">setInterval(someFunction, 3000);
</pre><h3>12. 不要使用with语句</h3><p>初识之下，“with”语句似乎还挺好用的。它用于设置代码在特定对象中的作用域。其基本用法是提供深入到对象中处理元素的快速写法。例如：</p><pre class="brush:jscript">with (being.person.man.bodyparts) {
 arms = true;
 legs = true;
}
</pre><p>– 等价于 —</p><pre class="brush:jscript">being.person.man.bodyparts.arms = true;
being.person.man.bodyparts.legs= true;
</pre><p>不幸的是，测试表明，若你要为对象插入新成员，with的表现非常糟糕，它的执行速度非常缓慢。替代方案是声明一个变量：</p><pre class="brush:jscript">var o = being.person.man.bodyparts;
o.arms = true;
o.legs = true;
</pre><h3>13. 使用 {}，而不用New Object()</h3><p>在JavaScript有多种方式能新建对象。最传统的方法是 new 语句，如下：</p><pre class="brush:jscript">var o = new Object();
o.name = 'Benhuoer';
o.lastName = 'Yang';
o.someFunction = function() {
 console.log(this.name);
}
</pre><p>不过，这一方法读起来却比较糟糕。我强烈建议你采用下面这种在文字样式上更为强健的写法：</p><h4>更好的写法</h4><pre class="brush:jscript">var o = {
 name: 'Jeffrey',
 lastName = 'Way',
 someFunction : function() {
 console.log(this.name);
 }
};
</pre><p>注意，如果你想新建一个空对象，用 {} 就能行：</p><pre class="brush:jscript">var o = {};
</pre><blockquote><p>“对象字面符(Objects literals)帮助我们写出支持很多特性，同时又关联性强、简明直接的代码。没必要直接调用新建语句，然后再费心维护声明变量和传递变量的语句之间的正确顺序，等等。” &#8211; <a
href="http://www.dyn-web.com/tutorials/obj_lit.php" target="_blank">dyn-web.com</a></p></blockquote><h3>14. 使用[]，而不用New Array()</h3><p>新建数组时的同类型运用。</p><h4>行得通的写法</h4><pre class="brush:jscript">var a = new Array();
a[0] = &quot;Joe&quot;;
a[1] = 'Plumber';
</pre><h4>更好的写法</h4><pre class="brush:jscript">var a = ['Joe','Plumber'];
</pre><blockquote><p>“在JavaScript编程中经常遇到的一个错误是，该用数组时却用了对象，该用对象时却用了数组。规则其实很简单：当属性名是小的连续整数时，你应该使用数组。其他情况，使用对象。” &#8211; Douglas Crockford</p></blockquote><h3>15. 一长列变量声明？别写那么多var，用逗号吧</h3><pre class="brush:jscript">var someItem = 'some string';
var anotherItem = 'another string';
var oneMoreItem = 'one more string';
</pre><h4>更好的写法</h4><pre class="brush:jscript">var someItem = 'some string',
 anotherItem = 'another string',
 oneMoreItem = 'one more string';
</pre><p>…不言自明。我不知道这样做能否提升代码执行速度，但是确实让你的代码干净许多。</p><h3>17. 千万千万记得写分号</h3><p>大部分浏览器都允许你不写句尾分号：</p><pre class="brush:jscript">var someItem = 'some string'
function doSomething() {
 return 'something'
}
</pre><p>之前已经说过，这样做会造成潜在的更大、更难以发现的问题：</p><h4>更好的写法</h4><pre class="brush:jscript">var someItem = 'some string';
function doSomething() {
 return 'something';
}
</pre><h3>18. “For in” 语句</h3><p>遍历对象时，你可能会发现你还需要获取方法函数。所以遇到这种情况时，请一定记得给你的代码包一层 if 语句，用以过滤信息。</p><pre class="brush:jscript">for(key in object) {
 if(object.hasOwnProperty(key) {
 ...then do something...
 }
}
</pre><p><em>引自</em><em> Douglas Crockford 所作：</em><em> JavaScript: The Good Parts </em></p><h3>19. 使用Firebug的“Timer”功能优化你的代码</h3><p>想要轻松地快速了解某项操作的用时吗？使用Firebug的timer功能来记录结果好了。</p><pre class="brush:jscript">function TimeTracker(){
 console.time(&quot;MyTimer&quot;);
 for(x=5000; x &gt; 0; x--){}
 console.timeEnd(&quot;MyTimer&quot;);
}
</pre><h3>20. 读，读，读……Read, Read, Read…</h3><p>虽然我是Web开发博客（就像这个！）的超级粉丝，但吃饭和睡觉前除了看<strong>书</strong>好像也别无选择~ 在你的床头柜上摆一本Web开发的好书吧！下列书单都是我的最爱：</p><ul><li><a
href="http://www.packtpub.com/object-oriented-javascript-applications-libraries/book" target="_blank">Object-Oriented JavaScript</a>（暂无中文版）</li><li><a
href="http://oreilly.com/catalog/9780596517748/" target="_blank">JavaScript: The Good Parts</a>（<a
href="http://www.douban.com/subject/3590768/" target="_blank">中文版</a>）</li><li><a
href="http://www.packtpub.com/learning-jquery-1.3/boo" target="_blank">Learning jQuery 1.3</a>（暂无中文版，但你可以看看<a
href="http://www.douban.com/subject/3082293/" target="_blank">老版本的中文版</a>）</li><li><a
href="http://oreilly.com/catalog/9780596527464/" target="_blank">Learning JavaScript</a>（<a
title="豆瓣" href="http://www.douban.com/subject/1232061/" target="_blank">中文版</a>）</li></ul><p>阅读他们…… 反复阅读很多次！我现在都还在读。</p><h3>21. 自决的函数</h3><p>相比于调用函数，让函数在页面载入或者某一父函数被调用时自动执行，是十分简单方便的做法。你只需要把你的函数包在父辈之内，然后添上一个额外的括号，本质上这括号就触发了你定义的函数（<a
href="http://20032334.javaeye.com/blog/288989" target="_blank">了解更多</a>）。</p><pre class="brush:jscript">(function doSomething() {
 return {
 name: 'jeff',
 lastName: 'way'
 };
})();
</pre><h3>22. 原生 JavaScript 总是会比使用代码库来的快</h3><p>诸如jQuery和Mootools这样的JavaScript库，能为你写代码的过程省下不少时间——尤其是当需要 AJAX 操作时。不过你可得记住，只要你的代码写得恰当，原生JavaScript总是会比利用代码库的写法执行得快一些。</p><p>jQuery的“each” 方法对于循环操作十分便利，但是使用原生态的for语句总归会快很多。</p><h3>23. Crockford 的 JSON.Parse</h3><p>尽管 JavaScript 2会内建JSON处理器，但写这篇文章之时，我们还是需要自己实现。Douglas Crockford，JSON的创建者，已经为我们创作出能直接使用的处理器了。您可以在这里<a
href="http://www.json.org/json2.js" target="_blank">下载</a>。</p><p>导入这段代码，你就能新建 JSON 全局对象，然后处理你的 .json 文件。</p><pre class="brush:jscript">var response = JSON.parse(xhr.responseText);
var container = document.getElementById('container');
for(var i = 0, len = response.length; i &lt; len; i++) {
 container.innerHTML += '&lt;li&gt;' + response[i].name + ' : ' + response[i].email + '&lt;/li&gt;';
}
</pre><p>关于JSON，请查看<a
href="http://www.json.org/json-zh.html" target="_blank">更多介绍</a>。</p><h3>24. 移去“Language”</h3><p>很多年前，language还是每段script标签必备属性：</p><pre class="brush:jscript">&lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot;&gt;
...
&lt;/script&gt;
</pre><p>不过现在，这属性已经没啥用很久了…… 所以，删掉算啦！</p><h3>就这些了，朋友们~</h3><p>就是这些了，这就是我给JavaScript初学者的24条小建议。各位亲爱的朋友，你们的看法呢？你们有什么快速小贴士吗？感谢你的耐心阅读。</p><blockquote><p>英文原文：<a
href="http://net.tutsplus.com/tutorials/javascript-ajax/24-javascript-best-practices-for-beginners/" target="_blank">24-javascript-best-practices-for-beginners</a></p><p>译文原文：<a
rel="bookmark" href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" target="_blank">给JavaScript新手的24条建议</a></p><p>© 请尊重版权，若需转载，务必保留链接。</p></blockquote><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html" rel="bookmark">正则表达式高级技巧背后的关键概念[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/javascript" rel="tag">JavaScript</a>, <a
href="http://blog.benhuoer.com/tag/jquery" rel="tag">jQuery</a>, <a
href="http://blog.benhuoer.com/tag/tutsplus" rel="tag">TutsPlus</a>, <a
href="http://blog.benhuoer.com/tag/%e5%85%a5%e9%97%a8" rel="tag">入门</a>, <a
href="http://blog.benhuoer.com/tag/%e6%95%99%e7%a8%8b" rel="tag">教程</a></div><p><small>©2009 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html#comments" target="_blank">已经有6条评论了</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html&title=给JavaScript新手的24条实用建议[TUTS+]&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html/feed</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>正则表达式高级技巧背后的关键概念[SM]</title><link>http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html</link> <comments>http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html#comments</comments> <pubDate>Mon, 01 Jun 2009 10:09:50 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[php]]></category> <category><![CDATA[Smashing Magazine]]></category> <category><![CDATA[教程]]></category> <category><![CDATA[正则表达式]]></category> <category><![CDATA[编程]]></category> <guid
isPermaLink="false">http://blog.benhuoer.com/?p=971</guid> <description><![CDATA[英文原文来自Smashing Magazine。由笨活儿翻译。转载请注明出处。 正则表达式(Regular Expression, abbr. regex) 功能强大，能够用于在一大串字符里找到所需信息。它利用约定俗成的字符结构表达式来发生作用。不幸的是，简单的正则表达式对于一些高级运用，功能远远不够。若要进行筛选的结构比较复杂，你可能就需要用到高级正则表达式。 本文为您介绍正则表达式的高级技巧。我们筛选出了八个常用的概念，并配上实例解析，每个例子都是满足某种复杂要求的简单写法。如果你对正则的基本概念尚缺乏了解，请先阅读这篇文章，或者这个教程，或者维基条目。 这里的正则语法适用于PHP，与Perl兼容。 1. 贪婪/懒惰 所有能多次限定的正则运算符都是贪婪的。他们尽可能多地匹配目标字符串，也就是说匹配结果会尽可能地长。不幸的是，这种做法并不总是我们想要的。因此，我们添加“懒惰”限定符来解决问题。在各个贪婪运算符后添加“?”能让表达式只匹配尽可能短的长度。另外，修改器“U”也能惰化能多次限定的运算符。理解贪婪与懒惰的区别是运用高级正则表达式的基础。 贪婪操作符 操作符 * 匹配之前的表达式零次或零次以上。它是一个贪婪操作符。请看下面的例子： preg_match( '/&#60;h1&#62;.*&#60; \/h1&#62;/', '&#60;/h1&#62;&#60;h1&#62;这是一个标题。&#60;/h1&#62; &#60;h1&#62;这是另一个。&#60;/h1&#62;', $matches ); 句点(.)能代表除换行符外的任意字符。上面的正则表达式匹配 h1 标签以及标签内的所有内容。它用句点(.)和星号(*)来匹配标签内的所有内容。匹配结果如下： 这是一个标题。 这是另一个。 整个字串都被返回。* 操作符会连续匹配所有内容—— 甚至包括中间的 h1 闭合标签。因为它是贪婪的，匹配整个字串是符合其利益最大化原则。 懒惰操作符 把上面的式子稍作修改，加上一个问号(?)，能让表达式变懒惰： /&#60;h1&#62;.*?&#60; \/h1&#62;/&#60;/h1&#62; 这样它会觉得，只需匹配到第一个 h1 结尾标签就完成任务了。 另一个有着类似属性的贪婪操作符是 {n,} 。它代表之前的匹配模式重复n次或n次以上，如果没有加上问号，它会寻找尽可能多的重复次数，加上的话，则会尽可能少重复（当然也就是“重复n次”最少）。 # 建立字串 $str = 'hihihi oops hi'; # 使用贪婪的{n,}操作符进行匹配 preg_match( '/(hi){2,}/', $str, [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<blockquote><p>英文原文来自<a
title="Smashing Magazine" href="http://www.smashingmagazine.com/2009/05/06/introduction-to-advanced-regular-expressions/" target="_blank">Smashing Magazine</a>。由<a
title="正则表达式高级技巧" href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html" target="_blank">笨活儿</a>翻译。转载请注明出处。</p></blockquote><p>正则表达式(Regular Expression, <em>abbr. regex</em>) 功能强大，能够用于在一大串字符里找到所需信息。它利用约定俗成的字符结构表达式来发生作用。不幸的是，简单的正则表达式对于一些高级运用，功能远远不够。若要进行筛选的结构比较复杂，你可能就需要用到<strong>高级正则表达式</strong>。</p><p>本文为您<strong>介绍正则表达式的高级技巧</strong>。我们筛选出了八个常用的概念，并配上实例解析，每个例子都是满足某种复杂要求的简单写法。如果你对正则的基本概念尚缺乏了解，请先阅读<a
title="正则表达式入门" href="http://unibetter.com/deerchao/zhengzhe-biaodashi-jiaocheng-se.htm#introduction" target="_blank">这篇文章</a>，或者<a
href="http://www.regexlab.com/zh/deelx/syntax.htm" target="_blank">这个教程</a>，或者<a
title="维基百科" href="http://zh.wikipedia.org/wiki/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F" target="_blank">维基条目</a>。</p><p>这里的正则语法适用于PHP，与<a
title="维基百科" href="http://zh.wikipedia.org/wiki/Perl" target="_blank">Perl</a>兼容。</p><p><span
id="more-971"></span></p><h3>1. 贪婪/懒惰</h3><p><img
src="http://i27.photobucket.com/albums/c156/jyyjcc/benhuoer-blog/regular-expression/greed.jpg" alt="Greed" width="400" height="300" /></p><p>所有能多次限定的正则运算符都是贪婪的。他们<strong>尽可能多</strong>地匹配目标字符串，也就是说匹配结果会<strong>尽可能地长</strong>。不幸的是，这种做法并不总是我们想要的。因此，我们添加“懒惰”限定符来解决问题。在各个贪婪运算符后添加“?”能让表达式只匹配<strong>尽可能短</strong>的长度。另外，修改器“U”也能惰化能多次限定的运算符。理解贪婪与懒惰的区别是运用高级正则表达式的基础。</p><h4>贪婪操作符</h4><p>操作符 * 匹配之前的表达式零次或零次以上。它是一个贪婪操作符。请看下面的例子：</p><pre class="brush:php">preg_match( '/&lt;h1&gt;.*&lt; \/h1&gt;/', '&lt;/h1&gt;&lt;h1&gt;这是一个标题。&lt;/h1&gt;
&lt;h1&gt;这是另一个。&lt;/h1&gt;', $matches );</pre><p>句点(.)能代表除换行符外的任意字符。上面的正则表达式匹配 h1 标签以及标签内的所有内容。它用句点(.)和星号(*)来匹配标签内的所有内容。匹配结果如下：</p><pre class="brush:php">
<h1>这是一个标题。</h1>
<h1>这是另一个。</h1>
</pre><p>整个字串都被返回。* 操作符会连续匹配所有内容—— 甚至包括中间的 h1 闭合标签。因为它是贪婪的，匹配整个字串是符合其利益最大化原则。</p><h4>懒惰操作符</h4><p>把上面的式子稍作修改，加上一个问号(?)，能让表达式变懒惰：</p><pre class="brush:php">/&lt;h1&gt;.*?&lt; \/h1&gt;/&lt;/h1&gt;</pre><p>这样它会觉得，只需匹配到第一个 h1 结尾标签就完成任务了。</p><p>另一个有着类似属性的贪婪操作符是 {n,} 。它代表之前的匹配模式重复n次或n次以上，如果没有加上问号，它会寻找尽可能多的重复次数，加上的话，则会尽可能少重复（当然也就是“重复n次”最少）。</p><pre class="brush:php"># 建立字串
$str = 'hihihi oops hi';
# 使用贪婪的{n,}操作符进行匹配
preg_match( '/(hi){2,}/', $str, $matches );  # matches[0] 将是 'hihihi'
# 使用堕化了的 {n,}? 操作符匹配
preg_match( '/(hi){2,}?/', $str, $matches );  # matches[0] 将是 'hihi'</pre><h3>2. 回返引用(Back referencing)</h3><p><img
src="http://i27.photobucket.com/albums/c156/jyyjcc/benhuoer-blog/regular-expression/back.jpg" alt="Back Referencing" width="300" height="290" /></p><h4>有什么用？</h4><p><strong>回返引用(Back referencing)</strong>一般被翻译成“反向引用”、“后向引用”、“向后引用”，个人觉得“回返引用”更为贴切[<a
title="笨活儿" href="http://blog.benhuoer.com/">笨活儿</a>]。它是在正则表达式内部引用<strong>之前捕获到的内容</strong>的方法。例如，下面这个简单例子的目的是匹配出引号内部的内容：</p><pre class="brush:php"># 建立匹配数组
$matches = array();
# 建立字串
$str = "\"This is a 'string'\"";
# 用正则表达式捕捉内容
preg_match( "/(\"|').*?(\"|')/", $str, $matches );
# 输出整个匹配字串
echo  $matches[0];</pre><p>它会输出：</p><pre class="brush:php">"This is a'</pre><p>显然，这并不是我们想要的内容。</p><p>这个表达式从开头的双引号开始匹配，遭遇单引号之后就错误地结束了匹配。这是因为表达式里说：<code>("|')</code>，也就是双引号（<code>"</code>）和单引号（<code>'</code>）均可。要修正这个问题，你可以用到回返引用。<strong>表达式\1,\2,…,\9</strong> 是对前面已捕获到的各个子内容的编组序号，能作为对这些编组的“指针”而被引用。在此例中，第一个被匹配的引号就由<code>1</code>代表。</p><h4>如何运用？</h4><p>将上面的例子中，后面的闭合引号替换为1：</p><pre class="brush:php">preg_match( '/("|\').*?\1/', $str, $matches );</pre><p>这会正确地返回字串：</p><pre class="brush:php">"This is a 'string'"</pre><blockquote><p><strong>译注思考题：</strong></p><p>如果是中文引号，前引号和后引号不是同一个字符，怎么办？</p></blockquote><p>还记得PHP函数 <code>preg_replace</code> 吗？其中也有回返引用。只不过我们没有用 \1 … \9，而是用了 $1 … $9 … $n （此处任意数目均可）作为回返指针。例如，如果你想把所有的段落标签 <code>&lt;p&gt; </code>都替换成文本：</p><pre class="brush:php">$text = preg_replace( '/&lt;p&gt;(.*?)&lt; \/p&gt;/',
'&amp;lt;p&amp;gt;$1&amp;lt;/p&amp;gt;', $html );</pre><p>参数$1是一个回返引用，代表段落标签<code> </code></p><p><code> </code></p><p>内部的文字，并插入到替换后的文本里。这种简便易用的表达式写法为我们提供了一个获取已匹配文字的简单方法，甚至在替换文本时也能使用。</p><h3>3. 已命名捕获组(Named Groups)</h3><p>当在一个表达式内多次用到回返引用时，很容易就会把自己弄糊涂，判断N个数字（\1 … \9）都到底代表哪一部分会比较困难。这是就可以用到带名字的捕获组（下文简称“有名组”）。有名组使用<code>(?P&lt;pattern&gt;)</code>来设定，name代表组名，pattern是配合该有名组的正则结构。请看下面的例子：</p><pre class="brush:php">/(?P&lt;quote&gt;"|').*?(?P=quote)/</pre><p>上式中，quote就是组名，<code>"|'</code>是改组匹配内容的正则。后面的(?P=quote)是在调用组名为quote的有名组。这个式子的效果和上面的回调引用实例一样，只不过是用了有名组来实现。是不是更加易读易懂了？</p><p>有名组也能用于处理已匹配内容之数组的内部数据。赋予特定正则的组名也能作为所匹配到的内容在数组内部的索引词。</p><pre class="brush:php">preg_match( '/(?P&lt;quote&gt;"|\')/', "'String'", $matches );
# 下面的语句输出“'”(不包括双引号)
echo $matches[1];
# 使用组名调用，也会输出“'”
echo $matches['quote'];</pre><p>所以，有名组并不只是让写代码更容易，它也能用于组织代码。</p><h3>4. 字词边界(Word Boundaries)</h3><p><img
src="http://i27.photobucket.com/albums/c156/jyyjcc/benhuoer-blog/regular-expression/boundary.jpg" alt="Word Boundaries" width="400" height="284" /></p><p><strong>字词边界</strong>是字串里的字词字符（包括字母、数字和下划线，自然也包括汉字）和非字词字符之间的位置。其特殊之处就在于，它并不匹配某个实在的字符。它的长度是<strong>零</strong>。 \<code>b</code> 匹配所有字词边界。</p><p>可惜，字词边界大多数情况下都被无视了，很多人并不知道如何实际运用。 下面举个例子。比如说你想要匹配单词“import”：</p><pre class="brush:php">/import/</pre><p>注意了！正则表达式有时候很调皮的。下面的字串也能和上面的式子匹配成功：</p><pre class="brush:php">important</pre><p>你或许觉得，只要在import前后加上空格，不就可以匹配 import 这个独立的单词了：</p><pre class="brush:php">/ import /</pre><p>那如果遇上这种情况呢：</p><pre class="brush:php">The trader voted for the import</pre><p>当 import 这个词在字串开头或者结尾时，修改后的表达式仍然不能用。因此，考虑各种情况是必须的：</p><pre class="brush:php">/(^import | import | import$)/i</pre><p>别慌，还没完呢。如果遇到标点符号呢？就为了满足这一个单词的匹配，你的正则可能就需要这样写：</p><pre class="brush:php">/(^import(:|;|,)? | import(:|;|,)? | import(\.|\?|!)?$)/i</pre><p>对于只匹配一个单词来说，这样做实在是有点大动干戈了。正因如此，字词边界才显得意义重大。要满足上述要求，以及<strong>很多其他情况</strong>，利用字符边界，只需如此写：</p><pre class="brush:php">/\bimport\b/</pre><p>上面所有情况都得到了解决。\ <code>b</code> 的灵活性就在于，它是一个没有长度的匹配。它只匹配两个实际字符之间想象出的位置。它检查两个相邻字符是否是一个为单字，另一个为非单字。情况符合，就返回匹配。如果遇到了单词的开头或结尾， \<code>b</code> 会把它当成是非单词字符对待。由于import里面的 <code>i</code> 仍然被看成是单词字符，import 就被匹配出来了。</p><p>注意，与<code>\b</code>相对，我们还有\<code>B</code>，此操作符匹配两个单字或者两个非单字之间的位置。因此，如果你想匹配在某个单词内部的‘hi’，可以使用：</p><pre class="brush:php">\Bhi\B</pre><p>“this”、“hight”，都会返回匹配，而“hi there”则不会返回匹配。</p><h3>5. 最小组团(Atomic Groups)</h3><p><img
src="http://i27.photobucket.com/albums/c156/jyyjcc/benhuoer-blog/regular-expression/groups.jpg" alt="Advanced Operators" width="400" height="266" /></p><p><strong>最小组团</strong>是无捕捉的特殊正则表达式分组。通常用来提高正则表达式的效能，也能用于消除特定匹配。一个最小组团可以用(?&gt;pattern) 来定义，其中pattern是匹配式。</p><pre class="brush:php">/(?&gt;his|this)/</pre><p>当正则引擎针对最小组团进行匹配时，它会跳过组团内标记的回溯位置。以单词“smashing”为例，当用上面的正则表达式匹配时，正则引擎会先尝试在“smashing”里寻找“his”。显然，找不到任何匹配。此时，最小组团就发挥作用了：正则引擎会放弃所有回溯位置。也就是说，它不会尝试再从“smashing”里查找“this”。为什么要这样设置？因为“his”都没有返回匹配结果，包含有“his”的“this”当然就更匹配不了了！</p><p>上面的例子并没有什么实用性，我们用<code>/t?his?/</code> 也能达到效果。再看看下面的例子：</p><pre class="brush:php">/\b(engineer|engrave|end)\b/</pre><p>如果把“engineering”拿去匹配，正则引擎会先匹配到“engineer”，但接下来就遇到了字词边界，\<code>b</code>，所以匹配不成功。然后，正则引擎又会尝试在字串里寻找下一个匹配内容：engrave。匹配到eng的时候，后面的又对不上了，匹配失败。最后，尝试“end”，结果同样是失败。仔细观察，你会发现，一旦engineer匹配失败，并且都抵达了字词边界，“engrave”和“end”这两个词就已经不可能匹配成功了。这两个词都比engineer短小，正则引擎不应该再多做无谓的尝试。</p><pre class="brush:php">/\b(?&gt;engineer|engrave|end)\b/</pre><p>上面的替代写法更能节省正则引擎的匹配时间，提高代码的工作效率。</p><h3>6. 递归(Recursion)</h3><p><img
src="http://i27.photobucket.com/albums/c156/jyyjcc/benhuoer-blog/regular-expression/recursion.jpg" alt="Recursion" width="400" height="300" /></p><p><strong>递归(Recursion)</strong>用于匹配嵌套结构，例如括弧嵌套， (this (that))，HTML标签嵌套<code> </code></p><p><code> </code></p><p><code> </code></p><p><code> </code></p><p>。我们使用<code>(?R)</code>来代表递归过程中的子模式。下面是一个匹配嵌套括弧的例子：</p><pre class="brush:php">/\(((?&gt;[^()]+)|(?R))*\)/</pre><p>最外层使用了反义符的括号“<code>(</code>”匹配嵌套结构的开端。然后是一个多选项操作符<code>( * | * )</code>，可能匹配除括号外的所有字符 “<code>(?&gt;[^()]+)</code>”，也可能是通过子模式“<code>(?R)</code>”来再次匹配整个表达式。请注意，这个操作符会尽量多地匹配所有嵌套。</p><p>递归的另一个实例如下：</p><pre class="brush:php">/&lt;([\w]+).*?&gt;((?&gt;[^&lt;&gt;]+)|((?R)))*&lt;\/\1&gt;/</pre><p>以上表达式综合运用了字符分组，贪婪操作符、回溯，以及最小化组团来匹配嵌套标签。第一个括弧内分组<code>([\w]+)</code>匹配出标签名，用于接下来的应用。若找到这尖括号样式的标签，则尝试寻找标签内容的剩余部分。下一个括弧括起来的子表达式和上一个实例非常相似：要么匹配不包括尖括号的所有字符 <code>?&gt;[^&lt;&gt;]+</code>，要么递归匹配整个表达式<code>(?R)</code>。表达式最后的<code>&lt;\/1&gt;</code>代表闭合标签。</p><h3>7. 回调(Callbacks)</h3><p><img
src="http://i27.photobucket.com/albums/c156/jyyjcc/benhuoer-blog/regular-expression/call.jpg" alt="Callbacks" width="400" height="290" /></p><p>匹配结果中的特定内容有时可能会需要某种特别的修改。要应用多重而复杂的修改，正则表达式的<strong>回调</strong>就有了用武之地。回调是用于函数<code>preg_replace_callback</code>中的动态修改字串的方式。你可以为<code>preg_replace_callback</code>指定某个函数为参数，此函数能接收匹配结果数组为参数，并将数组修改后返回，作为替换的结果。</p><p>例如，我们想将某字串中的单词全部转换为首字母大写。十分不巧，PHP没有直接转化字母大小写的正则操作符。要完成这项任务，就可以用到正则回调。首先，我们要匹配出所有需要被大写的字母：</p><pre class="brush:php">/\b\w/</pre><p>上式同时使用了字词边界和字符类。光有这个式子还不够，我们还需要一个回调函数：</p><pre class="brush:php">function upper_case( $matches ) {
return strtoupper( $matches[0] );
}</pre><p>函数<code>upper_case</code>接收匹配结果数组，并将整个匹配结果转化成大写。 在此例中，<code>$matches[0]</code>代表需要被大写的字母。然后，我们再利用<code>preg_replace_callback</code>完成这次回调：</p><pre class="brush:php">preg_replace_callback( '/\b\w/', 'upper_case', $str );</pre><p>一个简单的回调即有这般强大的力量。</p><h3>8. 注释(Commenting)</h3><p><img
src="http://i27.photobucket.com/albums/c156/jyyjcc/benhuoer-blog/regular-expression/comment.jpg" alt="Commenting" width="400" height="300" /></p><p><strong>注释</strong>不用来匹配字串，但确实是正则表达式中最重要的部分。当正则越写越深入，越写越复杂，要推译出究竟什么东西被匹配就会变得越来越困难。在正则表达式中间加上注释，是最小化将来的迷糊和困惑的最佳方式。</p><p>要在正则表达式内部加上注释，使用<code>(?#comment)</code>格式。把“comment”替换成你的注释语句：</p><pre class="brush:php">/(?#数字)\d/</pre><p>如果你打算把代码公之于众，为正则表达式加上注释就显得尤为重要。这样别人才能更容易看懂和修改你的代码。和其他场合的注释一样，这样做也能为你重访自己以前写的程序时提供方便。</p><p>考虑使用“x”或“(?x)”标记位来格式化注释。这个修改器让正则引擎忽略表达式参数之间的空格。“有用的”空格仍然能够通过<code>[ ]</code>或\<code>s</code>，或者\<code> </code>（反义符加空格）来匹配。</p><pre class="brush:php">/
\d    #digit
[ ]   #space
\w+   #word
/x</pre><p>上面的代码与下面的式子作用一样：</p><pre class="brush:php">/\d(?#digit)[ ](?#space)\w+(?#word)/</pre><p>请时刻注意代码的可读性。</p><h3>更多资源（英文）</h3><ul><li><a
href="http://www.regular-expressions.info/" target="_blank">Regular-Expressions.info</a> Comprehensive website on regular expressions</li><li><a
href="http://www.addedbytes.com/cheat-sheets/regular-expressions-cheat-sheet/" target="_blank"> Cheat Sheet</a>Informative regular expressions cheat sheet</li><li><a
href="http://www.jslab.dk/tools.regex.php" target="_blank"> Regex Generator</a>JavaScript regular expressions generator</li></ul><h4>关于作者</h4><p><em>Karthik Viswanathan 是一个喜欢编程和做网站的高中生。你可以到他的博客上查看他的作品：<a
href="http://www.lateralcode.com/" target="_blank">Lateral Code</a>。你也可以关注一下他的线上<a
href="http://twitter.lateralcode.com/" target="_blank">Twitter应用</a>。</em></p><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/javascript" rel="tag">JavaScript</a>, <a
href="http://blog.benhuoer.com/tag/php" rel="tag">php</a>, <a
href="http://blog.benhuoer.com/tag/smashing-magazine" rel="tag">Smashing Magazine</a>, <a
href="http://blog.benhuoer.com/tag/%e6%95%99%e7%a8%8b" rel="tag">教程</a>, <a
href="http://blog.benhuoer.com/tag/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f" rel="tag">正则表达式</a>, <a
href="http://blog.benhuoer.com/tag/%e7%bc%96%e7%a8%8b" rel="tag">编程</a></div><p><small>©2009 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html#comments" target="_blank">已经有10条评论了</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html&title=正则表达式高级技巧背后的关键概念[SM]&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html/feed</wfw:commentRss> <slash:comments>10</slash:comments> </item> <item><title>40个实用的轻量级JavaScript库[SM]</title><link>http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html</link> <comments>http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html#comments</comments> <pubDate>Tue, 10 Mar 2009 10:25:09 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[CSS]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[Smashing Magazine]]></category> <category><![CDATA[Web标准]]></category> <category><![CDATA[免费资源]]></category> <guid
isPermaLink="false">http://blog.benhuoer.com/?p=495</guid> <description><![CDATA[流行的JavaScript库，如jQuery, MooTools, Prototype, Dojo和YUI等，完成起常见的JavaScript任务来得心应手。这些JS库为客户端动作(events)、动画特效(effects)，和AJAX应用等提供很多现成的函数。而且如果这些库中的某一个无法直接达到你要的效果，还可能会有相关插件满足你的要求。 JavaScript库的灵活性给我们的工作提供方便，但有利也有弊——比如说JavaScript文件过大的问题。尽管放弃这些著名的JavaScript库能显示你的聪明才智，但你可能还是会愿意采用一些体积小巧、专注于特定任务的JavaScript库。 以下是40个帮助你达到特定目的的独立JavaScript库。 网上能用的当然不只这些，但每位网页设计师和程序员应该都能在这里有所收获。 1. 表单 wForms wForms 是一个开源的、 无入侵的(unobstrusive)注*代码库，能够简化大部分与表单相关的常用JavaScript函数。 它能对表单的用户输入值进行验证，只需为表单元素添加一个特定的类即可使用。另外，wForms 还具有强大的表单同步（例如“全选/全不选”）和条件表单（如，当x被选择则显示y）功能。 注* 这个词也被译为“不唐突”，“有的放矢”等。意即JavaScript代码和HTML代码分离，同时也对不同版本浏览器选择性地做出反应，以提高用户体验。更多解释，请参照“为之漫笔”。译者认为“无入侵”贴合英文原文，作为术语更加简洁易懂，应该成为这个词的通用译法。 Validanguage Validanguage 是一个无入侵的 JavaScript表单验证框架。 它有一个继承逻辑，可以全局定义，也可以对每个表单或每个元素分别定义。 利用作者提供的两个API，以及诸如综合的AJAX支持(integrated AJAX support)、缓存和调用函数等特性，该框架可以提供强健的(robust)验证体验。两个API用以高级设置，分别是加在注释里的像HTML语言的 API和基于JavaScript对象的API。 LiveValidation LiveValidation是一个轻量级的JavaScript库，提供一系列验证函数。除了经典验证法，此库还具有实时验证(live validation)特性，能根据你键入的文字实时控制特定区域。 Ruby on Rails的开发者会发现LiveValidation异常好用，因为二者的命名规范和参数设置非常相似。虽然它是独立库，不过也有一个Prototype版注*。 注* 也就是依赖于Prototype库，但是本身代码更简洁的版本 yav 一个功能强大、可扩展、使用灵活的表单验证代码库。yav可处理多种情况，从日期、email、整数之类的基本验证到掩码文本框和自定义正则表达式之类的高级应用，都得心应手。该库内建AJAX支持，并且可以轻易在每个对象层自定义错误显示信息。 qForms 处理表单的完全解决方案。为开发者提供诸如多样验证规则，阻止多次提交，锁定/禁用域等特性。 formreform 不用表格来实现多栏布局通常都很有挑战性。这个小巧的代码库能够把一个简单表单转换成一栏、两栏或四栏格式化布局的表单。利用formreform能自动让表单样式适应任何设计。 2. 动画 $fx() $fx() 是一个用户为HTML元素添加动画效果的轻量级代码库。利用此库，你可以指定在一定时间内改变任何CSS属性。对于复杂动画，你可以合并效果，给各效果分组，让它们链式反应或者同时发生。你还可以为每一步动画设定不同的回调动作，进行更深入的自定义。 JSTweener 补间动画的JavaScript库。它的API和著名的ActionScript补间动画引擎 Tweener 相似。你可以调用动画时间，定义形状变换方式和延迟。在几乎任何时间点（如onStart &#8211; 开始时, onComplete -完成时, onUpdate &#8211; [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html" rel="bookmark">正则表达式高级技巧背后的关键概念[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p>流行的<strong>JavaScript库</strong>，如<a
title="jQuery官网" href="http://jquery.com" target="_blank">jQuery</a>, <a
title="Mootools官网" href="http://mootools.net/" target="_blank">MooTools</a>, <a
title="Prototype官网" href="http://www.prototypejs.org/" target="_blank">Prototype</a>, <a
title="dojo官网，貌似最近出问题了" href="http://www.dojotoolkit.org/" target="_blank">Dojo</a>和<a
title="雅虎提供的一个JS库" href="http://developer.yahoo.com/yui/" target="_blank">YUI</a>等，完成起常见的JavaScript任务来得心应手。这些JS库为客户端动作(events)、动画特效(effects)，和AJAX应用等提供很多现成的函数。而且如果这些库中的某一个无法直接达到你要的效果，还可能会有相关插件满足你的要求。</p><p>JavaScript库的灵活性给我们的工作提供方便，但有利也有弊——比如说JavaScript文件过大的问题。尽管放弃这些著名的JavaScript库能显示你的聪明才智，但你可能还是会愿意采用一些体积小巧、专注于特定任务的JavaScript库。</p><p>以下是<strong>40个帮助你达到特定目的的独立JavaScript库</strong>。 网上能用的当然不只这些，但每位网页设计师和程序员应该都能在这里有所收获。</p><h3><span
id="more-495"></span>1. 表单</h3><p><a
href="http://www.formassembly.com/wForms/" target="_blank">wForms</a><br
/> wForms 是一个<strong>开源的</strong>、<strong> 无入侵的(unobstrusive)</strong><strong><sup>注*</sup></strong><strong>代码库</strong>，能够简化大部分与表单相关的常用JavaScript函数。 它能对表单的用户输入值进行验证，只需为表单元素添加一个特定的类即可使用。另外，<strong>wForms</strong> 还具有强大的<strong>表单同步</strong>（例如“全选/全不选”）和<strong>条件表单</strong>（如，当x被选择则显示y）功能。</p><p><span
style="color: #999999;">注* 这个词也被译为“不唐突”，“有的放矢”等。意即JavaScript代码和HTML代码分离，同时也对不同版本浏览器选择性地做出反应，以提高用户体验。更多解释，请参照“<a
href="http://www.cn-cuckoo.com/2007/08/14/unobtrusive-javascript-progressive-enhancement-gracefully-degrade-82.html" target="_blank">为之漫笔</a>”。译者认为“无入侵”贴合英文原文，作为术语更加简洁易懂，应该成为这个词的通用译法。</span></p><p><a
href="http://www.formassembly.com/wForms/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/wforms.gif" border="0" alt="wForms" width="480" height="116" /></a></p><p><a
href="http://www.drlongghost.com/validanguage.php" target="_blank">Validanguage</a><br
/> Validanguage 是一个无入侵的 <strong>JavaScript表单验证框架</strong>。 它有一个继承逻辑，可以全局定义，也可以对每个表单或每个元素分别定义。 利用作者提供的两个API，以及诸如综合的AJAX支持(integrated AJAX support)、缓存和调用函数等特性，该框架可以提供强健的(robust)验证体验。两个API用以高级设置，分别是加在注释里的像HTML语言的 API和基于JavaScript对象的API。</p><p><a
href="http://www.drlongghost.com/validanguage.php" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/validanguage.gif" border="0" alt="Validanguage" width="480" height="116" /></a></p><p><a
href="http://www.livevalidation.com/" target="_blank">LiveValidation</a><br
/> LiveValidation是一个轻量级的JavaScript库，提供一系列验证函数。除了经典验证法，此库还具有实时验证(live validation)特性，能<strong>根据你键入的文字实时控制特定区域</strong>。 <strong>Ruby on Rails</strong>的开发者会发现LiveValidation异常好用，因为二者的命名规范和参数设置非常相似。虽然它是独立库，不过也有一个Prototype版<sup>注*</sup>。</p><p><span
style="color: #999999;">注* 也就是依赖于Prototype库，但是本身代码更简洁的版本</span></p><p><a
href="http://www.livevalidation.com/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/live-validation.gif" alt="LiveValidation" width="480" height="116" /></a></p><p><a
href="http://yav.sourceforge.net/en/index.html" target="_blank">yav</a><br
/> 一个功能强大、可扩展、使用灵活的<strong>表单验证代码库</strong>。<strong>yav</strong>可处理多种情况，从日期、email、整数之类的基本验证到<a
title="JavaScript Mask，利用JavaScript改变输入域在客户端的外观" href="http://www.webresourcesdepot.com/javascript-input-masks/" target="_blank">掩码文本框</a>和自定义正则表达式之类的高级应用，都得心应手。该库内建AJAX支持，并且可以轻易在每个对象层自定义错误显示信息。</p><p><a
href="http://www.pengoworks.com/index.cfm?action=get:qforms" target="_blank">qForms</a><br
/> 处理表单的完全解决方案。为开发者提供诸如多样验证规则，阻止多次提交，锁定/禁用域等特性。</p><p><a
href="http://code.google.com/p/formreform/" target="_blank">formreform</a><br
/> 不用表格来实现多栏布局通常都很有挑战性。这个小巧的代码库能够把一个简单表单转换成一栏、两栏或四栏格式化布局的表单。利用<strong>formreform</strong>能自动让表单样式适应任何设计。</p><p><a
href="http://code.google.com/p/formreform/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/formreform.gif" border="0" alt="formreform" width="480" height="116" /></a></p><h3>2. 动画</h3><p><a
href="http://fx.inetcat.com/" target="_blank">$fx()</a><br
/> <strong>$fx()</strong> 是一个用户为HTML元素添加动画效果的轻量级代码库。利用此库，你可以指定在一定时间内改变任何CSS属性。对于复杂动画，你可以合并效果，给各效果分组，让它们链式反应或者同时发生。你还可以为每一步动画设定不同的回调动作，进行更深入的自定义。</p><p><a
href="http://fx.inetcat.com/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/fx-javascript-animations.jpg" border="0" alt="$fx() JavaScript Animation Library" width="480" height="116" /></a></p><p><a
href="http://coderepos.org/share/wiki/JSTweener" target="_blank">JSTweener</a><br
/> 补间动画的JavaScript库。它的API和著名的ActionScript补间动画引擎 <a
href="http://code.google.com/p/tweener/" target="_blank">Tweener</a> 相似。你可以调用动画时间，定义形状变换方式和延迟。在几乎任何时间点（如onStart &#8211; 开始时, onComplete -完成时, onUpdate &#8211; 更新时），你都可以引发新动作。</p><p><a
href="http://coderepos.org/share/wiki/JSTweener" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/jstweener.gif" border="0" alt="JSTweener" /></a></p><p><a
href="http://developers.facebook.com/animation/" target="_blank">Facebook Animation</a><br
/> 用于创建基于CSS的自定义动画的强大代码库。利用一两行Facebook Animation，你就能改善用户界面。本代码库的语法遵循FBJS（在Facebook实用工具中使用的代码库），一旦学会，你也就具备了创建Facebook实用工具的能力！</p><p><a
href="http://ryanmorr.com/archives/fx-lightweight-and-standalone" target="_blank">FX</a><br
/> 一个轻量级代码库，拥有和YUI类似的使用句法。<strong>FX</strong>可以为几乎所有CSS属性创建补间动画。支持颜色和滚动动画。你只需要设计任意对象，任意属性的起始值和结束值就够了。</p><h3>3. 视觉化和图像特效</h3><p><a
href="http://www.jscharts.com/" target="_blank">JS charts</a><br
/> <strong>JS charts</strong> 可以输出柱状图，饼图和曲线图。只需从一个XML文件或JavaScript数组里调用数据，它就能提供极佳的易用性。图表被输出为png图像文件。该库支持大部分流行的浏览器。</p><p><a
href="http://www.jscharts.com/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/js-charts.jpg" border="0" alt="JS Charts" width="480" height="116" /></a></p><p><a
href="http://www.c3dl.org/" target="_blank">Canvas 3D JS Library (C3DL)</a><br
/> <strong>C3DL</strong>让编写3D应用更加容易。它提供一组算法、场景和3D对象类，对于想在浏览器里开发3D内容，但是对3D图像的深层算法不甚了了的程序员真是不小的福音。</p><p><a
href="http://www.c3dl.org/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/c3dl.jpg" border="0" alt="C3DL" width="480" height="116" /></a></p><p><a
href="http://ejohn.org/blog/processingjs/" target="_blank">Processing.js</a><br
/> 这个JavaScript库指向 <a
href="http://processing.org/" target="_blank">Processing 语言</a> （一个用于图像、动画和交互编程的语言）。它有丰富的特性用于创建2D输出，提供形状/图像绘制方法、颜色处理、字体、对象、算法函数等等。</p><p><a
href="http://ejohn.org/blog/processingjs/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/processing-js.gif" border="0" alt="Processing.js" width="480" height="116" /></a></p><p><a
href="http://raphaeljs.com/" target="_blank">Rapha?l</a><br
/> 一个极赞的代码库，简化在网页中使用矢量图形的工作。Rapha?l 利用<a
title="维基百科上的SVG" href="http://zh.wikipedia.org/wiki/SVG" target="_blank">SVG</a>和<a
title="维基百科上的VML词条" href="http://zh.wikipedia.org/wiki/Vector_Markup_Language" target="_blank">VML</a>来创建图像，并能为这些图像绑定动作处理器。该库功能强大，包括旋转、动画、缩放和绘制曲线、矩形、圆形等。</p><p><a
href="http://raphaeljs.com/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/raphael-js.jpg" border="0" alt="Raphael: Vectors With JavaScript" width="480" height="116" /></a></p><p><a
href="http://www.nihilogic.dk/labs/imagefx/" target="_blank">ImageFX</a><br
/> 可以为图像添加特效，例如模糊、锐化、浮雕、变亮等等。ImageFX使用画布元素来创建效果。兼容所有主流浏览器（你可以在其页面看到兼容性列表）。此库简单易用，只需要在网页中插入.js文件然后用一行代码调用就够了。</p><p><a
href="http://www.nihilogic.dk/labs/imagefx/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/imagefx.jpg" border="0" alt="Imagefx" width="480" height="116" /></a></p><p><a
href="http://www.pixastic.com/" target="_blank">Pixastic</a><br
/> <strong>Pixastic</strong> 使用HTML5的画布对象，此对象可以直接处理像素级数据。支持的效果包括减淡和去色、反相、翻转、亮度和对比度调节、色相和饱和度、浮雕、模糊等等等等。由于画布对象相对较新，各个浏览器对这一JavaScript库的支持程度不尽相同。</p><p><a
href="http://cow.neondragon.net/stuff/reflection/" target="_blank">Reflection.js</a><br
/> 自动创建倒影效果的无侵入JavaScript库。倒影的高度和透明度可以自定义。使用该库就像给图像添加一个“类”一样简单。在所有主流浏览器中都能正常工作，文件大小不过5 KB。</p><p><a
href="http://cow.neondragon.net/stuff/reflection/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/reflection-js.jpg" border="0" alt="Reflection.js" width="480" height="116" /></a></p><h3>4. 数据库</h3><p><a
href="http://taffydb.com/" target="_blank">Taffy DB</a><br
/> 可以作为浏览器中的SQL数据库来使用的JavaScript，也可以看做是一个高级的“数组管理器”。在AJAX化的Web应用中，它可以工作在数据库层。你可以创建、读取、编辑和删除数据，也可以使用循环、归类以及各种高级查询方式。</p><p><a
href="http://www.activerecordjs.org/" target="_blank">ActiveRecord.js</a><br
/> 此库支持Google Gears和Chrome，Aptana Jaxer，Adobe AIR ，以及任何支持W3C HTML5 SQL规范的平台（现在Webkit和iPhone也支持了）。它使在JavaScript利用数据库变得简单。使用<strong>ActiveRecord.js</strong>, 你能自动创建数据表、验证和同步数据等等。</p><p><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/activerecord-js.gif" alt="ActiveRecord.js" width="480" height="116" /></p><h3>5. 字符串和数学函数</h3><p><a
href="http://www.datejs.com/" target="_blank">Date.js</a><br
/> 和日期打交道总是很容易把人搞昏掉。如此多的点、斜杠和格式。<strong>Datejs</strong>以令人耳目一新的方式提供或简单或复杂的日期函数。它可以处理如下格式的日期：“Next thursday”(下星期四), “+2 years”(两年后) 以及诸如2009.01.08, 12/6/2001的所有格式。</p><p><span
style="color: #999999;">译注：此函数很有用啊，哪位朋友来把它汉化成可以支持中文就好了。</span></p><p><a
href="http://www.datejs.com/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/datejs.jpg" border="0" alt="Datejs" width="480" height="116" /></a></p><p><a
href="http://sylvester.jcoglan.com/" target="_blank">Sylvester</a><br
/> 此JavaScript库可以轻松处理矢量和矩阵。有了它你就不用被一串串循环和大量数组搅得头昏脑胀了。此库包含模数化矢量和任意维度的矩阵的类，从而可以计算无限直线的模数和3D空间里的平面。</p><p><span
style="color: #999999;">译注：太高级了，直冒冷汗&#8220;` -_-||</span></p><p><a
href="http://sylvester.jcoglan.com/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/sylvester.gif" border="0" alt="Sylvester" width="480" height="116" /></a></p><p><a
href="http://ejohn.org/projects/javascript-pretty-date/" target="_blank">Pretty Date </a><br
/> 一个聪明的JavaScript解决方案，让过去一个月内的日期以更加漂亮和用户友好的方式显示。它能让日期以距离现在多久的方式显示，如“3天以前”，“昨天”。</p><p><a
href="http://ejohn.org/projects/javascript-pretty-date/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/pretty-date.gif" alt="Pretty Date" width="480" height="116" /></a></p><p><a
href="http://stevenlevithan.com/regex/xregexp/" target="_blank">XRegExp</a><br
/> 正则表达式可以在JavaScript里通过RegExp对象加以利用。 <strong>XRegExp</strong> 能使正则表达式变得更加强大，它提供一些在将来的浏览器才会实现的特性（据 ECMAScript 4 &#8211; ES4 的开发愿景）。使用该库，RegExp对象可以被缓存和再利用，还能为已经存在的RegExp对象添加修改器等等。</p><p><a
href="http://www.fliquidstudios.com/projects/javascript-url-library/" target="_blank">JavaScript URL Library</a><br
/> 一个用与方便处理URLs的JavaScript库。如果需要，它可以控制到将URL内每一个部分当做字符串来处理。这一URL代码库刚出炉不久，但已能像刚才所提一样工作。</p><h3>6. 字体</h3><p><a
href="http://typeface.neocracy.org/" target="_blank">typeface.js</a><br
/> 一个用以在网页上使用任意字体的代码库。与流行的解决方案（如<a
href="http://www.mikeindustries.com/blog/sifr/" target="_blank">sIFR</a> 和 <a
href="http://facelift.mawhorter.net/" target="_blank">FLIR</a>）不同，<strong>typeface.js</strong> 并不需要Flash，是100%的JavaScript应用。要使用任意字体，只需上传其字体文件到一个 <a
href="http://typeface.neocracy.org/fonts.html" target="_blank">基于网页的字体生成器</a>，然后下载渲染过的JavaScript文件，把它添加到你的网页中即可。</p><p><a
href="http://typeface.neocracy.org/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/typeface-js.gif" border="0" alt="Typeface.js" width="480" height="116" /></a></p><p><a
href="http://cufon.shoqolate.com/generate/" target="_blank">Cufón</a><br
/> 与typeface.js十分相似， <strong>Cufón</strong> 也是一个让你在网页中使用TrueType字体的代码库。同样，它也使用一个生成器来将字体文件转换成VML图像。只需在网页中插入generated .js文件，你即可像使用普通字体一样使用你指定的字体。</p><p><span
style="color: #888888;">译注：这两个工具对于中文网页不太实用…… (⊙_⊙)</span></p><h3>7. 调试与记录</h3><p><a
href="http://www.gscottolson.com/blackbirdjs/" target="_blank">Blackbird</a><br
/> 在JavaScript开发过程中，经常会用到alert()函数来添加断点。<strong>Blackbird</strong> 提供一个风格化的控制台，用以记录、查看和过滤JavaScript中的消息，如此即可消除在每个alert()的停顿，并且更好地分析它们，从而加快开发进程。</p><p><a
href="http://www.gscottolson.com/blackbirdjs/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/blackbird.jpg" border="0" alt="Blackbird" width="288" height="116" /></a></p><p><a
href="http://www.nitobibug.com/" target="_blank">NitobiBug</a><br
/> 基于浏览器的，跨浏览器 <strong>JavaScript 对象记录和检测组件</strong>。通过在你的代码中插入规则（和JavaScript对象的用法类似），你可以轻易区别简单类型，如字符串、布尔值和数值，以及复杂元素，如错误信息和JavaScript对象。</p><p><a
href="http://www.nitobibug.com/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/nitobibug.jpg" border="0" alt="NitobiBug" width="480" height="116" /></a></p><p><a
href="http://getfirebug.com/lite.html" target="_blank">Firebug Lite</a><br
/> <strong>Firebug</strong>，大概是世界上最好的JavaScript调试工具，可惜只能在Firefox中使用。要在所有浏览器中拥有一个类似工具，向你的网页添加这个<strong>Firebug Lite</strong> .js文件吧，面对你的是你所熟悉的功能和界面。</p><p><a
href="http://getfirebug.com/lite.html" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/firebug-lite.jpg" border="0" alt="Firebug Lite" width="480" height="116" /></a></p><h3>8. 其他</h3><p><a
href="http://code.google.com/p/swfobject/" target="_blank">swfobject</a><br
/> <strong>swfobject</strong> 是最流行的，扩展性最好的插入Flash影片的方式。此库符合Web标准，生成可以通过验证的标记，能够自动检测用户的Flash播放器版本，如果版本不匹配，它还允许你向用户显示代替内容。你可以看一看“<a
href="http://www.alistapart.com/articles/flashembedcagematch/" target="_blank">为什么应该使用swfobject</a>”这篇文章，写得不错。</p><p><a
href="http://code.google.com/p/swfobject/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/swjobject.jpg" border="0" alt="swfobject" width="480" height="116" /></a></p><p><a
href="http://www.kryogenix.org/code/browser/sorttable/" target="_blank">sorttable</a> and <a
href="http://www.danvk.org/wp/dragtable/" target="_blank">dragtable</a><br
/> 不管你喜不喜欢，表格仍然是展示数据的最佳方式。不过表格还可以更好用： <strong>sorttable</strong> 让表格数据可以排序，升序降序均可。你指向为添加class=”sortable” 属性。你还可以排除某些特定的栏，让他们不自动排序，以及指定升序或者降序哪一个为默认值。<strong>dragtable</strong> 使表格的行列变得可拖动。在网页中插入此库后，同样，给表格添加一个class=”dragtable”即可。如果需要两个功能都用，只需在网页中包含同时两个库，然后添加class=”sortable dragtable” 。</p><p><a
href="http://dillerdesign.com/experiment/DD_roundies/" target="_blank">DD_roundies</a> and <a
href="http://www.dillerdesign.com/experiment/DD_belatedPNG/" target="_blank">DD_belatedPNG</a><br
/> <strong>DD_roundies</strong> 是一个极佳的<strong>不利用图片创建圆角</strong>的JavaScript解决方案。它处理的重点在IE，通过使用VML来解决问题。其他浏览器被忽略，因为他们支持CSS的 border-radius 属性。<span
style="color: #888888;">(译注：Really?)</span></p><p><a
href="http://dillerdesign.com/experiment/DD_roundies/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/javascript-round-corners.jpg" border="0" alt="JavaScript Rounded Corners" width="480" height="116" /></a></p><p><strong>DD_belatedPNG</strong>为臭名昭著的IE6 PNG问题提供了一个可自定义的解决办法。不论PNG图像是用于“src”或是“background-image”中， <strong>DD_belatedPNG</strong> 都能把它解决掉。与其他解决方案不同， “background-position” 和 “background-repeat” 属性也能正常工作！</p><p><span
style="color: #888888;">译注：这个太实用啦！O(∩_∩)O 哈哈~</span></p><p><a
href="http://www.leigeber.com/2008/04/custom-javascript-dialog-boxes/" target="_blank">Custom JavaScript Dialog Boxes</a><br
/> 用于创建<strong>自定义对话框</strong>的轻量级（约 4.5 KB）代码库。四种对话框可用： alerts(出错), warnings(警告), prompts(提示), success(成功)。利用一个简单的函数，你可以自定义对话框的标题，内容和显示时间。</p><p><a
href="http://www.leigeber.com/2008/04/custom-javascript-dialog-boxes/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/custom-dialog-boxes.jpg" border="0" alt="Custom Dialog Boxes" width="480" height="116" /></a></p><p><a
href="http://www.tommysmind.com/gamejs/" target="_blank">GameJS</a><br
/> <strong>GameJS </strong>是一个JavaScript版本的 <a
href="http://www.xna.com/" target="_blank">Microsoft’s XNA 游戏框架</a>， 使用 “画布” 作为渲染机制。JavaScript不是编写游戏的最佳平台。不过如果是那些帧速要求较低的游戏，而你又是一个JavaScript开发者，何乐而不为？ 此库包含一些控制游戏元素、屏幕显示和键盘操作的方便好用的类。</p><p><a
href="http://www.tommysmind.com/gamejs/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/gamejs.jpg" border="0" alt="GameJS" width="480" height="116" /></a></p><p><a
href="http://www.openjs.com/scripts/events/keyboard_shortcuts/" target="_blank">Shortcuts.js</a><br
/> 自从Google Reader和Gmail之后，Web应用里的键盘快捷键变得越来越流行，因为他们大大提升了易用性。<strong>Shorcuts.js</strong>提供更为方便地处理键盘快捷键的函数。 使用该库，创建快捷键，然后在按下键盘的同时就运行函数成为更易实现的可能。</p><p><a
href="http://mapstraction.com/" target="_blank">Mapstraction</a><br
/> 几个不同的地图供应商都提供了各自不同的API。如果你想在供应商之间转换（比如说从Google Map转到MapQuest），则需要重写一些代码。<strong>Mapstraction</strong>就是用来帮你解决这个问题的。它提供一个通用 API ，帮你在大多数流行的地图供应商之间转换。只需更新一行代码，即可转换完毕。</p><p><a
href="http://mapstraction.com/" target="_blank"><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/mapstraction.jpg" border="0" alt="Mapstraction" width="480" height="116" /></a></p><p><a
href="http://amberjack.org/" target="_blank">Amberjack</a><br
/> 一个小巧的JavaScript库，为你的网站添加上漂亮的导游信息。 一旦启用，一个模式化的内容框就能像到导游一样介绍您的站点，框内可以添加任意你想要的内容。导游内容的代码可以手工编写，也可以用<a
href="http://amberjack.org/wizard/" target="_blank">线上工具</a>自动生成。当然，你可以通过编写css或者利用即刻可用的<a
href="http://amberjack.org/skins/" target="_blank">主题</a>来使导游信息符合内容框的样式。</p><p><img
src="http://s27.photobucket.com/albums/c156/jyyjcc/40-js-libraries/amberjack.jpg" border="0" alt="Amberjack" width="480" height="116" /></p><p><a
href="http://jsload.net/" target="_blank">JsLoad</a><br
/> JavaScript库的远程载入API。JsLoad这个简单的API能够让你从Google的服务器上导入大体积JavaScript文件。JsLoad能自动载入任何版本代码库的依赖文件。</p><h4>关于作者</h4><p>Umut Muhaddisoglu是一位网页设计师，同时也是程序员。他维护网站<a
href="http://www.webresourcesdepot.com/" target="_blank">WebResourcesDepot</a>，一个每天提供免费网页设计和开发资源的网志。要联系作者，你可以<a
href="http://twitter.com/umutm" target="_blank">在Twitter上关注他</a>。</p><p><em>(完)</em></p><p
class="entry-title"><span
class="entry-title-link">©原文 </span><a
class="entry-title-link" href="http://www.smashingmagazine.com/2009/03/02/40-stand-alone-javascript-libraries-for-specific-purposes/" target="_blank">40 Useful JavaScript Libraries</a><span
class="entry-source-title-parent"> 来自<a
class="entry-source-title" href="https://www.google.com/reader/view/feed/http%3A%2F%2Frss1.smashingmagazine.com%2Ffeed%2F" target="_blank">Smashing Magazine</a></span> ，作者为 <span
class="entry-author-name">Umut Muhaddisoglu。译者<a
title="笨活儿的部落格" href="http://blog.benhuoer.com/">笨活儿</a>保留译文版权，转载请保留出处和此版权信息。</span><span
class="entry-author-name">欢迎留言指正错误。</span></p><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/crucial-concepts-behind-advanced-regular-expressions.html" rel="bookmark">正则表达式高级技巧背后的关键概念[SM]</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/css" rel="tag">CSS</a>, <a
href="http://blog.benhuoer.com/tag/html5" rel="tag">HTML5</a>, <a
href="http://blog.benhuoer.com/tag/javascript" rel="tag">JavaScript</a>, <a
href="http://blog.benhuoer.com/tag/jquery" rel="tag">jQuery</a>, <a
href="http://blog.benhuoer.com/tag/smashing-magazine" rel="tag">Smashing Magazine</a>, <a
href="http://blog.benhuoer.com/tag/web%e6%a0%87%e5%87%86" rel="tag">Web标准</a>, <a
href="http://blog.benhuoer.com/tag/%e5%85%8d%e8%b4%b9%e8%b5%84%e6%ba%90" rel="tag">免费资源</a></div><p><small>©2009 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html#comments" target="_blank">板凳还在</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html&title=40个实用的轻量级JavaScript库[SM]&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>[Drpal模板制作手册-5]重写可主题化的输出</title><link>http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html</link> <comments>http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html#comments</comments> <pubDate>Sat, 16 Aug 2008 11:05:11 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[drupal]]></category> <category><![CDATA[模板]]></category> <guid
isPermaLink="false">http://jackoko.cn/?p=171</guid> <description><![CDATA[只要当默认的内容标记需要变更时才会用到下面的知识。对于想纯粹使用 样式表 来处理页面表现的，可以跳过这一章节。 重写用于主题化的输出一共有三个要点。首先是要找到输出来源，然后找到可用于覆写的内容，第三是理解其类型。 注意：Drupal会用主题注册表来缓存主题数据。当要建立覆写时必须将其清除 1.找到输出源: 要追踪到输出源可能会有点困难，因为有些可主题化的调用会被继承很多次，在整个系统中来回传播。 链接到一个520KB大小的PDF. Provided for illustration only. 大多数页面元素都是被“绑定” 到 主题(&#8216;页面&#8216;)  中，渲染出导航菜单，导航菜单中的项目，块域，块域中的区块，等等，然后放在 page.tpl.php 模板里。每一块主题化数据通常作为一个主题&#8220;挂钩&#8221; 来引用。 注意: 主题函数和模板现在可以作为主题挂钩来引用。整个系统中还有很多和制作主题没有关系的挂钩。 此文中提到的所有“挂钩”都是指主题挂钩。 现在可以用devel模块来追踪系统输出的标记内容的来源。 It includes a theming tool to easily visualize the source of any output, its type and tons of other theming data. See the screencast for a demonstration. 由于技术限制，此模块Drupal 6以下版本并不适用。 2. 覆写系统： 覆写系统有着一个特定的串联层次，并且很少有例外。Drupal核心与模块通过主题挂钩为它的标记处理提供有意义的默认形式。如果默认形式无法满足主题的需求，则可以阻止默认形式的使用，然后将其替换。通过这种方式，默认样式被抛到一边，而为主题所做的特殊更改则可以完全放置到主题文件夹之内来进行。 决不要试图修改主题文件夹以外的文件。 [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" rel="bookmark">[Drupal模板制作手册-1]主题定制概述</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p><em>只要当默认的内容标记需要变更时才会用到下面的知识。对于想纯粹使用 <a
href="http://drupal.org/node/171209">样式表</a> 来处理页面表现的，可以跳过这一章节。</em></p><p>重写用于主题化的输出一共有三个要点。首先是要找到<a
href="http://drupal.org/node/173880#theming-source">输出来源</a>，然后找到可用于<a
href="http://drupal.org/node/173880#theming-overrides">覆写</a>的内容，第三是理解其<a
href="http://drupal.org/node/173880#theme-type">类型</a>。</p><p><span
id="more-171"></span></p><p><em>注意：Drupal会用</em><a
href="http://drupal.org/node/173880#theme-registry"><em>主题注册表</em></a><em>来缓存主题数据。当要建立覆写时必须将其清除</em></p><p>1.找到输出源:</p><dl
style="width: 430px;"><dd>要追踪到输出源可能会有点困难，因为有些可主题化的调用会被继承很多次，在整个系统中来回传播。</dd></dl><p
style="text-align: center;"><a
href="http://drupal.org/files/theme_tree_1.pdf"><img
class="aligncenter" src="http://drupal.org/files/theme_tree.png" alt="output overrides" /></a><br
/> <em>链接到一个520KB大小的PDF. Provided for illustration only.</em></p><p>大多数页面元素都是被“<a
href="http://api.drupal.org/api/function/template_preprocess_page">绑定</a>” 到 <em>主题</em>(&#8216;<em>页面</em>&#8216;)  中，渲染出导航菜单，导航菜单中的项目，块域，块域中的区块，等等，然后放在 <em>page.tpl.php</em> 模板里。每一块主题化数据通常作为一个主题<em>&#8220;挂钩&#8221;</em> 来引用。</p><p><em>注意: 主题函数和模板现在可以作为主题挂钩来引用。整个系统中还有很多和制作主题没有关系的挂钩。 此文中提到的所有“挂钩”都是指主题挂钩。</em></p><p>现在可以用<a
href="http://drupal.org/project/devel">devel模块</a>来追踪系统输出的标记内容的来源。 It includes a theming tool to easily visualize the source of any output, its type and tons of other theming data. See the <a
href="http://drupal.org/node/209561">screencast</a> for a demonstration. <em>由于技术限制，此模块Drupal 6以下版本并不适用。</em></p><p>2. 覆写系统：</p><dd>覆写系统有着一个特定的串联层次，并且很少有例外。Drupal核心与模块通过主题<em>挂钩</em>为它的标记处理提供有意义的默认形式。如果默认形式无法满足主题的需求，则可以阻止默认形式的使用，然后将其替换。通过这种方式，默认样式被抛到一边，而为主题所做的特殊更改则可以完全放置到主题文件夹之内来进行。 决不要试图修改主题文件夹以外的文件。</dd><dd
style="text-align: center;"><img
src="http://drupal.org/files/theme_overrides_0.png" alt="output overrides" /></dd><p>如果你需要在这些主题化约定之外控制更多东西，试试 <a
href="http://drupal.org/node/223463">主题注册表</a> 。</p><p><em>注意：尽管仍然可能实施，Drupal 6中的PHPTemplate.engine将不再覆写主题函数。. In 5, that is what allowed templates to be used for a handful of the theming hooks. 现在没有必要这么做。</em></p><dt
id="theme-type">3. 函数还是模板:</dt><p>如上所说，有两种方式，或者“类型”，可以达到处理挂钩的目的。普通的<em>&#8220;函数(functions)&#8221;</em> 或者<em>&#8220;模板(templates)&#8221;。</em>根据主题化元素的性质，这两种方式各有适用范围。核心与模块可以通过两种方式的任意一种来生成输出。The upper theming layers can carry over the same type or change it.</p><p
class="tips" style="text-align: center;"><a
href="http://drupal.org/files/theme_flow_6_1.pdf"><img
class="aligncenter" src="http://drupal.org/files/theme_flow_6.png" alt="theme flow - function vs template" /></a><br
/> <em>链接到一个PDF文档. <a
href="http://drupal.org/files/theme_flow_5_1.pdf">Flow map for 5</a> also available for comparison.</em></p><p
class="tips" style="text-align: center;"><a
href="/wp-content/uploads/2008/08/theme_flow_6_1.pdf"><strong>中文版</strong></a><strong>[不完全翻译]</strong></p><p>通过函数来应用的主题挂钩速度更快。通常来说会比用模板快五倍左右。但是对于只熟悉xhtml的设计者来说，用模板肯定要简单一些。通常情况下，这些速度不用被考虑，因为这也取决于挂钩的性质和它在页面中被调用的次数。</p><p><em>Note: In versions before 6, core and modules could only work as functions for the theming hooks. Implementing through templates was done by PHPTemplate by overriding the hooks and doing the conversion on the engine layer.</em></p><p>以下是在devel themer模块的帮助下进行覆写的两个例子。</p><dl
style="width: 550px;"><dt
id="function-override">覆写函数：</dt><dd>主题函数<a
href="http://api.drupal.org/api/function/theme_menu_local_tasks/6">theme_menu_local_tasks</a> 是一个用于输出primary和secondary标签页的简单函数。（也就是Drupal中默认带有的primary menu和secondary menu这两个菜单。）这个例子中的挂钩就是&#8221;<em>menu_local_tasks</em>&#8220;. 要重写它，函数中的&#8221;theme&#8221; 前缀可以被改为你的主题名或者你正在使用的主题引擎（如phptemplate）的名字。我们建议你使用主题名，以防止将来可能会和<a
href="http://drupal.org/node/225125">子主题</a>产生冲突。<img
class="aligncenter" src="http://drupal.org/files/function_override_example_2.png" alt="search override" width="572" height="194" /><em>此例显示系统默认的Garland主题使用的是主题引擎的名字来覆写。如果你要用Garlan作为父主题建立一个子主题，你就必须使用主题名来进行覆写。</em>将以下代码放到主题的template.php文件中就可以覆写默认输出。要看到结果需要先清理主题注册表。 <em>把&#8221;drop&#8221; 改为你的主题名。</em></p><div
class="codeblock"><code><span
style="color: #000000;"><span
style="color: #0000bb;">&lt;?php<br
/> </span><span
style="color: #007700;">function </span><span
style="color: #0000bb;">drop_menu_local_tasks</span><span
style="color: #007700;">() {<br
/> </span><span
style="color: #0000bb;">$output </span><span
style="color: #007700;">= </span><span
style="color: #dd0000;">''</span><span
style="color: #007700;">;  if (<span
style="color: #0000bb;">$primary </span><span
style="color: #007700;">= </span><span
style="color: #0000bb;">menu_primary_local_tasks</span><span
style="color: #007700;">()) {<br
/> </span><span
style="color: #0000bb;">$output </span><span
style="color: #007700;">.= </span><span
style="color: #dd0000;">"&lt;ol class="tabs primary"&gt;n"</span><span
style="color: #007700;">. </span><span
style="color: #0000bb;">$primary </span><span
style="color: #007700;">.</span><span
style="color: #dd0000;">"&lt;/ol&gt;n"</span><span
style="color: #007700;">;<br
/> }<br
/> if (</span><span
style="color: #0000bb;">$secondary </span><span
style="color: #007700;">= </span><span
style="color: #0000bb;">menu_secondary_local_tasks</span><span
style="color: #007700;">()) {<br
/> </span><span
style="color: #0000bb;">$output </span><span
style="color: #007700;">.= </span><span
style="color: #dd0000;">"&lt;ol class="tabs secondary"&gt;n"</span><span
style="color: #007700;">. </span><span
style="color: #0000bb;">$secondary </span><span
style="color: #007700;">.</span><span
style="color: #dd0000;">"&lt;/ol&gt;n"</span></p><div><span
style="color: #007700;">;<br
/> }</span></div><p><span
style="color: #007700;"> return <span
style="color: #0000bb;">$output</span><span
style="color: #007700;">;<br
/> }<br
/> </span><span
style="color: #0000bb;">?&gt;</span></span></p><div><span
style="color: #007700;">这里所做的改变仅仅是把无序列表变成了有序列表。</span></div><p><span
style="color: #007700;"><em>全部<a
href="http://api.drupal.org/api/group/themeable/6">theme函数</a>的列表可以在<a
href="http://api.drupal.org/">api.drupal.org</a>找到。</em></span></p><div><span
style="color: #007700;"> </span></div><p><span
style="color: #007700;"> </span></p><p><span
style="color: #007700;"> </span></p><p></span></span></code></p></div></dd><dt
id="template-override">覆写模板：</dt><dd>If the default implementation is done as a template then simply moving the source template file into the theme will automatically override it after clearing the theme registry. 这里有一个针对<a
href="http://api.drupal.org/api/file/modules/search/search-theme-form.tpl.php/6/source">search-theme-form.tpl.php</a>的例子。 Note that the theming hook in this case is &#8220;<em>search_theme_form</em>&#8221; with the template using hyphens instead of underscores.<img
class="aligncenter" src="http://drupal.org/files/template_override_example_2.png" alt="search override" width="540" height="213" />That is all you need to do.只要把主题模板文件找到，复制到你自己的主题文件夹中的任意位置，然后做出自己的更改就可以了。. All the core .tpl.php files are documented. It should give a good indication on what can be done with the output.<em>Note: templates can be placed in any directory within the theme. This allows for better management and less clutter in the base level of the theme directory.</em>Related pages:</p><ul
class="tips"><li><em>To customize the variables inside templates, see the sub-page on <a
href="http://drupal.org/node/223430">Preprocess functions</a>.</em></li><li><em>A listing of all the theme templates can be found on the sub-page, <a
href="http://drupal.org/node/190815">Core templates and suggestions</a>.</em></li></ul></dd><dt
id="convert-type">从函数转换为模板</dt><dd>将函数转换为模板需要做一点初始工作，但是一旦完成，数据将变得更易处理。 如果你在和一个设计师合作，这样的转换就能帮助他们关注于页面设计，而非编写代码。 Drupal核心中已经有很多模板可供控制，将来会有更多的。Drupal社区中共享的模块如果编写得当，也应该提供有了相应的模板。 These instructions are provided for the theming hooks not already made available as templates.Getting Drupal to recognize the theming hook as a template is automated. These are the only requirements to trigger this change:</p><ul><li>Name of the template must match the theming hook.</li><li>The underscores in the hook must be changed to hyphens.</li><li>The template name must have an extension of &#8220;.tpl.php&#8221;. <em>(It can vary based on the theme engine.)</em></li></ul><p>Consider the theming function <a
href="http://api.drupal.org/api/function/theme_user_signature/6">theme_user_signature</a>. The theme hook here is &#8220;<em>user_signature</em>&#8220;. Creating a file named &#8220;user-signature.tpl.php&#8221; will tell Drupal that the hook is now a template after clearing the registry. Any content in this file will now take the place of the function. The part that takes more work is setting up the variables to be used in this file and that is done through preprocess functions.</p><p><em>A few notes:</em></p><ul
class="tips"><li><em>While it is possible to code directly inside the template, it is not considered good practice. All the complex logic should be separated from the .tpl.php file. This keeps it clean and easy to manage.</em></li><li
class="marker"><em>There is also the issue of security. The separation can minimize the chance of cross-site scripting attacks by cleaning out potentially malicious user generated content. When handing over template files to your designer, all the output should be clean so they do not have to concern themselves with security issues.</em></li><li><em>Compare the <a
href="http://api.drupal.org/apis/5/theme_forum">theming functions in 5</a> to the <a
href="http://api.drupal.org/apis/6/template_preprocess_forum">template conversions in 6</a> for forums. You can use that as an example on converting between the two types.</em></li><li><em>More information on <a
href="http://drupal.org/node/223430">preprocess functions</a> available.</em></li></ul></dd></dl><dt
id="theme-registry">主题注册表：</dt><dd>Drupal&#8217;s theme registry maintains cached data on the available theming hooks and how to handle them.</dd><dl></dl><p>对于大多数开发者来说，这些注册表项不会被直接接触到。只要记得在增删主题函数和模板的时候清理注册表就好了。 编辑已有函数和模板不需要重建注册表。</p><p>要清空主题注册表，执行以下步骤之一：</p><ol
class="tips"><li>点击&#8221;管理&gt;站点配置&gt;性能&#8221;中的清除缓存按钮。</li><li>如果启用了devel 区块<em>(由devel模块提供)</em>，点击“清空缓存(Clear Cache)”链接</li><li>使用API函数<a
href="http://api.drupal.org/api/function/drupal_rebuild_theme_registry/6">drupal_rebuild_theme_registry</a>.</li></ol><p>The theme registry is cached data instructing Drupal on the available theming hooks and how to handle it by indicating its type. In previous versions all theming calls were handled on the fly. Since a lot more work is being done under the hood, the cached instructions speeds up the process especially for templates. The theme engine your theme is running under should automatically register all the theming hooks for you.</p><p>There are special cases where you may need to work with the registry directly. When your theme requires a new hook to be registered that was not already implemented on the layers below it <em>(core, modules, engine)</em>. This includes some forms when they are not explicitly themed by core or modules but instead rely on the default form presentation.</p><ul
class="tips"><li><em>More details can be found in the sub-page, <a
href="http://drupal.org/node/223463">The theme registry for special cases</a>.</em></li><li><em>Do not confuse the theme registry with the <a
href="http://drupal.org/node/171205">theme&#8217;s .info</a> file which is also cached. Points 1 and 2 on clearing the registry will clear both.</em></li></ul><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" rel="bookmark">[Drupal模板制作手册-1]主题定制概述</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/drupal" rel="tag">drupal</a>, <a
href="http://blog.benhuoer.com/tag/%e6%a8%a1%e6%9d%bf" rel="tag">模板</a></div><p><small>©2008 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html#comments" target="_blank">已经有3条评论了</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html&title=[Drpal模板制作手册-5]重写可主题化的输出&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html/feed</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>[Drupal模板制作手册-4]主题的.info文件</title><link>http://blog.benhuoer.com/posts/info-files-for-themes.html</link> <comments>http://blog.benhuoer.com/posts/info-files-for-themes.html#comments</comments> <pubDate>Sun, 10 Aug 2008 14:14:28 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[CSS]]></category> <category><![CDATA[drupal]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[jQuery]]></category> <category><![CDATA[模板]]></category> <guid
isPermaLink="false">http://jackoko.cn/?p=161</guid> <description><![CDATA[从Drupal 6开始，每个主题都需要一个信息文件。这个文件必须一直在你的主题的根目录下。没有这个文件，你的主题将不会被Drupal侦测到。  .info文件必须是以&#8221;.info&#8221;为文件后缀名。 &#8220;机器&#8221; 可读的主题的[内部名]来源于这个文件。例如，如果这个文件的被命名为&#8221;drop.info&#8221;, 那么Drupal就好认为相应的主题名为&#8221;drop&#8221;。请注意不要用特殊字符，因为Drupal会在很多PHP函数中用到这个名字因此在PHP语言中命名字符串的限制也适用于这个内部名的命名。必须以字母开头，不可带空格和标点。可以使用下划线(_)但不可以使用连字号(-)。数字也是被允许的，只是不能用作首字符。 注意： 警告! 和你的主题内部名相同的模块可能会造成站点无法工作。因为这可能引起函数的重复定义，而这是不被PHP允许的。你安装的所有外部组件都必须有唯一的名字。 .info文件的内容被换成在数据库中，所有替换或者修改这个文件并不会引起Drupal的注意。（不要将这种情况和主题注册表的缓存好混淆。）要清楚缓存，执行以下步骤： 点击位于&#8221;管理(Administer) &#62; 站点设置(Site configuration) &#62; 性能(Performance)&#8221;的&#8221;清除缓存数据(clear)&#8221; 按钮。 如果开启了devel区块(由模块devel提供) ，点击链接 &#8220;清空缓存(Empty cache)&#8221; 。 再次访问位于&#8221;管理(Administer) &#62; 站点构建(Site building) &#62; 主题(Themes)&#8221;的主题选择页面。 语法与 INI 文件类似。.info文件本质上就是一个配置主题的文本文档。该文本文档的每一行都是一个键-值对，左边是键名，右边是值。 中间再加个等号。(例如: key = value) 分号用以在行外面添加注释。某些键需要特殊的语法。添加方括号组合一系列关联的值，相当于一个“数组”。如果你并不熟悉数组，使用这种键值对时就应该保持足够的简单易懂。你可以参考Drupal中默认的.info文档，仔细阅读其中的注释信息 Drupal只懂得下列的键名（带!号的为必须设定的键值)。Drupal会为没有在.info文件中指定的键使用默认值。看看核心主题的示例。 name ! description * screenshot version * core ! engine * base theme regions features stylesheets scripts php name (必须) 人类易读的名字可以在这里设定，相对于&#8221;机读&#8221;内部名而言。这里对可用字符的限制更少。 [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" rel="bookmark">[Drpal模板制作手册-5]重写可主题化的输出</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" rel="bookmark">[Drupal模板制作手册-1]主题定制概述</a></li><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p>从Drupal 6开始，每个主题都需要一个信息文件。这个文件必须一直在你的主题的根目录下。没有这个文件，你的主题将不会被Drupal侦测到。  .info文件必须是以&#8221;.info&#8221;为文件后缀名。</p><p>&#8220;机器&#8221; 可读的主题的[内部名]来源于这个文件。例如，如果这个文件的被命名为&#8221;drop.info&#8221;, 那么Drupal就好认为相应的主题名为&#8221;drop&#8221;。请注意不要用特殊字符，因为Drupal会在很多<a
href="http://us3.php.net/manual/en/language.functions.php">PHP函数</a>中用到这个名字因此在PHP语言中命名字符串的限制也适用于这个内部名的命名。必须以字母开头，不可带空格和标点。可以使用下划线(_)但不可以使用连字号(-)。数字也是被允许的，只是不能用作首字符。</p><p><span
id="more-161"></span></p><p><em
class="tips">注意：</em></p><ul
class="tips"><li
class="marker"><em>警告! 和你的主题内部名相同的模块可能会造成站点无法工作。因为这可能引起函数的重复定义，而这是不被PHP允许的。你安装的所有外部组件都必须有唯一的名字。</em></li><li><em>.info文件的内容被换成在数据库中，所有替换或者修改这个文件并不会引起Drupal的注意。（不要将这种情况和</em><em
class="tips"><a
href="http://drupal.org/node/173880#theme-registry">主题注册表</a>的缓存好混淆。）</em>要清楚缓存，执行以下步骤：<ol><li><em>点击位于&#8221;管理(Administer) &gt; 站点设置(Site configuration) &gt; 性能(Performance)&#8221;的&#8221;清除缓存数据(clear)&#8221; 按钮。</em></li><li><em>如果开启了devel区块</em><em
class="tips">(由模块devel提供) ，点击链接 </em>&#8220;清空缓存(Empty cache)&#8221; 。</li><li><em>再次访问位于&#8221;管理(Administer) &gt; 站点构建(Site building) &gt; 主题(Themes)&#8221;的主题选择页面。</em></li></ol></li></ul><p>语法与 <a
href="http://en.wikipedia.org/wiki/INI_file">INI</a> 文件类似。.info文件本质上就是一个配置主题的文本文档。该文本文档的每一行都是一个键-值对，左边是键名，右边是值。 中间再加个等号。<em>(例如: <code>key = value</code>)</em> 分号用以在行外面添加注释。某些键需要特殊的语法。添加方括号组合一系列关联的值，相当于一个“数组”。如果你并不熟悉数组，使用这种键值对时就应该保持足够的简单易懂。你可以参考Drupal中默认的.info文档，仔细阅读其中的注释信息</p><p>Drupal只懂得下列的键名（带!号的为必须设定的键值)。Drupal会为没有在.info文件中指定的键使用<a
href="http://drupal.org/node/171206">默认值</a>。<em
class="tips">看看核心主题的<a
href="http://drupal.org/node/171205#example">示例</a>。</em></p><ul><li><a
href="http://drupal.org/node/171205#name">name</a> <em
class="tips marker">!</em></li><li><a
href="http://drupal.org/node/171205#description">description</a> <em
class="tips">*</em></li><li><a
href="http://drupal.org/node/171205#screenshot">screenshot</a></li><li><a
href="http://drupal.org/node/171205#version">version</a> <em
class="tips">*</em></li><li><a
href="http://drupal.org/node/171205#core">core</a> <em
class="tips marker">!</em></li><li><a
href="http://drupal.org/node/171205#engine">engine</a> <em
class="tips">*</em></li><li><a
href="http://drupal.org/node/171205#base-theme">base theme</a></li><li><a
href="http://drupal.org/node/171205#regions">regions</a></li><li><a
href="http://drupal.org/node/171205#features">features</a></li><li><a
href="http://drupal.org/node/171205#stylesheets">stylesheets</a></li><li><a
href="http://drupal.org/node/171205#scripts">scripts</a></li><li><a
href="http://drupal.org/node/171205#php">php</a></li></ul><dl><dt
id="name">name <em
class="tips marker">(必须)</em></dt><dd>人类易读的名字可以在这里设定，相对于&#8221;机读&#8221;内部名而言。这里对可用字符的限制更少。</p><div
class="codeblock"><code>name = Un tema nombre de fantasía<br
/> </code></div></dd><dt
id="description">description <em
class="tips">(必须)</em></dt><dd>主题的简短描述。 这个名字会被显示在管理界面的主题选择页面。&#8221;Administer &gt; Site building &gt; themes&#8221;.</p><div
class="codeblock"><code>description = Tableless multi-column theme designed for blogs.<br
/> </code></div></dd><dt
id="screenshot">screenshot</dt><dd>这个可选的键值告诉Drupal哪里去找寻该主题的截屏缩略图，用于在主题选择页面显示(admin/build/themes)。如果跳过不设定，Drupal会查找改主题根目录下名为&#8221;screenshot.png&#8221;的文件。所以请当你的缩略图不是&#8221;screenshot.png&#8221;时或者你想要把缩略图放在主题根目录以外的文件夹中(如 <code>screenshot = images/screenshot.png</code>)，才设定此项。 <code>screenshot = screenshot.png<br
/> </code></dd><dt
id="version">version <em
class="tips">(建议)</em></dt><dd>The version string will automatically be added by drupal.org when a release is created and a tarball packaged. So you may omit this value for contributed themes. However, if your theme is not being hosted on the drupal.org infrastructure, you can give your theme whatever version string makes sense. 设置你开发的主题的版本。</p><div
class="codeblock"><code>version = 1.0<br
/> </code></div></dd><dt
id="core">core <em
class="tips marker">(必须)</em></dt><dd>指定主题使用的核心。Drupal 6之后的版本会检测组件的版本匹配指定，如果不相符或者不知道，该组件都会被禁用。<a
href="http://api.drupal.org/api/constant/DRUPAL_CORE_COMPATIBILITY">DRUPAL_CORE_COMPATIBILITY常量。</a></p><div
class="codeblock"><code>core = 6.x<br
/> </code></div><p><em
class="tips">The drupal.org packaging script automatically sets this value based on the Drupal core compatibility setting on each release node. So people downloading packaged themes from drupal.org will always get the right thing. However, for sites that deploy Drupal directly from CVS, it helps if you commit this change to the .info file for your theme. This is also a good way to indicate to users of each theme what version of core the <a
href="http://drupal.org/handbook/cvs/introduction#HEAD">HEAD</a> of CVS is compatibile with at any given time.</em></p></dd><dt
id="engine">engine <em
class="tips">(建议)</em></dt><dd>一般情况下直接设置为phptemplate就可以了。The theme engine, which is used by the theme. If none is provided, the theme is assumed to be stand alone, i.e., implemented with a &#8220;.theme&#8221; file. Most themes should use &#8220;phptemplate&#8221; as the default engine.<em
class="tips">PHPTemplate&#8217;s job is to discover theme functions and templates for the behavior of the theme. Omit this entry only if you know what you are doing.</em></p><div
class="codeblock"><code>engine = phptemplate<br
/> </code></div></dd><dt
id="base-theme">base theme</dt><dd>当你的主题需要作为子主题来使用时，给他指定一个基础主题。Sub-themes can declare a base theme. This allows for theme inheritance, meaning the resources from the &#8220;base theme&#8221; will cascade and be reused inside the sub-theme. Sub-themes can declare other sub-themes as their base, allowing multiple levels of inheritance. Use the internal &#8220;machine&#8221; readable name of the base theme. The following is used in Minnelli, the sub-theme of Garland.</p><div
class="codeblock"><code>base theme = garland<br
/> </code></div><p><em
class="tips">More details are available on the page <a
href="http://drupal.org/node/225125">Sub-themes, their structure and inheritance</a>.</em></p></dd><dt
id="regions">regions</dt><dd>主题的可用“块域”。定义方法为在&#8217;<code>regions</code>&#8216;后面添加方括号括起来的“机读”内部名作为键名，然后将方便人类阅读的名字作为键值。如<code>regions[theRegion] = The region name。</code>如果没有块域被定义，Drupal会假定下列块域可用。如果需要，你可以覆写这些值。</p><div
class="codeblock"><code>regions[left] = Left sidebar<br
/> regions[right] = Right sidebar<br
/> regions[content] = Content<br
/> regions[header] = Header<br
/> regions[footer] = Footer<br
/> </code></div><p><em
class="tips">更多细节：<a
href="http://drupal.org/node/171224">Blocks, content and their regions</a></em></p></dd><dt
id="features">features</dt><dd>在主题设定页面可以选择开关的主题特性。&#8221;features&#8221; 键控制在主题设置页面哪些特性可以设定。当你的主题没有定义某些元素的时候你就可以使用这个键值来关闭这些元素显示与否的可设置性。要停用某项设置的复选框，略过这个条目不写即可。但是，如果所有条目都不写，由于系统的默认假定，所有的复选框都会被显示出来。下面的例子显示了所有可用的设定项。.通过注释掉<code>primary_links和</code><code>secondary_links元素</code>，相应的复选框就被禁止显示，不会被站点管理员看到。</p><div
class="codeblock"><code>features[] = logo<br
/> features[] = name<br
/> features[] = slogan<br
/> features[] = mission<br
/> features[] = node_user_picture<br
/> features[] = comment_user_picture<br
/> features[] = search<br
/> features[] = favicon<br
/> ; These last two disabled by redefining the<br
/> ; above defaults with only the needed features.<br
/> ; features[] = primary_links<br
/> ; features[] = secondary_links<br
/> </code></div><p><em
class="tips">更多细节： <a
href="http://drupal.org/node/221905">Custom theme settings</a></em></p></dd><dt
id="stylesheets">stylesheets</dt><dd>以前，默认地，主题是通过自动查找style.css文件，然后调用template.php文件中 <a
href="http://api.drupal.org/api/function/drupal_add_css">drupal_add_css()</a> 函数来添加额外的样式表。 从Drupal 6开始，.info文件也可以为主题添加样式表。</p><div
class="codeblock"><code>stylesheets[all][] = theStyle.css<br
/> </code></div><p><em
class="tips">更多细节在<a
href="http://drupal.org/node/171209">样式表</a>一节</em></p></dd></dl><dt
id="scripts">scripts[与stylesheets同理]</dt><dd>Traditionally, themes could add javascripts by calling <a
href="http://api.drupal.org/api/function/drupal_add_js">drupal_add_js()</a> in their template.php file. Starting in 6.x, themes can also add javascripts by adding lines to their .info file:</dd><dd></dd><dd><code>scripts[] = script.js<br
/> </code><em
class="tips">More details are available in the <a
href="http://drupal.org/node/171213">JavaScript &amp; jQuery</a> section.</em></dd><dt
id="php">php</dt><dd>定义主题可以支持的最低<strong>PHP版本</strong>。The default value is derived from the <a
href="http://api.drupal.org/api/constant/DRUPAL_MINIMUM_PHP">DRUPAL_MINIMUM_PHP</a> constant, which is the minimum required version for the rest of core. This can be redefined for a newer version if needed. For most themes, this should not be added.</dd><dd></dd><dd><code>php = 4.3.3<br
/> </code></dd><p><strong
id="example">Example .info files from core themes</strong></p><p>Garland:<br
/> <img
src="http://drupal.org/files/info_display.png" alt="theme administration display" /></p><div
class="codeblock"><code>; $Id: garland.info,v 1.5 2007/07/01 23:27:32 goba Exp $<br
/> name = Garland<br
/> description = Tableless, recolorable, multi-column, fluid width theme (default).<br
/> version = VERSION<br
/> core = 6.x<br
/> engine = phptemplate<br
/> stylesheets[all][] = style.css<br
/> stylesheets[print][] = print.css</code>Minnelli <em
class="tip">sub-theme of Garland.</em>:</div><div
class="codeblock"><code>; $Id: minnelli.info,v 1.7 2007/12/04 20:58:44 goba Exp $<br
/> name = Minnelli<br
/> description = Tableless, recolorable, multi-column, fixed width theme.<br
/> version = VERSION<br
/> core = 6.x<br
/> base theme = garland<br
/> stylesheets[all][] = minnelli.css</code><em
class="tips">Note that everything from the line &#8220;; Information added by drupal.org packaging script on 2008-02-13&#8243; and down is added by the drupal.org packaging script. You should never manually add the project and datestamp keys. The version key added manually (in the first section) allows sites to use your theme when taken directly from CVS.</em></div><p>; Information added by drupal.org packaging script on 2008-02-13<br
/> version = &#8220;6.0&#8243;<br
/> project = &#8220;drupal&#8221;<br
/> datestamp = &#8220;1202913006&#8243;</p><p>; Information added by drupal.org packaging script on 2008-02-13<br
/> version = &#8220;6.0&#8243;<br
/> project = &#8220;drupal&#8221;<br
/> datestamp = &#8220;1202913006&#8243;</p><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" rel="bookmark">[Drpal模板制作手册-5]重写可主题化的输出</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" rel="bookmark">[Drupal模板制作手册-1]主题定制概述</a></li><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/css" rel="tag">CSS</a>, <a
href="http://blog.benhuoer.com/tag/drupal" rel="tag">drupal</a>, <a
href="http://blog.benhuoer.com/tag/javascript" rel="tag">JavaScript</a>, <a
href="http://blog.benhuoer.com/tag/jquery" rel="tag">jQuery</a>, <a
href="http://blog.benhuoer.com/tag/%e6%a8%a1%e6%9d%bf" rel="tag">模板</a></div><p><small>©2008 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html#comments" target="_blank">板凳还在</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/info-files-for-themes.html&title=[Drupal模板制作手册-4]主题的.info文件&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/info-files-for-themes.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>[Drupal模板制作手册-3]子主题，结构与继承</title><link>http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html</link> <comments>http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html#comments</comments> <pubDate>Sun, 10 Aug 2008 12:22:00 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[CSS]]></category> <category><![CDATA[drupal]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[主题]]></category> <category><![CDATA[模板]]></category> <category><![CDATA[继承]]></category> <guid
isPermaLink="false">http://jackoko.cn/?p=149</guid> <description><![CDATA[子主题(sub-theme)和其他主题基本一样，只有一个区别：它们可以继承父主题(parent-theme)的资源(如CSS和JavaScript文档、icon图标等)。在父主题给子主题的资源传递链上，没有传递层级的限制。一个主题可以是另一个子主题的子主题，并且可以分支出N个它自己的子主题，没有个数和层级的限制。 想象一下从设计一个基本主题(base theme)作为模型开始， 然后添加一些子主题，在子主题上完善你的网页样式。再然后，依据这同一个模型，试试分支出一些其他样式的子主题。需要同时建立多个站点，但是需要有共性的外观感觉？ 有了子主题功能，一系列设计资源都可以共享. 特定站点外观可以组织到特定的子主题中，但是一旦需要改变某个共同特性，只需要编辑一次共有资源中的某项，即可应用到所有主题。只要规划得当，此功能可以给你带来无限可能。 要声明一个父主题，或成为“基本主题”，将下列语句添加到子主题的.info文件中，“themeName”替换为您的父主题的内部名字。 base theme = themeName 下列资源会被继承: 父主题中定义的所有样式表，但是这也是可以通过某些选项来控制的。 父主题中定义的所有JavaScripts。 所有的模板文件(.tpl.php)。 文件&#8221;template.php&#8221;中定义的所有内容。包括主题函数重写, 预处理器和其他所有东西。所有子主题把它自己的template.php文件和父主题的该文件包含在一起。 父主题的截图，只要.info文件使用了和他的父主题一样的设置。 下列资源不会被继承： 为父主题制定的logo.png文件。不包括用户上传的logo，因为他们总是会被使用。 .info文件定义的某些设置。 This includes regions. If you are not using the default regions, then make sure your &#8220;page.tpl.php&#8221; file for the sub-theme matches what is set for regions in the .info file. Each base and sub-theme can [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" rel="bookmark">[Drpal模板制作手册-5]重写可主题化的输出</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" rel="bookmark">[Drupal模板制作手册-1]主题定制概述</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p>子主题(sub-theme)和其他主题基本一样，只有一个区别：它们可以继承父主题(parent-theme)的资源(如CSS和JavaScript文档、icon图标等)。在父主题给子主题的资源传递链上，没有传递层级的限制。一个主题可以是另一个子主题的子主题，并且可以分支出N个它自己的子主题，没有个数和层级的限制。</p><p
style="TEXT-ALIGN: center"><img
class="aligncenter" src="http://drupal.org/files/sub-theme_branching.png" alt="sub-themes and dependancies" /></p><p><span
id="more-149"></span></p><p>想象一下从设计一个基本主题(base theme)作为模型开始， 然后添加一些子主题，在子主题上完善你的网页样式。再然后，依据这同一个模型，试试分支出一些其他样式的子主题。需要同时建立多个站点，但是需要有共性的外观感觉？ 有了子主题功能，一系列设计资源都可以共享. 特定站点外观可以组织到特定的子主题中，但是一旦需要改变某个共同特性，只需要编辑一次共有资源中的某项，即可应用到所有主题。只要规划得当，此功能可以给你带来无限可能。</p><p>要声明一个父主题，或成为“基本主题”，将下列语句添加到子主题的<a
href="http://drupal.org/node/171205">.info文件</a><code>中，“themeName”</code>替换为您的父主题的<strong>内部名字</strong>。</p><div
class="codeblock"><code>base theme = themeName<br
/> </code></div><p>下列资源会被继承:</p><ul
id="sub-theme-inherit"><li>父主题中定义的所有<a
href="http://drupal.org/node/171209">样式表</a>，但是这也是可以通过某些<a
href="http://drupal.org/node/171209#styles-override-parent">选项</a>来控制的。</li><li>父主题中定义的所有<a
href="http://drupal.org/node/171213">JavaScripts</a>。</li><li>所有的模板文件(.tpl.php)。</li><li>文件&#8221;template.php&#8221;中定义的所有内容。包括<a
href="http://drupal.org/node/173880#function-override">主题函数重写</a>, <a
href="http://drupal.org/node/223430">预处理器</a>和其他所有东西。所有子主题把它自己的template.php文件和父主题的该文件包含在一起。</li><li>父主题的截图，只要.info文件使用了和他的父主题一样的设置。</li></ul><p>下列资源不会被继承：</p><ul
id="sub-theme-not-inherit"><li>为父主题制定的logo.png文件。不包括用户上传的logo，因为他们总是会被使用。</li><li>.info文件定义的某些设置。 This includes regions. If you are not using the default regions, then make sure your &#8220;page.tpl.php&#8221; file for the sub-theme matches what is set for regions in the .info file. Each base and sub-theme can have their own region settings.</li><li>Anything set within the &#8220;theme-settings.php&#8221; file for the <a
href="http://drupal.org/node/177868">主题高级设置</a>.</li><li>Anything set within the &#8220;color&#8221; directory for <a
href="http://drupal.org/node/108459">color模块支持</a>.</li></ul><p><em
class="tips">Note that sub-themes can be placed outside of the base theme&#8217;s directory or within it. Before version 6, they had to be in the sub-directory of the parent theme.</em></p><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" rel="bookmark">[Drpal模板制作手册-5]重写可主题化的输出</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" rel="bookmark">[Drupal模板制作手册-1]主题定制概述</a></li><li><a
href="http://blog.benhuoer.com/posts/40-stand-alone-javascript-libraries-for-specific-purposes.html" rel="bookmark">40个实用的轻量级JavaScript库[SM]</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/css" rel="tag">CSS</a>, <a
href="http://blog.benhuoer.com/tag/drupal" rel="tag">drupal</a>, <a
href="http://blog.benhuoer.com/tag/javascript" rel="tag">JavaScript</a>, <a
href="http://blog.benhuoer.com/tag/%e4%b8%bb%e9%a2%98" rel="tag">主题</a>, <a
href="http://blog.benhuoer.com/tag/%e6%a8%a1%e6%9d%bf" rel="tag">模板</a>, <a
href="http://blog.benhuoer.com/tag/%e7%bb%a7%e6%89%bf" rel="tag">继承</a></div><p><small>©2008 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html#comments" target="_blank">板凳还在</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html&title=[Drupal模板制作手册-3]子主题，结构与继承&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>[Drupal模板制作手册-2]主题的解剖</title><link>http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html</link> <comments>http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html#comments</comments> <pubDate>Sun, 10 Aug 2008 08:53:00 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[CSS]]></category> <category><![CDATA[drupal]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[模板]]></category> <guid
isPermaLink="false">http://jackoko.cn/?p=141</guid> <description><![CDATA[phptemplate主题: .info (必需) 要Drupal看懂你的主题所需的所有东西就是这个 &#8221;.info&#8221; 文件. Meta数据, 样式表, JavaScripts, 块区域 以及更多的东西都是定义在这里。其他文件都是可选的。主题的内部名字也在这个文件中定义。 例如，如果此文件被命名为&#8221;drop.info&#8221;，那么Drupal就会认为这个主题的名字是&#8221;drop&#8221;。 Drupal 5 以及更低版本用文件夹的名字作为主题名。主题的信息文件是在Drupal 6中才出现。Drupal5中， 只有模块才会使用.info文件。 模板文件 (.tpl.php) 这些模板文件用以产生xHTML 标签和php变量。 有时也可用于输出其他类型的数据——例如xml rss 。每一个.tpl.php文件处理一类特定的可以主题化的数据输出，某些情况下，它也可以通过模板建议来处理多个.tpl.php文件。这些文件是可选的，如果你的主题不包括任何这类文件，内容就会以默认样式输出。请尽量避免在这些文件中添加过多处理逻辑。大多数情况下，应该只包括xHTML 标签和纯粹而直接的PHP变量。在Drupal核心与模块的文件夹里也有很多这样的文件。 把它们复制到你的主题文件夹里会强制Drupal使用你的版本。注意：所谓主题注册表缓存了可用的主题数据的信息。要在你的主题中添加或删除模板文件或者主题函数，你需要重设主题注册表。 template.php 所以的有条件的逻辑和内容输出的数据处理过程，都有一个template.php文件。 它并不是必须的, 但是为了保持.tpl.php文件的整洁，它可以作为 变量合并到.tpl.php文件的标记语言中之前 产生变量的预处理器 。自定义函数， 重写主题函数或者其他任何对原始输出的自定义都应该在这里完成。此文件必须以PHP的开始标记（&#60;?php）打头，但是结束标记并非必需，并且我们建议您不要添加它。 子主题(sub-theme) 表面上，子主题的表现和其他主题一样。唯一的区别就在于它能够继承“父主题”的资源。要创建子主题,需要在.info文件里添加一个&#8221;base theme&#8221;(基础主题)条目。子主题就是从那儿继承父主题的资源。可以使用多重继承。也就是说，一个子主题可以声明为另一个主题的基础主题(base theme)。对于多重继承没有硬性限制。Drupal 5及更低版本要求子主题必须在父主题的子文件夹里。现在已经没有这样的限制了。 其他 logo和截屏(screeshot)并非主题工作所必须，但我们建议你提供这两个文件，特别是当你想与他人分享这个主题时。Screenshots will show inside the theme administration page and the user account settings for selecting themes when the [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" rel="bookmark">[Drpal模板制作手册-5]重写可主题化的输出</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" rel="bookmark">[Drupal模板制作手册-1]主题定制概述</a></li><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p><strong>phptemplate主题:</strong></p><div
class="wp-caption aligncenter" style="width: 385px"><a
href="http://drupal.org/files/theme_anatomy_0.png" target="_blank"><img
src="http://drupal.org/files/theme_anatomy_0.png" alt="theming requirements" width="375" height="370" /></a><p
class="wp-caption-text">一个常规的Drupal主题的文件树</p></div><p><span
id="more-141"></span></p><dl><dt
id="info"><a
href="http://drupal.org/node/171205">.info</a> <em
class="marker">(必需)</em></dt><dd>要Drupal看懂你的主题所需的所有东西就是这个 &#8221;.info&#8221; 文件. Meta数据, <a
href="http://drupal.org/node/171209">样式表</a>, <a
href="http://drupal.org/node/171213">JavaScripts</a>, <a
href="http://drupal.org/node/171224">块区域</a> 以及更多的东西都是定义在这里。其他文件都是可选的。主题的内部名字也在这个文件中定义。 例如，如果此文件被命名为&#8221;drop.info&#8221;，那么Drupal就会认为这个主题的名字是&#8221;drop&#8221;。 <em
class="tips">Drupal 5 以及更低版本用文件夹的名字作为主题名。</em><em
class="tips">主题的信息文件是在Drupal 6中才出现。Drupal5中， 只有模块才会使用.info文件。</em></dd><dt
id="tpl"><a
href="http://drupal.org/node/190815">模板文件</a> <em
class="tips">(.tpl.php)</em></dt><dd>这些模板文件用以产生<em>x</em>HTML 标签和php变量。 有时也可用于输出其他类型的数据——例如<a
href="http://api.drupal.org/api/function/theme_aggregator_page_rss"><em>xml rss</em></a> 。每一个.tpl.php文件处理一类特定的可以主题化的数据输出，某些情况下，它也可以通过<a
href="http://drupal.org/node/223440">模板建议</a>来处理多个.tpl.php文件。这些文件是可选的，如果你的主题不包括任何这类文件，内容就会以默认样式输出。请尽量避免在这些文件中添加过多处理逻辑。大多数情况下，应该只包括<em>x</em>HTML 标签和纯粹而直接的PHP变量。在Drupal核心与模块的文件夹里也有很多这样的文件。 把它们复制到你的主题文件夹里会强制Drupal使用你的版本。<em
class="tips">注意：所谓<a
href="http://drupal.org/node/173880#theme-registry">主题注册表</a>缓存了可用的主题数据的信息。要在你的主题中添加或删除模板文件或者主题函数，你需要重设主题注册表。</em></dd><dt
id="template-php">template.php</dt><dd>所以的有条件的逻辑和内容输出的数据处理过程，都有一个template.php文件。 它并不是必须的, 但是为了保持.tpl.php文件的整洁，它可以作为 变量合并到.tpl.php文件的标记语言中之前 产生变量的<a
href="http://drupal.org/node/223430">预处理器</a> 。自定义函数， <a
href="http://drupal.org/node/173880#function-override">重写主题函数</a>或者其他任何对原始输出的自定义都应该在这里完成。此文件必须以PHP的开始标记（&lt;?php）打头，但是结束标记并非必需，并且我们建议您不要添加它。</dd><dt
id="sub-theme"><a
href="http://drupal.org/node/225125">子主题</a>(sub-theme)</dt><dd>表面上，子主题的表现和其他主题一样。唯一的区别就在于它能够继承“父主题”的资源。要创建子主题,需要在.info文件里添加一个&#8221;base theme&#8221;(基础主题)条目。子主题就是从那儿继承父主题的资源。可以使用多重继承。也就是说，一个子主题可以声明为另一个主题的基础主题(base theme)。对于多重继承没有硬性限制。<em
class="tips">Drupal 5及更低版本要求子主题必须在父主题的子文件夹里。现在已经没有这样的限制了。</em></dd><dt
id="other">其他</dt><ul><li>logo和截屏(screeshot)并非主题工作所必须，但我们建议你提供这两个文件，特别是当你想<a
href="http://drupal.org/node/14208">与他人分享这个主题</a>时。Screenshots will show inside the theme administration page and the user account settings for selecting themes when the appropriate permissions are set. <em
class="tips">See the <a
href="http://drupal.org/node/11637">screenshot guidelines</a> for more information.</em></li><li>要提供自定义的主题管理界面和设置，或者logo、搜索、站点宗旨(mission)之外的“<a
href="http://drupal.org/node/221905">特性</a>”设置，可以添加一个&#8221;theme-settings.php&#8221; 文件。 这是一个高级功能。 更改相关信息请参考<a
href="http://drupal.org/node/177868">Advanced settings</a>。</li><li>要启用<a
href="http://drupal.org/node/108459">色彩模块支持</a>，包含&#8221;color.inc&#8221;的名为&#8221;color“的文件夹以及相应的css文档和图像文件就是必须的。</li></ul></dl><ul
class="tips"><li><em>如果你打算以某个核心主题为基础开始工作，请使用<a
href="http://drupal.org/node/225125">子主题</a>功能或者复制后重命名为你自己的文件夹。强烈建议你不要</em><em
class="marker">直接修改默认主题Garland或者Minnelli，因为这两个主题在系统安装和升级时会用到。</em></li><li><em>所以主题都应该安装在&#8221;sites/all/themes&#8221; 文件夹，与核心文件分开。阅读关于<a
href="http://drupal.org/node/43816">多站点支持</a>的内容来了解在其他文件夹安装主题的情况。</em></li></ul><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" rel="bookmark">[Drpal模板制作手册-5]重写可主题化的输出</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" rel="bookmark">[Drupal模板制作手册-1]主题定制概述</a></li><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/css" rel="tag">CSS</a>, <a
href="http://blog.benhuoer.com/tag/drupal" rel="tag">drupal</a>, <a
href="http://blog.benhuoer.com/tag/javascript" rel="tag">JavaScript</a>, <a
href="http://blog.benhuoer.com/tag/%e6%a8%a1%e6%9d%bf" rel="tag">模板</a></div><p><small>©2008 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html#comments" target="_blank">板凳还在</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html&title=[Drupal模板制作手册-2]主题的解剖&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>[Drupal模板制作手册-1]主题定制概述</title><link>http://blog.benhuoer.com/posts/drupal_theming_overview.html</link> <comments>http://blog.benhuoer.com/posts/drupal_theming_overview.html#comments</comments> <pubDate>Sun, 10 Aug 2008 07:58:11 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[CSS]]></category> <category><![CDATA[drupal]]></category> <category><![CDATA[模板]]></category> <guid
isPermaLink="false">http://jackoko.cn/?p=133</guid> <description><![CDATA[通常编写软件都需要把表现层和程序层分离。 这样做有 很多原因 ， 最明显的就是编写后台业务逻辑程序所需知识和创建视觉外观、用户界面所需知识有很大不同。作为主题开发者，你可以控制某些可用数据的特定方面，但应该只限于数据输出和呈现样式。 只有Drupal核心和模块才能用以数据输入。 例如，一个模块可以产生带有默认外观的表格采集用户输入的数据，然后转存到数据库中。主题的作用应该仅仅是重写这些默认外观。 以上所述过程在Drupal中是通过 theme 函数来实现的。可以把它看作是数据到主题子系统的管道。它为主题引擎提供一个可选择的中间层，以便被例如 PHPTAL 或 Smarty 一类的标记语言利用， 它同时允许主题控制所有表现层标记。 主题引擎和标记语言同样是可选的。 PHPTemplate 即是默认的引擎。顾名思义，在输出变量和xHTML标签的混合体时它使用的是PHP语言。 自Drupal 6开始，创建主题引擎的要求实际上是降低了。 所有层次都能生成主题化的输出， 但是只有主题层可以重写（也有例外） 。 主题引擎可以重写来自核心与模块的输出，而主题可以重写其他一切东西。 请注意PHPTemplate引擎并不重写任何输出，但是有些其他引擎可以。 也有少数模块可以控制输出样式，并且几乎可以重写所有东西，但这种功能应当只用于少数特殊情况。 例如，主题模块devel 就有这样的功能，以帮助主题开发。 更多细节我们将在 下一节讨论 。 如果你想完全通过CSS来控制主题，那么你可以忽略下面的内容。但是如果有标签需要更改，知道如何访问数据输出的来源以自定义它 就变得十分重要。 请注意Drupal 核心以及数不清的模块总是用themable 函数和 模板文件来输出表现层的标签。请务必不要修改主题文件夹以外的文件，不然在系统需要升级时你会遇到麻烦。 我们把这种行为叫做&#8221;分流&#8221;. 开源软件的最大能量就在于有强大的社区后盾为你修复bug和开发新功能。 一旦你开始分流，你就失去了这个社区的支持。 Drupal已经提供重写表现层所需的所有功能。 除非你自己找到了Drupal的bug，否则修改主题文件夹以外的文件就是一件错事。这种情况下，请帮忙撰写bug报告。或者最好， 提供一个补丁修复这个问题。 对于那些在以前的版本中就熟悉过PHPTemplate引擎的人来说，几乎所有功能都已经变得更接近核心（即Drupal核心现在提供更多功能，从而不必使用PHPtemplate引擎）。 PHPTemplate现在的工作只包括探索与主题有关的theme函数和相应模板. 相对于“引擎”而言，现在它更多的是一个“主题帮手”。PHPTemplate was originally written by Adrian Rossouw for 4.7. The changes in 6 were the work of Earl Miles. [...]<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" rel="bookmark">[Drpal模板制作手册-5]重写可主题化的输出</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<p>通常编写软件都需要把表现层和程序层分离。 这样做有 <a
href="http://en.wikipedia.org/wiki/Separation_of_concerns">很多原因</a> ， 最明显的就是编写后台<a
href="http://zh.wikipedia.org/wiki/%E5%85%B3%E6%B3%A8%E7%82%B9%E5%88%86%E7%A6%BB">业务逻辑</a>程序所需知识和创建视觉外观、用户界面所需知识有很大不同。作为主题开发者，你可以控制某些可用数据的特定方面，但应该只限于数据输出和呈现样式。 只有Drupal核心和模块才能用以数据输入。 例如，一个模块可以产生带有默认外观的表格采集用户输入的数据，然后转存到数据库中。主题的作用应该仅仅是重写这些默认外观。</p><p><span
id="more-133"></span></p><p>以上所述过程在Drupal中是通过 <strong><a
href="http://api.drupal.org/api/function/theme">theme</a></strong> 函数来实现的。可以把它看作是数据到主题子系统的管道。它为主题引擎提供一个可选择的中间层，以便被例如 <a
href="http://drupal.org/project/phptal">PHPTAL</a> 或 <a
href="http://drupal.org/project/smarty">Smarty</a> 一类的标记语言利用， 它同时允许主题控制所有表现层标记。 主题引擎和标记语言同样是可选的。 PHPTemplate 即是默认的引擎。顾名思义，在输出变量和<em>x</em>HTML标签的混合体时它使用的是PHP语言。</p><p><em
class="tips">自Drupal 6开始，创建主题引擎的要求实际上是降低了。</em></p><p><a
href="http://blog.benhuoer.com/wp-content/uploads/2008/08/theme_tech_stack_0-e589afe69cac.jpg"><img
class="size-full wp-image-135 alignnone" title="theme_tech_stack_0" src="http://blog.benhuoer.com/wp-content/uploads/2008/08/theme_tech_stack_0-e589afe69cac.jpg" alt="" width="500" height="194" /></a></p><p>所有层次都能生成主题化的输出， 但是只有主题层可以重写（也有例外） 。 主题引擎可以重写来自核心与模块的输出，而主题可以重写其他一切东西。</p><p>请注意PHPTemplate引擎并不重写任何输出，但是有些其他引擎可以。 也有少数模块可以控制输出样式，并且几乎可以重写所有东西，但这种功能应当只用于少数特殊情况。 例如，主题模块<a
href="http://drupal.org/project/devel">devel</a> 就有这样的功能，以<a
href="http://drupal.org/node/209561">帮助主题开发</a>。 更多细节我们将在 <a
href="http://drupal.org/node/173880">下一节讨论</a> 。</p><p>如果你想<a
href="http://drupal.org/node/171209">完全通过CSS来控制主题</a>，那么你可以忽略下面的内容。但是如果有标签需要更改，知道如何<a
href="http://drupal.org/node/173880">访问数据输出的来源以自定义它</a> 就变得十分重要。</p><ul
class="tips"><li>请注意Drupal 核心以及数不清的模块总是用<a
href="http://api.drupal.org/api/group/themeable/6">themable 函数</a>和 <a
href="http://api.drupal.org/api/search/6/.tpl.php">模板文件</a>来输出表现层的标签。<span
style="color: #ff0000;">请务必不要修改主题文件夹以外的文件，</span>不然在系统需要升级时你会遇到麻烦。 我们把这种行为叫做&#8221;分流&#8221;. 开源软件的最大能量就在于有强大的社区后盾为你修复bug和开发新功能。 一旦你开始分流，你就失去了这个社区的支持。 Drupal已经提供重写表现层所需的所有功能。 除非你自己找到了Drupal的bug，否则修改主题文件夹以外的文件就是一件错事。这种情况下，请帮忙撰写<a
href="http://drupal.org/node/317">bug报告</a>。或者最好， <a
href="http://drupal.org/patch">提供一个补丁</a>修复这个问题。</li><li>对于那些在以前的版本中就熟悉过PHPTemplate引擎的人来说，几乎所有功能都已经变得更接近核心（即Drupal核心现在提供更多功能，从而不必使用PHPtemplate引擎）。 PHPTemplate现在的工作只包括探索与主题有关的theme函数和相应模板. 相对于“引擎”而言，现在它更多的是一个“主题帮手”。PHPTemplate was originally written by <a
href="http://drupal.org/user/1337">Adrian Rossouw</a> for 4.7. The changes in 6 were the work of <a
href="http://drupal.org/user/26979">Earl Miles</a>. <a
href="http://drupal.org/node/7133">An extended forum discussion</a> provides some of the reasoning behind the initial creation of the engine and the <a
href="http://drupal.org/node/130987">issue queue for the new direction</a> in 6.（PHPTemplate 的版本历史就不用翻译了吧？）</li></ul><p>原文：<a
href="http://drupal.org/node/171188">http://drupal.org/node/171188</a></p><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/sub-themes-their-structure-and-inheritance.html" rel="bookmark">[Drupal模板制作手册-3]子主题，结构与继承</a></li><li><a
href="http://blog.benhuoer.com/posts/anatomy-of-a-drupal-theme.html" rel="bookmark">[Drupal模板制作手册-2]主题的解剖</a></li><li><a
href="http://blog.benhuoer.com/posts/info-files-for-themes.html" rel="bookmark">[Drupal模板制作手册-4]主题的.info文件</a></li><li><a
href="http://blog.benhuoer.com/posts/drupal-overriding-themable-output.html" rel="bookmark">[Drpal模板制作手册-5]重写可主题化的输出</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/css" rel="tag">CSS</a>, <a
href="http://blog.benhuoer.com/tag/drupal" rel="tag">drupal</a>, <a
href="http://blog.benhuoer.com/tag/%e6%a8%a1%e6%9d%bf" rel="tag">模板</a></div><p><small>©2008 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/drupal_theming_overview.html#comments" target="_blank">板凳还在</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/drupal_theming_overview.html&title=[Drupal模板制作手册-1]主题定制概述&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/drupal_theming_overview.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>学习Web技术的基本原则</title><link>http://blog.benhuoer.com/posts/learning-priciple.html</link> <comments>http://blog.benhuoer.com/posts/learning-priciple.html#comments</comments> <pubDate>Thu, 13 Dec 2007 13:36:35 +0000</pubDate> <dc:creator>慵云</dc:creator> <category><![CDATA[前端开发]]></category> <category><![CDATA[XHTML]]></category> <category><![CDATA[入门]]></category> <category><![CDATA[教程]]></category> <guid
isPermaLink="false">http://sunnyjesse.yo2.cn/articles/588976.html</guid> <description><![CDATA[这是写给我们部门新成员的一个介绍性的基础的帖子。 首先，欢迎各位加入本群。 本群为校学生会网络工作部的官方QQ群，主要用于交流安排与学习交流。也同时欢迎校内其他网页制作的爱好者加入。 针对初学者，在此我愿意与大家分享一点我自己的经验。 学习电脑技术，不管是网页制作或者相应的一些专业软件，应该时刻注意一个原则： （简便起见，将网页制作、后台编程、网站美工统称为Web技术） 善用搜索引擎。 有问题？百度一下。”学习Web技术最好的老师就是网络。碰到问题的时候，先试试能不能自己解决，然后用搜索引擎找找有没有相关的问题。个人比较推荐Google，因为技术上的东西好像还是Google搜出来的结果更有用的。我是很少用百度，除非有一些自己搜搜不出来的问题我才会用用百度知道求助高手。（很少碰到这样的情况）。使用搜索软件的技巧无外乎关键字的选择，如果大家需要将来我可以专门写一个帖子来讲讲经验。 此外，总结一些初学时的方法和经验： 1. 网络永远比教材快。 学习Web技术，最好是看网上的教程或教材。对于日新月异的计算机技术，图书馆二楼的书几乎已经丧失借阅的价值了，能够在一楼借到相关内容的书就坚决不在二楼借。当然，也有一些很经典的书在基础知识的讲解上非常值得参考。或者有时候没有条件上网，借一本教材来翻着玩也是可以的。 2. 从最基础的东西入手。 很多同学，连最基本的概念和操作都没有学会，就想要开始做很高级的东西。这里也试验，那里也试验，可是真要做一个指定的效果的时候，却又不知道从何入手了。所以应该先系统的了解一下最基本的概念性的东西已经Web开发软件的基本操作。比如做一个网页需要用到哪些语言？这些语言都能做哪方面的事情？HTML最基本的语法是什么？每个标签各有哪些常用属性？不要到时候在Dreamweaver的可视化做出一个页面后你还不知道插入图片的代码是&#60;img&#62;&#60;/img&#62;&#60;img /&#62;。常用的快捷键有哪些？至少Ctr+C和Ctr+V你得会用吧？Photoshop工具栏上那一串东西都能做些什么？ 3. 经常参考帮助文档。 有时候可能你想要执行的操作在网上也搜不到，就是因为这个操作太简单啦，看一下帮助文档就能找到！而你一时间没有反应过来，就一直在那里迷茫着。学习的时候不是随时都有高手在身边为你答疑解惑的，这个时候按下F1，打开软件的帮助文档看一下，你会发现你的这些可爱的工具能实现的东西比你想象中还多。 具体的学习思路我会另写一篇帖子。 你应该也会喜欢： 即刻提升jQuery性能的十个技巧[TUTS+]给JavaScript新手的24条实用建议[TUTS+] 分类于：前端开发       标签: XHTML, 入门, 教程 ©2007 笨活儿 &#124; 永久链接 &#124; 板凳还在 &#124; 推荐到豆瓣<div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li></ol></div> ]]></description> <content:encoded><![CDATA[<h3><em>这是写给我们部门新成员的一个介绍性的基础的帖子。</em></h3><p>首先，欢迎各位加入本群。</p><p>本群为校学生会网络工作部的官方QQ群，主要用于交流安排与学习交流。也同时欢迎校内其他网页制作的爱好者加入。</p><p>针对初学者，在此我愿意与大家分享一点我自己的经验。</p><p>学习电脑技术，不管是网页制作或者相应的一些专业软件，应该时刻注意一个原则：</p><p>（简便起见，将网页制作、后台编程、网站美工统称为Web技术）</p><p><strong>善用搜索引擎。</strong> 有问题？百度一下。”学习Web技术最好的老师就是网络。碰到问题的时候，先试试能不能自己解决，然后用搜索引擎找找有没有相关的问题。个人比较推荐Google，因为技术上的东西好像还是Google搜出来的结果更有用的。我是很少用百度，除非有一些自己搜搜不出来的问题我才会用用百度知道求助高手。（很少碰到这样的情况）。使用搜索软件的技巧无外乎关键字的选择，如果大家需要将来我可以专门写一个帖子来讲讲经验。</p><p>此外，总结一些初学时的方法和经验：</p><h4>1. 网络永远比教材快。</h4><p>学习Web技术，最好是看网上的教程或教材。对于日新月异的计算机技术，图书馆二楼的书几乎已经丧失借阅的价值了，能够在一楼借到相关内容的书就坚决不在二楼借。当然，也有一些很经典的书在基础知识的讲解上非常值得参考。或者有时候没有条件上网，借一本教材来翻着玩也是可以的。</p><h4>2. 从最基础的东西入手。</h4><p>很多同学，连最基本的概念和操作都没有学会，就想要开始做很高级的东西。这里也试验，那里也试验，可是真要做一个指定的效果的时候，却又不知道从何入手了。所以应该先系统的了解一下最基本的概念性的东西已经Web开发软件的基本操作。比如做一个网页需要用到哪些语言？这些语言都能做哪方面的事情？HTML最基本的语法是什么？每个标签各有哪些常用属性？不要到时候在Dreamweaver的可视化做出一个页面后你还不知道插入图片的代码是<span
style="text-decoration: line-through;">&lt;img&gt;&lt;/img&gt;</span>&lt;img /&gt;。常用的快捷键有哪些？至少Ctr+C和Ctr+V你得会用吧？Photoshop工具栏上那一串东西都能做些什么？</p><h3>3. 经常参考帮助文档。</h3><p>有时候可能你想要执行的操作在网上也搜不到，就是因为这个操作太简单啦，看一下帮助文档就能找到！而你一时间没有反应过来，就一直在那里迷茫着。学习的时候不是随时都有高手在身边为你答疑解惑的，这个时候按下F1，打开软件的帮助文档看一下，你会发现你的这些可爱的工具能实现的东西比你想象中还多。</p><p>具体的学习思路我会另写一篇帖子。</p><div
class="related-post"> <strong>你应该也会喜欢：</strong><ol><li><a
href="http://blog.benhuoer.com/posts/10-tips-for-jquery-performance.html" rel="bookmark">即刻提升jQuery性能的十个技巧[TUTS+]</a></li><li><a
href="http://blog.benhuoer.com/posts/24-javascript-best-practices-for-beginners.html" rel="bookmark">给JavaScript新手的24条实用建议[TUTS+]</a></li></ol></div><div
style="border-top:dashed 1px #ccc;  border-bottom:dashed 1px #ccc;padding:0.3em 0;">分类于：<a
href="http://blog.benhuoer.com/category/web-technology/web-apps-development" title="查看 前端开发 中的全部文章" rel="category tag">前端开发</a>        标签: <a
href="http://blog.benhuoer.com/tag/xhtml" rel="tag">XHTML</a>, <a
href="http://blog.benhuoer.com/tag/%e5%85%a5%e9%97%a8" rel="tag">入门</a>, <a
href="http://blog.benhuoer.com/tag/%e6%95%99%e7%a8%8b" rel="tag">教程</a></div><p><small>©2007 <a
href="http://blog.benhuoer.com" target="_blank">笨活儿</a> | <a
href="http://blog.benhuoer.com/posts/learning-priciple.html" target="_blank">永久链接</a> | <a
href="http://blog.benhuoer.com/posts/learning-priciple.html#comments" target="_blank">板凳还在</a> | <a
href="http://9.douban.com/recommend/?url=http://blog.benhuoer.com/posts/learning-priciple.html&title=学习Web技术的基本原则&v=1&n=1" target="_blank">推荐到豆瓣</a> <br/> </small></p>]]></content:encoded> <wfw:commentRss>http://blog.benhuoer.com/posts/learning-priciple.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> </channel> </rss>
