对web应用效率提升的一些经验及疑问

1. 对dom节点的使用:

    尽量避免使用dom对象,大家都知道对dom树的遍历非常耗费资源,因此如果需要重复使用时,将dom对象存在一个js的变量中,然后对这个变量进行使用,避免每次使用dom节点时对dom树的遍历,切记,在使用完对dom对象引用的变量后要将其置为null,否则你会发现内存的占用率有增无减,直到你关闭了浏览器为止。

2. 对eval函数的使用:

     在使用eval函数时,会增加了对eval函数中代码解析的过程,而这个解析的过程是非常耗费资源的,因此,尽量避免使用eval函数,如果非用不可,也要尽可能的减少eval解析的代码量,将需要执行的代码提取到一个方法内,eval只解析这个函数名来提高eval的效率,可以通过以下的示例进行比较:

    方法一:

eval("for(var i = 0; i < 10000000; i ++) { var str = 'test' + i }");

      方法二:

var test = function() { 
    for(var i = 0; i < 10000000; i ++) {
        var str = 'test' + i; 
    } 
} 
var testFun = eval('test'); 
testFun(); 

3. try-catch的使用:

    尽量把try-catch语句放在循环外边。

4. 全局变量的使用:

     全局变量的生命周期贯穿整个脚本的生命周期,而本地变量的存在范围随着本地命名空间的销毁而消失。当在函数或其它地方引用一个全局变量时,脚本引擎需要搜索整个全局命名空间。

5. 压缩合并js和css文件:

     这方面的优化估计很多人都做过,现在有好多JS和CSS压缩和混淆的工具,如yahoo的yui-compressor.jar,在页面完全使用Ext等js框架开发时压缩和混淆JS对效率提升尤其明显。

6. 异步请求中GET与POST的选择:

     大家都知道用GET方式来发送HTTP请求效率要远远高于POST请求,但是出于安全的考虑,这里需要慎重选择请求方式,可以参考我的另外一篇文章。

 

——————————————————————————————– 

 

另外,还有一些开发过程中的细节也会对效率提升起到一定得作用:

1. 不要使用with语句

2. str += “aaa”; str += “bbb”; 效率大于 str = “aaa” + “bbb”;

3. 原生的态的写法效率大于函数,如:

    a > b   a : b; 效率大于 Math.max(a, b);

    array[array.length] = obj; 效率大于 array.push(obj);

4. 对数组进行遍历时,先把数组的长度保存在变量中

for(var i = 0, len = array.length; i < len; i ++) { 
    // 遍历数组 
}

5. innerHTML方法效率大于createElement()/appendChild()方法

6. 尽量减少图片链接个数,减少对带宽的耗费

 

——————————————————————————————–

 

目前还在对以下几方面的优化进行分析和研究,都是本机测试,基本可以忽略网络问题,希望高人可以进行指点:

1. ajax以POST方式发送异步请求时的性能优化

    现状:用HTTPWATCH检测时,SEND时间过长,有时竟然会超过0.8秒,传输量并不大,   

    请求信息:

    Content-Type : application/x-www-form-urlencoded;charset=UTF-8

    Content-Length : 133 (10个字符串参数)

2. 在接收response的content时的性能优化

    现状:用HTTPWATCH监测时,RECEIVE时间过长

    response信息:

    HTTP/1.1 200 OK

    Server : Apache-Coyote/1.1

    Content-Type : text/plain;charset=UTF-8

    Content-Length : 4147

3. 在多个请求之间会有延时,如第一个请求完成之后会有零点几秒的延时才会进行下一个请求,那么这个延时的时间可以进行优化吗?这个延时的时间到底是在做什么呢?执行javascript代码?还是请求的等待队列?

希望高人可以指点,先行谢过!

 

何为w3c

W3C:W3C释义 W3C是英文 World Wide Web Consortium 的缩写,中文意思是W3C理事会或万维网联盟。W3C于1994年10月在麻省理工学院计算机科学实验室成立。创建者是万维网的发明者Tim Berners-Lee。 W3C组织是对网络标准制定的一个非赢利组织,像HT…

W3C组织:W3C组织是对网络标准制定的一个非赢利组织,W3C是World Wide Web Consortium(万维网联盟)的缩写,像HTML、XHTML、CSS、XML的标准就是由W3C来定制。 W3C的官方网站网址为 http://www.W3C.org 根据W3C官方网站的介绍,W3C会员包括生产技…

org.W3C.dom:软件包 org.W3C.dom 的描述 为文档对象模型 (DOM) 提供接口,该模型是 Java API for XML Processing 的组件 API。该 Document Object Model Level 2 Core API 允许程序动态访问和更新文档的内容和结构。有关更多信息,请参阅 规范。 从…

org.W3C.dom.bootstrap:软件包 org.W3C.dom.bootstrap 类摘要 DOMImplementationRegistry 启用应用程序来获得 DOMImplementation 实例的工厂。…

org.W3C.dom.events:软件包 org.W3C.dom.events 接口摘要 DocumentEvent DocumentEvent 接口提供一种机制,通过该机制用户可以创建实现支持的 Event 类型。 Event Event 接口用于为处理事件的处理程序提供关于事件的上下文信息。 EventListener EventListen…

org.W3C.dom.ls:软件包 org.W3C.dom.ls 接口摘要 DOMImplementationLS DOMImplementationLS 包括创建 Load 和 Save 对象的工厂方法。 LSInput 此接口表示数据的输入源。 LSLoadEvent 此接口表示通知文档加载完成的加载事件对象。 LSOutput 此接口表示…

WEB标准:对应的标准也分三方面:结构化标准语言主要包括XHTML和XML,表现标准语言主要包括CSS,行为标准主要包括对象模型(如W3C DOM)、ECMAScript等。这些标准大部分由W3C起草和发布,也有一些是其他标准组织制订的标准,比如ECMA(European Computer Manu…

html:0——1995年11月作为RFC 1866发布,在RFC 2854于2000年6月发布之后被宣布已经过时 HTML 3.2——1996年1月14日,W3C推荐标准 HTML 4.0——1997年12月18日,W3C推荐标准 HTML 4.01(微小改进)——1999年12月24日,W3C推荐标准 ISO/IEC 1544…

xml:XML同时也推出一种新型文档类型,使得开发者也可以不必定义文档类型。 因为XML是W3C制定的,XML的标准化工作由W3C的XML工作组负责,该小组成员由来自各个地方和行业的专家组成,他们通过email交流对XML标准的意见,并提出自己的看法 (www.w3…

XHTML:所以,本质上说,XHTML是一个过渡技术,结合了部分XML的强大功能及大多数HTML的简单特性。 2000年底,国际W3C组织(World Wide Web Consortium)组织公布发行了XHTML 1.0版本。XHTML 1.0是一种在HTML 4.0基础上优化和改进的的新语言,目的

【前端与智能】前言

   最近越来越强烈地感觉到整个行业的发展正在走向智能化。虽然说很多方面离科幻片中的描述还是有很长的距离,但是奇迹往往也会出现在连科幻片都无法想象到一些角落。我目前在公司从事前端开发方面的工作,从这个角度来看,用户体验上的智能化开始逐渐地变得成为一个未来的方向。

     从最初的css随机换肤,到google chrome那样可以根据用户爱好初始化的开始页等,这里面创意一直在升级进化,或许这里的很多实现技术并不是前端在主导的,但是他可以让我们感受到我们的世界正在走向一个智能化的方向。我们不难想象未来的web是有“思想”的,他能够知道用户需要什么,喜欢什么,并且随着和用户交互的次数增加,系统自我修正和进化,逐渐和用户越来越近,乃至成为不可分割的一部分。在这个技术发展过程中前端作为一个与用户直接交互的层面,对于智能的处理,丰富信息的传感是必不可少的!如果前端开发一直停留在当前,那么很多东西都将是茶壶里面装饺子,倒不出来。没声音,再好的戏也出不来。这个瓶颈的存在会导致智能的时代推迟很多年出现,只到人们重新重视起来。

    未来的前端,不仅仅是web应用的前端,也不仅仅是PC平台上的前端,随着新技术的发展,随着新的输入输出设备的产生,前端会产生很多新的分支,前端将不会仅仅处理视觉上交互,他还会处理气味的输入,转后端存储和嗅觉的交互,情感信息的输入输出….

   再复杂的事情,都可以用信息来表达,再复杂的信息都可以用状态图的转换来求解。信息的处理只要涵盖到输入和输出就需要有前端,当然这是广义上的前端。前端一定要智能,也必须要智能。我们的匹诺曹最先需要的是从柴火堆里的木头先变刻一个人样来。然后需要能够丰富地表达自己,因为它已经自闭了半个多世纪。

  未来永远是我们无法想象到的,网络和应用系统目前已经成为我们之间相互交流的一个工具。假使这个工具足够智能,灵活,拓展了几千年来人类仅仅通过面对面有限表达和沟通的方式,这种过程足够接近我们的神经传输的话。那么整个网络连接起来的将是一个由无数个大脑+无数个虚拟的智能+超速运转的“中继器” 组成的有机体,这个有机体的复杂度将远远超过单个的人。这个有机体中存储的不仅仅只是文字,而是一种更高层面的智能。

  一切都有点遥远,却又不是梦想,是可以通过努力去实现的,希望此后更多的创意会被点起

jquerycore源码分析

jQuery是一个非常优秀的JS库,与Prototype,YUI,Mootools等众多的Js类库相比,它剑走偏锋,从web开发的实用角度出发,抛除了其它Lib中一些中看但不实用的东西,为开发者提供了优美短小而精悍的类库。其使用简单,文档丰富,而且性能高效,能极大地提高web系统的开发效率。因此可以说是web应用开发中最佳的Js辅助类库之一。大部分开发者正在抛弃Prototype,而选择Jquery做为他们进行web开发的JS库。

如是开发人员仅仅只知道文档中的简单的使用方法,却不明白Jquery的运行原理和内部机制,在使用jquery时,肯定会碰到许多的问题。这些问题有一部分是JqueryBug。大部分是自身的使用不当而造成的。而文档的简单的使用说明很难解决问题。在调试基于jQueryweb应用时,很多时候都要跟踪进入jQuery对象分析其运行状态以了解出错的原因。

如果对于web的应用的页面运行性能和效率有所要求的话,那么我们更应该去明白其运行机理和核心源码。但是jQuery源码不像其它的类库那样,它有点晦涩,难懂。这就是本源码分析的原因,让所有使用jQuery的读者,能快速上手jQuery的源码,并在开发中得心应用。

Jquery的网络资源丰富,但Baidu了很久,很难找到那种完全深入地分析Jquery源码的文稿。倒是Jquery的开发者,John Resi的《Pro Javascript Techniques》涉及到Jquery的源码的分析,但是其主指还是在于JavaScript的使用。那本书并不能使我们完全细致地了解Jquery的源码。

 

写个这个源码分析的理由其实很简单,在工作中使用jquery经常出问题,不得不分析其源码,我把分析的源码放在blog。其标题是jquery core 源码分析。结果有一网友竟评论说打到标题党,可见还是有很多人像我这样想完全了解jquerycore代码。

从自己能看懂,到自己写出来。发现自己有一个质的提高。但是由于水平有限,分析过程的难免有错误。请大家多多指教。不过嘴下能留情就最好了。有什么问题可以到blog:jljlpch.iteye.com去访问和评论。附件附有打包的源码。

分析源码,最难的地方不是你能理解,你能分析得出来。如果把所有的分析都写在源文件中,我想很多人看不了多少行就会中止的。很难有人有兴趣对得源码一行行地去分析。何把源码有机地组合起来,串成一条线是本教程的最为头疼的地方。
读书的最高境界是厚积薄发。分析源码也是一样。对于45千行的jquery源码,我们如何做到心中有数,知道什么功能在什么函数里内呢? 什么函数用在什么地方呢?这样就得把所有的函数有机分类地重组起来,想着Jquery的主要目的和自己对于js方面的理解。我把整个Jquery薄发成三个单词 query–>manipulate–>expand

jquery一个很紧缩的lib,它的主要目的就是对dom元素进行操作。那么dom元素的从哪里?
dom树中去找。这就是query$()Jquery的构建就是一个query的过程。我们可以把这个query范围放大一点,它不光是从dom中查找的CSS selector,还有可能是从html的片断中去寻找的dom元素生成,更进一步就是直接的dom元素(集)。$()的构建就是从这里出发的。

query
到元素集,这个query的过程还没有最终完成。因为这些结果集不一定满足我们的要求,那么就要筛选,要过滤。要进行数组方面的相关的操作。这就涉及到jquery对象的类数组的特征。我们就可以把这些类数组的相关的函数放在一起来分析。

当最终的需求的集合形成,我们要的完成我们真正要做的,对集合中的dom元素进行操作。
怎么操作?操作什么呢?不就是对dom元素的attribute,class, style,cssevent等进行操作吗?

细化一下:

1
、我们可以把attribute,class,style都看作是是属性的操作,还有expando的自定义的属性。这就涉及到jquery.data

2
、对dom元素的内容。什么是内容。innerHtml是。all childNodes也是,value也可以算。对于内容的操作就有追加,插入,前插,后插,内部前插和内部后插。那当然不能少了clone,remove这些操作。

3
CSS是可以在dom元素中单独出来分成一块来做分析的。对于css的操作,不就是height,width,innerHeight,innerWidth,out(height,widith)的操作,还有元素的位置(position,offset),display or not。这就是对于CSS的操作。

4
Event也是元素的操作中的一部分。这一部分除了addEvent,fireEvent,removeEvent,domready就没有别的啦。

5
Ajax是给元素从服务器中找内容填充的。真正用到最多不还是load吗,对于getScript,getJson之类全都是在jQuery.ajax的函数的基础而出来。

6
Fx可以看做是CSS的操作。但是其又高于CSS。对于FX,最基本不就show,hide,slide(down,up),fade(in,out)这几种用法。无论什么用法,都基于时间的长短映射到元素CSS的属性值的对对应比率的大小。采用setInterval间隔来运行就形成了动画。这就animate()函数。所有效果的发源地。

想想整个jquery就是这么简单。当然如果没有去身体力行去自己分析,无论什么教程都是没有用的。

其实query–>manipulate是表层的东西。还有一个高层的就是expand。这涉及到一个lib的架构与设计。

这部分我们可以从源码的角度去解读对于js lib的架构。
除了扩展性(extend)之后,一个lib肯定是要花大力气去考虑它的性能。

考虑它的内存使用。

这是站在设计Jquery的角度去分析。

想了很久,但是这一部分还没有写入目前的源码分析中。

2008-08-31 prk

 

纯CSS方式实现圆角框

纯CSS方式实现圆角框的原理在网络上已经有很多人详细解说了,下面这个示意图是我将其中的一个圆角进行放大后的效果



1、Html结构层:

<div class="sharp color1">
       <b class="b1"></b><b class="b2"></b><b class="b3"></b><b class="b4"></b> 
     <div class="content">文字内容</div>
       </div>
       <b class="b5"></b><b class="b6"></b><b class="b7"></b><b class="b8"></b>   
</div>

b1~b4构成上面的左右两个圆角结构体,而b5~b8则构建了下面左右两个圆角结构体。而content则是内容主体,将这些全部放在一个大的容器中,并给它的一个类名sharp,用来设置通用的样式。再给它叠加了一个color1类名,这个类名用来区别不同的颜色方案,因为可能会有不同颜色的圆角框。

2、CSS样式:

.b1,.b2,.b3,.b4,.b5,.b6,.b7,.b8{}{height:1px; font-size:1px; overflow:hidden; display:block;}
.b1,.b8{}{margin:0 5px;}
.b2,.b7{}{margin:0 3px;border-right:2px solid; border-left:2px solid;}
.b3,.b6{}{margin:0 2px;border-right:1px solid; border-left:1px solid;}
.b4,.b5{}{margin:0 1px;border-right:1px solid; border-left:1px solid; height:2px;} 

将每个b标签都设置为块状结构,并定义其高度为1像素,超出部分溢出隐藏。从上面样式中我们已经看到margin值的设置,是从大到小减少的。而b1和b8的设置是一样,已经将它们合并在一起了,同样的原理,b2和b7、b3和b6、b4和b5都是一样的设置。这是因为上面两个圆和下面的两个圆是一样,只是顺序是相对的,所以将它合并设置在一起。有利于减少CSS样式代码的字符大小。后面三句和第二句有点不同的地方是多设置了左右边框的样式,但是在这儿并没有设置边框的颜色,这是为什么呢,因为这个边框颜色是我们需要适时变化,所以将它们分离出来,在下面的代码中单独定义。

接下我们设置内容区的样式:

.content {border-right:1px solid;border-left:1px solid;overflow:hidden;}

也是只设置左右边框线,但是不设置颜色值,它和上面八个b标签一起构成圆角框的外边框轮廓。

往往在一个页面中存在多个圆角框,而每个圆角框有可能其边框颜色各不相同,有没有可能针对不同的设计制作不同的换肤方案呢,答案是有的。在我的这个应用中,可以换不同的皮肤颜色,并且设置颜色方案也并不是一件很难的事情。下面看看我是如何将它们应用到不同的颜色的。

在上面的样式设计中,我已经给颜色方案留下了可以扩展的空间。我将所有的涉及到边框色的类名全部集中在一起,用群选择符给它们设置一个边框的颜色就可以了。如下所示:

.color1 .b2,.color1 .b3,.color1 .b4,.color1 .b5,.color1 .b6,.color1 .b7,.color1 .content{}{border-color:#96C2F1;}
.color1 .b1,.color1 .b8{}{background:#96C2F1;}

注意:需要将这两句的颜色值设置为一样的,第二句中虽说是设置的background背景色,但它同样是上下边框线的颜色,这一点一定要记住。因为b1和b8并没有设置border,但它的高度值为1px,所以用它的背景色就达到了模拟上下边框的颜色了。

现在已经将一个圆角框描述出来了,但是有一个问题要注意,就是内容区的背景色,因为这儿是存载文字主体的地方。所以还需要加入下面这句话,也是群集选择符来设置圆角内的所有背景色。

.color1 .b2,.color1 .b3,.color1 .b4,.color1 .b5,.color1 .b6,.color1 .b7,.color1 .content{background:#EFF7FF;}

这儿除了b1和b8外,其它的标签都包含进来了,并且包括content容器,将它们的背景色全部设置一个颜色,这样除了线框外的所有地方都成为一种颜色了。在这儿我也用到包含选择符,给它们都加了一个color1,这是颜色方案1的类名,依照这个原理可以设置不同的换肤方案。

好了,我们将上面的所有代码集中起来,就完成一个纯CSS圆角框的实例模型,在源码中,我设置了六套颜色方案,其它的颜色方案就看你的了。

WEB应用性能调优记录

2009-7-10日

一个子系统做好后,进行性能测试,由于是在一个大系统中,所以很多组件使用了原系统中的。

测试环境:

数据库:Intel(R) Core(TM) 4CPU 2.4GHz 3.25GB Windows 2003  Oralce10g

中间件:Intel(R) Core(TM) 2CPU 2.4GHz 3.25 Windows 2003   Was 6.1.0.11

网络:公司内网

测试工具:loadrunner8

目标:200并发,3s

一开始测时,有好几个页面在60S,一查看原来是页面里包含了几个1.5M左右JS和CSS文件,其实很多

脚本文件在这些页面是不需要引用的,但是在开始的时候把全部的JS和CSS合并到了一个JSP页面里,

方便调用,没想到在这里引起了问题。

解决办法:1、清除不需要引用的JS脚本和CSS文件,

  2、把需要用到的文件在登陆页面提前引用,进入系统后浏览器会使用缓存,不会重新下载这些文件

由于系统没有复杂的逻辑,因些服务端程序没有发现太大的性能问题。

主要做了如下调整:

1、对查询SQL,打印出来,然后查看其执行计划,根据过滤条件加索引。

                2、在查询一个列表时,由于用到了多对一关联。后台查询时出现多条相同的查询SQL,(hiberante3.2)查了一下原因,虽然在hbm.xml配置文件中设置了fetch=”join”。但是在查询时写法如下:from TZfdaInfo info where info.NRybh =  ,没有强制去取回映射的对象,

改为这程形式就好了:

from TZfdaInfo info inner join fetch info.user where info.NRybh =  

关于extjs的内存使用测试

今天简单的测试了一下extjs的内存使用情况,如下:

打开IE7,嵌入html代码:22M

           加入ext-all.css:25.3M

          加入ext-base.js:28M

              加入ext-all.js:33.4M

           基本上单单引入整个ext框架需要11M-12M的内存

    

写一个应用:

Ext.onReady(function(){

   var win;

           win = new Ext.Window({

               el:’hello-win’,

               width:500,

               height:300,

               closeAction:’hide’

           });

       win.show();

});

弹出一个window 内存升到44M-46M

但是我发现单单打开extjs自带的desktop例子,用的内存也大约是44-46M之间,但是在desktop中打开一个window需要用大约10多M的内存,升到55M多。

哪位高人能详解一下extjs是怎么样使用内存的?

用Smarty分离PHP应用程序中的形式与功能

使用智能模板引擎分离 Web 页面标记与底层设计逻辑

文档选项

将此页作为电子邮件发送

将此页作为电子邮件发送

未显示需要 JavaScript 的文档选项

样例代码

<!–START RESERVED FOR FUTURE USE INCLUDE FILES–><!– this content will be automatically generated across all content areas –>
<!–END RESERVED FOR FUTURE USE INCLUDE FILES–>

级别: 中级

Martin Streicher (martin.streicher@linux-mag.com), 主编, Linux Magazine

2007 年 9 月 06 日

随意混用 PHP 与其他 Web 页面标记将导致程序逻辑、HTML、层叠样式表(Cascading Style Sheets,CSS)和 JavaScript 处于混乱状态,使维护成为一项艰巨的任务。Smarty 模板引擎可以将形式与功能分离。

<!–START RESERVED FOR FUTURE USE INCLUDE FILES–><!– include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters –><!–END RESERVED FOR FUTURE USE INCLUDE FILES–>

PHP Web 应用程序易于上手。PHP 语言的语法整洁且易于掌握。可以将 PHP 与 HTML、JavaScript 和 CSS 直接混用以快速生成可视结果。而且,把 PHP 应用程序部署到您自己的 Web 服务器或托管服务中只是小菜一碟。

但是混用 PHP 与其他页面标记也是一项责任。PHP 代码通常是含有程序逻辑、结构化查询语言(Structured Query Language,SQL)查询、函数、类、开发人员注释、HTML、CSS 样式和脚本的复杂 web(不是开玩笑)。更糟糕的是,把内容从 PHP、echo 发送到输出缓冲区有很多种方法。维护这样混乱的页面十分费力。对代码或标记做出无关紧要的更改会带来严重破坏,并且增强页面可能需要设计人员与程序员的共同努力。使用 PHP,形式(页面的布局)及功能(页面的目的和构造)将被混在一起。

在理想情况下,形式与功能是相互独立的。例如,CSS 和 HTML 一定应该如此。CSS 是形式,而 HTML 是功能。在使用 PHP 的情况下,如果页面标记和代码能够分离将是十分理想的。代码将处理输入,制定决策并生成显示数据,而标记将期待获得数据并提供所需的支架以渲染信息。

例如,主页的标记可能留下一个 “填空” (fill in the blank) 以供用户登录,以及其他占位符以供保存用户的图像和重要信息。此模板 —— 这样命名是因为它将提供页面显示的模式 —— 只面向设计人员,设计人员将控制页面的整体外观并留下名称、图片和其他数据的占位符。代码只是为占位符提供数据。开发人员的任务仍然主要集中在计算上。

当然,形式与功能必须协作。如果模板期望获得以美元为单位的金额,则代码不应当提供 URL。如果模板期望获得对象,则代码不应当提供列表。因此,模板系统必须将表单与函数分离,但还必须在两者之间建立联系。

最流行的 Web 应用程序编程语言(Perl、Python、Ruby、Java )都有模板引擎,而 PHP 也不例外。在搜索引擎中键入 PHP template engine,然后您可能会找到 25 个以上的选项(有关强调所研究的每个引擎功能的列表 The PHP Template Engine Roundup,请参阅 参考资料)。

一些 PHP 模板引擎进行了速度优化。其他 PHP 模板引擎旨在鼓励分离表单与函数的同时简化使用。在某些包中,占位符是在 PHP 本身中描述的,而其他解决方案都有一种自定义的简短编程语言。如何选择模板引擎在很大程度上取决于要求,因此适宜进行少量研究和试验。

在这里,我向您介绍 Smarty,它是最流行的 PHP 模板引擎之一。Smarty “代码” 有它自己的语法和运算符扩展列表,但是系统并不难学。阅读或浏览 Smarty 文档,以便熟悉它的所有功能。从 Smarty 的小修改开始,根据需求扩展您的技能,然后越来越精通。

获得 Smarty

Smarty Web 站点维护着一张活动邮件列表、一个支持论坛和一个 Internet Relay Chat (IRC) 论坛(请参阅 参考资料)。开发正在进行,而本文基于 V2.6.18 版本,该版本发布于 2007 年 3 月 7 日。

Smarty 有两个方面:PHP 应用程序编程接口 (API) 和显示引擎。应用程序代码将调用 API 把代码变量与模板占位符关联起来,而显示引擎将解释 Smarty 标记、执行循环、引用占位符和显示最终结果。Smarty 功能包括:

用于显示 PHP 的所有基本数据结构的运算符
显示简单变量,迭代整个数组或关联数组,以及显示类的成员。
占位符的默认值
如果 PHP 代码没有将变量与占位符关联,则显示默认值。
控制运算符,例如 ifthenelse,可以根据输入数据选择动态显示哪些内容
例如,设计人员可以选择用加粗的红色文本显示负账户余额,而用黑色文本显示正余额。您可以在模板中隔离此类显示逻辑(使您可以更轻松地进行开发)。
循环控制,它将提供用于简化构建列表和表的特殊变量
例如,可以测试循环的第一次迭代并创建表头。还可以像循环迭代一样循环执行值轮循 (round-robin) 列表,循环迭代非常适于改变表行的颜色。
渲染时用于改变数据的修饰符
例如,可以用 Smarty 标记 <strong>{$name|upper}</strong> 大写加粗显示占位符 —— 如 $name

<strong> 是普通 HTML。大括号 ({}) 用于划定 Smarty 标记,$name 是占位符,而 |upper 是修饰符。还可以编写自己的修饰符以扩展 Smarty 的功能。

如果必须 包括脚本和原始 PHP 代码,可以用 literalphp 运算符来完成
literal 运算符内的所有内容都将被逐字传递给最终页面。php 运算符中放置的代码将像嵌入到 < php ...  > 转义符内一样执行。

还可以通过 {include ...} 运算符重用 Smarty 模板。要提高性能,则需缓存每个模板,以避免每次使用的转换负载。Smarty Web 站点提供了丰富文档和示例。Packt Publishing 还提供一本名为 Smarty: PHP Template Programming and Applications(请参阅 参考资料)的书,该书适于学习和参考(警告:一些最新运算符并未介绍,而且其他运算符的说明也不正确,因为该书介绍的是 Smarty V2.x 的早期版本)。


回页首

用 Smarty 进行开发

无法通过一篇文章列举和演示 Smarty 的所有功能。但是,即使是一个如下所示的小示例,也能证明模板的力量。

把 Smarty 添加到应用程序中十分轻松:

  1. 下载 Smarty.zip 演示代码(请参阅 下载)。
  2. 解压缩并把 Smarty 安装到路径中。
  3. 编写要求使用 Smarty 类的应用程序。
  4. 创建两个目录一起放置应用程序:
    • templates 将包含模板
    • templates_c 将包含缓存的模板

例如,示例应用程序的文件夹内容包含 Example.class.php index.php templates/ templates_c/

模板目录中的文件将由 Smarty 引擎读取。确保 Web 服务器对那些文件拥有适当的访问权。另外,templates_c 的内容必须可读可写,因为缓存的模板副本放置在该文件夹中。至少要使 Web 服务器可以将数据写入 templates_c。或者,如果不需要考虑安全问题,可以将目录更改为模式 777

清单 1 显示了 Example.class.php,这是一个有代表性的 PHP V5 类。清单 2 包含 index.php,即应用程序。图 1 中显示了用浏览器访问示例应用程序的结果。

清单 1. 简单 PHP V5 类,用于存储任意类型的已命名属性的随机列表

                
< php

//
// Example is a simple class that stores an arbitrary 
// number of named properties. 
//

class Example {
    private $catalog = array();
    
    public function SetProperties( $arrayVariables ) {
        foreach ( $arrayVariables as $name => $value ) {
            $this->SetProperty( $name, $value );
        }
    }
    
    public function SetProperty( $name, $value ) {
        $this->$name = $value;
        $this->catalog[] = $name;
    }
    
    public function GetProperties( ) {
        $result = array();
        foreach ( $catalog as $name ) {
            $result[$name] = $this->GetProperty( $name );
        }
        
        return( $result );
    }
    
    public function GetProperty( $name ) {
        return ( $this->$name );
    }
}
 >

Example 是一个简单类,用于持久保存任意数目的已命名属性。该类最令人感兴趣的部分是第 18 行 $this->$name = $value;。这行代码将动态创建类实例成员。例如,如果调用 $example->SetProperty( 'name', 'Groucho' ),则可以用(传统的)$example->name 检索名称。

清单 2. PHP 应用程序,完全没有任何 Web 页面标记

                
< php
require( 'Smarty.class.php' );
require( 'Example.class.php' );

$groucho = new Example();
$groucho->SetProperty( 'name', 'Groucho' );
$groucho->SetProperty( 'quote', 
    'Time flies like an arrow. Fruit flies like a banana.' 
);

$chico = new Example();
$chico->SetProperties( array(
        'name' => 'Chico',
        'quote' => "There's no such thing as a sanity clause!"
    )
);

$movies = new Example();
$movies->SetProperties( array(
    'movies' => array(
        'A Night at the Opera',
        'Horse Feathers',
        'Coconuts',
        'The Big Store'
    ))
);

$looks = new Example();
$looks->SetProperty( 'novelty', array(
        array( name =>'Groucho', 'signature' => 'moustache' ),
        array( name =>'Chico', 'signature' => 'hat' ),
        array( name => 'Harpo', 'signature' => 'raincoat' ),
        array( name => 'Zeppo', 'signature' => 'hair')
    )
);

$smarty = new Smarty();
$smarty->assign( 'person', $chico );
$smarty->assign( 'people', $looks->novelty );
$smarty->assign( 'quote', $groucho->quote );
$smarty->assign( 'movies', $movies->movies );
$smarty->display( 'template.tpl' );
 >

清单 2 反映了把 PHP 变量与 Smarty 占位符关联起来的一般策略。代码行 $smarty->assign( 'name', $x ) 将把 PHP 变量(或数组、对象)$x 与占位符名称关联起来。模板中显示 name 的所有位置都将显示 $x 的值。

图 1. 渲染最终页面,结合表单与函数
渲染最终页面,结合表单与函数

Smarty 模板是什么样的?Smarty 代码都是轻量级的,如清单 3、清单 4 和清单 5 所示。Smarty 将把大括号 ({}) 中的所有内容都视为 Smarty 代码。因此,如果任何其他页面标记(例如嵌入式 CSS 或 JavaScript)使用大括号,则必须用 {literal}...{/literal} 把那个标记括起来,如清单 3 中所示:

清单 3. 主模板中包括的简单 header 模板

                
<html>
<head>
	<title>{$title|default:'The Marx Brothers'}</title>
	<style type="text/css">
	{literal}
	body {
	    font-family: Verdana, Arial, sans-serif;
	    margin: 5%;
	}
	{/literal}
	</style>
</head>
<body>

如前所述,清单 3 将应用 {literal} 运算符来逐字渲染标记:定界符之间的所有文本都将被传递而无需进一步解释。第 3 行将显示名为 <title> 的占位符的值,该占位符与 PHP 应用程序中的标量变量相关联。如果不与 <title> 关联,则 |default: 修饰符将提供默认值。注意 Smarty 运算符中的空白。通常,必须忽略它。幸运的是,Smarty 编译器将提供有帮助的错误消息。

清单 4 页脚显示了使用 {if condition} 在渲染时做出决定。在这里,如果占位符 quote 的值已设定,则将显示 {if}{/if} 之间插入的标记。代码行 {$quote|upper} 将用全大写的形式发送 quote 的值。|upper 是改变字符串输出的众多修饰符之一 —— 同时,它对于分离字符串内容与显示形式十分有用。

清单 4. 页脚模板

                
<div style="clear: both;">
    <p align="center">
        {if $quote}
            <{$style|default:'strong'}>
                {$quote|upper}        
            </{$style|default:'strong'}>
        {/if}
    </p>
</div>
</body>
</html>

清单 5 渲染了最终页面。

清单 5. 应用程序的主要 Smarty 模板

                
{include file='header.tpl'}

<p>
    {$person->name} said, "{$person->quote}"
</p>

<ul>
    {section name=index loop=$movies}
    <li>
        {$movies[index]}
    </li>
    {/section}
</ul> 

<table>
{foreach item=person from=$people name=people}
    {if $smarty.foreach.people.first}
        <tr>
            <th>#</th>
            <th>Name</th>
            <th>Signature</th>
        </tr>
    {/if}
    <tr bgcolor="{cycle values="#eeeeee,#d0d0d0}">
        <td>{$smarty.foreach.people.iteration}</td>
        <td>{$person.name}</td>
        <td>{$person.signature}</td>
    </tr>
{foreachelse}
    <tr><td>Print this only if there's no data.</td></tr>
{/foreach}
</table>

{include file='footer.tpl'}

应用程序的这个主要 Smarty 模板采用了若干个 Smarty 运算符:

{include file=’filename‘}
像是 PHP 自己的 include() 方法一样运行,在适当的位置立即插入和解释 filename 的内容。虽然并未显示,但是可以将变量从一个模板传递给另一个模板,这样做鼓励重用。
{$person->GetProperty(‘name’)}
假定 person 与名为 GetProperty() 的方法相关。您可以调用对象的方法和引用对象成员,像 {$person->quote} 所做的那样。
{section name=index loop=$placeholder}
在数组内迭代。loop 属性将给占位符命名,而 name 属性将指定一个名称以供数组索引使用。在循环内,将把数组元素作为 {$placeholder[index]} 来引用。
foreach
section 一样迭代,但是提供了一个非常优秀的功能来处理一组关联数组,例如数据库查询的行列表。每个关联数组都被 “转换” 到名为 item 的索引中。例如,在清单 5 中,person 被命名为 item。每执行一次循环,person 就会被指定来自数组 people 的关联数组。在那之后,在整个循环过程中,可以通过关键字引用关联数组中的值,如 {$person.signature}
foreach 中的 name 属性
类似于 HTML 标记的 id 属性,它将惟一地识别循环。使用此 ID 来引用反映循环状态的特殊变量集。例如,一个特殊变量是 first,它只在循环的第一次迭代时才被设定。因此,值 $smarty.foreach.people.first 将引用与名为 people (people) 的 foreach 循环 (foreach) 关联的特殊 Smarty 变量 (smarty)。正如您可能会想到的那样,还有 last 值和 iteration 值,它们从 1 开始,并随每次迭代增加(如果需要从零开始的计数器,请使用 index 而不要使用 iteration)。
cycle
用于构建表的优秀运算符。如果提供 values 列表,Smarty 将像循环迭代一样在所有值中循环。将循环添加到 bgcolor 中将改变每个表行的颜色可以使表更清晰。
{foreachelse}
如果要迭代的数组为空,则转而显示 {foreachelse}...{/foreachelse} 的内容。

既然您已经预览了模板,那么 清单 2 读起来可能很简单。跟平常一样,清单 2 将执行计算并把渲染页面的工作传递给 Smarty。代码行 $smarty->display('template.tpl') 将渲染模板。要捕捉 Smarty 的输出,请使用 $smarty->fetch('template.tpl')


回页首

使用 Smarty 更聪明一点,而不是更辛苦一点

虽然本例是经过设计的,但是它展示了 Smarty 的强大之处和灵活性以及使用它分离标记与代码是多么简单。Smarty 还有更多技巧。Smarty 可能实现您所需要的几乎所有功能。您可以将模板输出捕捉到 Smarty 占位符中。您可以过滤模板,无论是在编译前,还是在编译后,还可以在渲染输出被显示或获取之前先进行处理。而且 Smarty 允许您缓存模板。

向 PHP 代码中添加 $smarty->caching = 1; 即可获得上述特性。如果缓存被启用,则调用 display('template.tpl') 将像往常一样渲染模板并将在缓存中保存一份模板副本。下一次调用 display('template.tpl') 将利用缓存的副本,而不再渲染模板。

分享这篇文章……

digg 将这篇文章提交到 Digg
del.icio.us 发布到 del.icio.us
Slashdot 提交到 Slashdot!

您可以控制缓存的有效期、手动清空缓存,并且如果在保存缓存版本后模板文件发生更改,可以使缓存可以自动刷新。如果希望阅读类似 清单 2 的代码,请把 Smarty 应用到 Web 项目中。


回页首

下载

描述名字大小下载方法
Smarty 示例

os-php-smarty.zip 3KB HTTP
关于下载方法的信息

参考资料

学习

获得产品和技术

  • 下载 Smarty 模板引擎。
  • 使用 IBM 试用软件 改进您的下一个开发项目,这些软件可以通过下载或从 DVD 中获得。
  • 下载 IBM 产品评估版,并开始使用 DB2 、Lotus 、Rational 、Tivoli  和 WebSphere  的应用程序开发工具和中间件产品。

讨论

关于作者

martin streicher,linux 杂志主编

Martin Streicher 是 Linux Magazine 的主编兼 Hesketh.com(Raleigh, N.C. 中的用户体验代理机构)的 Web 开发人员,以及 developerWorks 的定期投稿者。他毕业于普渡大学

HTML结构化:DIV+CSS网页布局入门指南

         你正在学习CSS布局吗?是不是还不能完全掌握纯CSS布局?通常有两种情况阻碍你的学习:

第一种可能是你还没有理解CSS处理页面的原理。在你考虑你的页面整体表现效果前,你应当先考虑内容的语义和结构,然后再针对语义、结构添加CSS。这篇文章将告诉你应该怎样把HTML结构化。

另一种原因是你对那些非常熟悉的表现层属性(例如:cellpadding,、hspace、align=”left”等等)束手无策,不知道该转换成对 应的什么CSS语句。

 
 

当你解决了第一种问题,知道了如何结构化你的HTML,我再给出一个列表,详细列出原来的表现属性用什么CSS来代替。

结构化HTML

我们在刚学习网页制作时,总是先考虑怎么设计,考虑那些图片、字体、颜色、以及布局方案。然后我们用Photoshop或者Fireworks画出来、切割成小图。最后再通过编辑HTML将所有设计还原表现在页面上。

如果你希望你的HTML页面用CSS布局(是CSS-friendly的),你需要回头重来,先不考虑“外观”,要先思考你的页面内容的语义和结构。

外观并不是最重要的。一个结构良好的HTML页面可以以任何外观表现出来,CSS Zen Garden是一个典型的例子。CSS Zen Garden帮助我们最终认识到CSS的强大力量。

HTML不仅仅只在电脑屏幕上阅读。你用photoshop精心设计的画面可能不能显示在PDA、移动电话和屏幕阅读机上。但是一个结构良好的HTML页面可以通过CSS的不同定义,显示在任何地方,任何网络设备上。

开始思考

首先要学习什么是”结构”,一些作家也称之为”语义”。这个术语的意思是你需要分析你的内容块,以及每块内容服务的目的,然后再根据这些内容目的建立起相应的HTML结构。

如果你坐下来仔细分析和规划你的页面结构,你可能得到类似这样的几块:

标志和站点名称
主页面内容
站点导航(主菜单)
子菜单
搜索框
功能区(例如购物车、收银台)
页脚(版权和有关法律声明)

我们通常采用DIV元素来将这些结构定义出来,类似这样:

div id=”header”></div

div id=”content”></div

div id=”globalnav”></div

div id=”subnav”></div

div id=”search”></div

div id=”shop”></div

div id=”footer”></div

这不是布局,是结构。这是一个对内容块的语义说明。当你理解了你的结构,就可以加对应的ID在DIV上。DIV容器中可以包含任何内容块,也可以嵌套另一个DIV。内容块可以包含任意的HTML元素—标题、段落、图片、表格、列表等等。

根据上面讲述的,你已经知道如何结构化HTML,现在你可以进行布局和样式定义了。每一个内容块都可以放在页面上任何地方,再指定这个块的颜色、字体、边框、背景以及对齐属性等等。

使用选择器是件美妙的事
id的名称是控制某一内容块的手段,通过给这个内容块套上DIV并加上唯一的id,你就可以用CSS选择器来精确定义每一个页面元素的外观表现,包括标 题、列表、图片、链接或者段落等等。例如你为#header写一个CSS规则,就可以完全不同于#content里的图片规则。

另外一个例子是:你可以通过不同规则来定义不同内容块里的链接样式。类似这样:#globalnav a:link或者 #subnav a:link或者#content a:link。你也可以定义不同内容块中相同元素的样式不一样。例如,通过#content p和#footer p分别定义#content和#footer中p的样式。从结构上讲,你的页面是由图片、链接、列表、段落等组成的,这些元素本身并不会对显示在什么网络 设备中(PDA还是手机或者网络电视)有影响,它们可以被定义为任何的表现外观。

一个仔细结构化的HTML页面非常简单,每一个元素都被用于结构目的。当你想缩进一个段落,不需要使用blockquote标签,只要使用p标签,并对p 加一个CSS的margin规则就可以实现缩进目的。p是结构化标签,margin是表现属性,前者属于HTML,后者属于CSS。(这就是结构于表现的 相分离.)

良好结构的HTML页面内几乎没有表现属性的标签。代码非常干净简洁。例如,原先的代码<table width=”80%” cellpadding=”3″ border=”2″ align=”left”>,现在可以只在HTML中写<table>,所有控制表现的东西都写到CSS中去,在结构化的HTML中, table就是表格,而不是其他什么(比如被用来布局和定位)。

亲自实践一下结构化

上面说的只是最基本的结构,实际应用中,你可以根据需要来调整内容块。常常会出现DIV嵌套的情况,你会看到”container”层中又有其它层,结构类似这样:

div id=”navcontainer”>

div id=”globalnav”>

<ul>a list</ul>

</div

div id=”subnav”>

<ul>another list</ul>

</div

</div

嵌套的div元素允许你定义更多的CSS规则来控制表现,例如:你可以给#navcontainer一个规则让列表居右,再给#globalnav一个规则让列表居左,而给#subnav的list另一个完全不同的表现。

 
 

用CSS替换传统方法
下面的列表将帮助你用CSS替换传统方法:

HTML属性以及相对应的CSS方法
HTML属性

CSS方法说明
align=”left”

align=”right” float: left;

float: right; 使用CSS可以浮动 任何元素:图片、段落、div、标题、表格、列表等等

当你使用float属性,必须给这个浮动元素定义一个宽度。

marginwidth=”0″ leftmargin=”0″ marginheight=”0″ topmargin=”0″ margin: 0; 使用CSS, margin可以设置在任何元素上, 不仅仅是body元素.更重要的,你可以分别指定元素的top, right, bottom和left的margin值。

vlink=”#333399″ alink=”#000000″ link=”#3333FF” a:link #3ff;

a:visited: #339;

a:hover: #999;

a:active: #00f;
HTML中,链接的颜色作为body的一个属性值定义。整个页面的链接风格都一样。使用CSS的选择器,页面不同部分的链接样式可以不一样。

bgcolor=”#FFFFFF” background-color: #fff; 在CSS中,任何元素都可以定义背景颜色,不仅仅局限于body和table元素。

bordercolor=”#FFFFFF” border-color: #fff; 任何元素都可以设置边框(boeder),你可以分别定义top, right, bottom和left

border=”3″ cellspacing=”3″ border-width: 3px; 用CSS,你可以定义table的边框为统一样式,也可以分别定义top, right, bottom and left边框的颜色、尺寸和样式。

你可以使用 table, td or th 这些选择器.

如果你需要设置无边框效果,可以使用CSS定义: border-collapse: collapse;

<br clear=”left”>

<br clear=”right”>

<br clear=”all”>

clear: left;

clear: right;

clear: both;
许多2列或者3列布局都使用 float属性来定位。如果你在浮动层中定义了背景颜色或者背景图片,你可以使用clear属性.

cellpadding=”3″

vspace=”3″

hspace=”3″ padding: 3px; 用CSS,任何元素都可以设定padding属性,同样,padding可以分别设置top, right, bottom and left。padding是透明的。

align=”center” text-align: center;

margin-right: auto; margin-left: auto;
Text-align 只适用于文本.

div,p这样的块级可以通过margin-right: auto; 和margin-left: auto;来水平居中

一些令人遗憾的技巧和工作环境

由于浏览器对CSS支持的不完善,我们有时候不得不采取一些技巧(hacks)或建立一种环境(Workarounds)来让CSS实现传统方法同样的效 果。例如块级元素有时侯需要使用水平居中的技巧,盒模型bug的技巧等等。所有这些技巧都在Molly Holzschlag的文章《Integrated Web Design: Strategies for Long-Term CSS Hack Management》中有详细说明。

另外一个关于CSS技巧的资源站点是Big John和Holly Bergevin的“Position is Everything”。

理解浮动行为

Eric Meyer的《Containing Floats》将帮助你掌握如何使用float属性布局。float元素有时候需要清除(clear),阅读《How To Clear Floats Without Structural Markup》将非常有帮助。

更多帮助

已有的《CSS Discussion》列表是很好的资源,它收集了一个WiKiA讨论组的信息,其中包括CSS布局总结(css- discuss.incutio.com/ page=CssLayouts),CSS 技巧总结 (css-discuss.incutio.com/ page=CssHack) 以及更多。