<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_BearRui(AK-47)</title><subtitle type="text">   花开有时，错过了一日便错过了一季，就象人生错过了相遇，就不再找寻到美丽的相聚</subtitle><id>http://feed.cnblogs.com/blog/u/17803/rss</id><updated>2010-10-19T01:37:46Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/17803/rss"/><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/08/24/URL_SESSION_ID_LEEK.html</id><title type="text">URL中允许携带sessionid带来的安全隐患。</title><summary type="text">很多WEB开发语言为了防止浏览器禁止了cookie而无法识别用户，允许在URL中携带sessionid，这样虽然方便，但却有可能引起钓鱼的安全漏洞。</summary><published>2010-08-24T00:44:00Z</published><updated>2010-08-24T00:44:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/08/24/URL_SESSION_ID_LEEK.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/08/24/URL_SESSION_ID_LEEK.html"/><content type="html">&lt;p&gt;很多WEB开发语言为了防止浏览器禁止了cookie而无法识别用户，允许在URL中携带sessionid，这样虽然方便，但却有可能引起钓鱼的安全漏洞。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;图示：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;下图是从测试组发来的安全报告中剪出来的，图有些小问题，本来想重画1个，在visio中没找到合适的图。所以只能用别人的图了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;img height="345" width="554" src="http://pic002.cnblogs.com/img/bearstar/201008/2010082317154179.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;说明：&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;让我们对上图的步骤进行详细说明：&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;1. 黑客用自己的帐号登录,假设登录页面是:http://www.abc.com/login.jsp&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;2. 服务器返回登录成功。&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;3. 黑客从cookie中查看自己的sessionid，比如是1234&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;4. 黑客把带自己sessionid的地址发送给一般用户。http://www.abc.com/login.jsp;jsessionid=1234(不同的语言带sessionid的方式不一样，着是jsp的方式)&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;5. 用户在黑客给的地址中用自己的帐号进行登录，登录成功。(这个时候用户登录的信息就会覆盖黑客之前的登录信息，而且2个人用的是同1个sessionid)&amp;nbsp;&amp;nbsp; 6. 黑客刷新页面，看到的账户信息就是用户的信息了，而不是之前黑客自己帐号的信息。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;防治：&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;要防止这种问题，其实也很简单，只要在用户登录时重置session(session.invalidate()方法)，然后把登录信息保存到新的session中。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;后语：&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;可能你跟我一样，刚开始看到这个时候，就自己去测试到底能不能钓鱼成功，经过我的测试是可以成功的，但测试过程中需要注意下面几个问题：&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;1. 要注意你使用的语言是如何在URL中带sessionid。(我测试的时候开始在URL中使用大写的jsessionid，导致一直不起效)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;2. 要http://www.abc.com/login.jsp;jsessionid=1234页面登录表单的action也带上了jsessionid,不然也没用。对于这个问题你可能觉得如果login.jsp表单的action是写死，而不是读取当前URL的，&lt;span&gt;&amp;nbsp;&lt;/span&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;可能就不会出现这个钓鱼问题。这只能防住1个方向。黑客可以做1个和login.jsp一模一样的页面(比如http://www.abc1.com/login.jsp)，然后把这个地址发个客户，而这个地址中的表单这样写就可以：&lt;span&gt;&amp;nbsp;&lt;/span&gt; &lt;span&gt;&lt;/span&gt; &amp;nbsp;&amp;lt;form action="http://www.abc.com/login.jsp;jsessionid=1234" ....&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1806664.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/08/24/URL_SESSION_ID_LEEK.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/08/05/js_include.html</id><title type="text">JS 实现完美include</title><summary type="text">   js为什么需要include？让我们想想这样1个场景，a.js 需要用到1个公用的common.js，当然你可以在用到a.js的页面使用，但假设有5个页面用到了a.js，你是不是要写5遍&lt;script。而且要是以后a.js 又需要引用common2.js，你是不是又的修改5个页面了？</summary><published>2010-08-05T00:51:00Z</published><updated>2010-08-05T00:51:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/08/05/js_include.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/08/05/js_include.html"/><content type="html">&lt;p&gt;js为什么需要include？让我们想想这样1个场景，a.js 需要用到1个公用的common.js，当然你可以在用到a.js的页面使用&amp;lt;script src="common.js"&amp;gt;，但假设有5个页面用到了a.js，你是不是要写5遍&amp;lt;script。而且要是以后a.js 又需要引用common2.js，你是不是又的修改5个页面了？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;已有js include的一些问题&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;在写这个之前在网上搜索了些资料，发现以前写的include都存在2个问题，这也是include需要解决的比较重要的2个问题。&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;1、相对路径的问题：&lt;span&gt;&amp;nbsp;&lt;/span&gt; 在a.js中使用include("../js/common.js"); &amp;nbsp;include 函数中肯定是使用相对路径，是相对a.js的路径。而a.js在html中使用&amp;lt;script&amp;gt;嵌入有可能是相对路径，有可能是绝对路径。&lt;span&gt;&amp;nbsp;&lt;/span&gt; include函数如何才能真正确定common.js的绝对路径，或者是相对html的相对路径。网上一些为了解决这个问题，还需要加一些js变量，不方便。&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;2、引用的问题。&lt;span&gt;&amp;nbsp;&lt;/span&gt; 网上include函数的实现几乎都是使用下面2种方式插入common.js&lt;span&gt;&amp;nbsp;&lt;/span&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&lt;/p&gt;&lt;p&gt;document.write("&amp;lt;script src='" + .. + "&amp;gt;&amp;lt;/script&amp;gt;")&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;或者&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;var s = document.createElement("script");&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;s.src = ...;&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;head.insertAfter(s,...);&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;document.write 输出的脚本会在a.js后面加载，而createElement("script")创建的脚本是非阻塞加载。&lt;span&gt;&amp;nbsp;&lt;/span&gt; 所以如果在common.js加载完毕之前，a.js中调用了common.js的函数就会报错。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;实现&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;解决上面2个问题，就可以实现js include。&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;第1个问题，我的方法是先获取到a.js在html中的绝对路径(如果是相对路径，就转为绝对路径)，然后再把common.js的路径转为绝对路径。&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;第2个问题，采用同步的ajax来请求common.js，这样就不会出现引用问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;实现代码如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;// 根据相对路径获取绝对路径&lt;br/&gt;function getPath(relativePath,absolutePath){&lt;br/&gt;var reg = new RegExp("\\.\\./","g");&lt;br/&gt;var uplayCount = 0;// 相对路径中返回上层的次数。&lt;br/&gt;var m = relativePath.match(reg);&lt;br/&gt;if(m) uplayCount = m.length;&lt;br/&gt;&lt;br/&gt;var lastIndex = absolutePath.length-1; &lt;br/&gt;for(var i=0;i&amp;lt;=uplayCount;i++){&lt;br/&gt;lastIndex = absolutePath.lastIndexOf("/",lastIndex);&lt;br/&gt;}&lt;br/&gt;return absolutePath.substr(0,lastIndex+1) + relativePath.replace(reg,"");&lt;br/&gt;} &lt;br/&gt;&lt;br/&gt;function include(jssrc){&lt;br/&gt;// 先获取当前a.js的src。a.js中调用include,直接获取最后1个script标签就是a.js的引用。&lt;br/&gt;var scripts = document.getElementsByTagName("script");&lt;br/&gt;var lastScript = scripts[scripts.length-1];&lt;br/&gt;var src = lastScript.src;&lt;br/&gt;if(src.indexOf("http://")!=0 &amp;amp;&amp;amp; src.indexOf("/") !=0){&lt;br/&gt;// a.js使用相对路径,先替换成绝对路径&lt;br/&gt;var url = location.href;&lt;br/&gt;var index = url.indexOf("?");&lt;br/&gt;if(index != -1){&lt;br/&gt;url = url.substring(0, index-1);&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;src = getPath(src,url);&lt;br/&gt;}&lt;br/&gt;var jssrcs = jssrc.split("|");// 可以include多个js，用|隔开&lt;br/&gt;for(var i=0;i&amp;lt;jssrcs.length;i++){&lt;br/&gt;// 使用juqery的同步ajax加载js.&lt;br/&gt;// 使用document.write 动态添加的js会在当前js的后面，可能会有js引用问题&lt;br/&gt;// 动态创建script脚本，是非阻塞下载，也会出现引用问题&lt;br/&gt;$.ajax({type:'GET',url:getPath(jssrc,src),async:false,dataType:'script'});&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在a.js中直接使用 include("../js/common.js");&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;多请求的问题&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;使用上面的include看上去挺爽的，不过却带来另外1个严重的问题，就是多发送了1个ajax的请求。&lt;/p&gt;&lt;p&gt;我们常常为了WEB性能，而合并js，减少请求。但使用include后却偏偏多了请求。如果这个问题不解决，相信很多人都不会在正式产品中使用include的了，除非是局域网产品。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如何解决这个多请求的问题，我也思考很久，最后觉的单单使用客户端js是没办法解决了。所以就想到了使用服务端代码来解决&lt;/p&gt;&lt;p&gt;还记的我之前有文章介绍 "&lt;a target="_blank" href="http://www.cnblogs.com/BearsTaR/archive/2010/05/12/web_performance.html"&gt;js、css的合并、压缩、缓存管理&lt;/a&gt;"的时候，就通过服务器端代码在程序启动时候去合并js。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;所以我把include多请求的解决方案也加到里面去。就是在程序启动的时候去查找所有的js，发现有使用include的就把include中common.js的源代码替换该include函数。这样a.js中在运行的时候就没有include函数，而是真真包含了common.js的内容的js文件&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;后语&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;丫的。说到最后，怎么又把所有的include都替换掉了，哪之前说的那么多不白说了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;个人觉得，每个产品都应该要区分开发环境和产品环境(一般通过配置文件进行区分)，在开发环境应该以开发效率为首要，而产品环境则以性能为首。所以这里的inlcude就应该要区分对待，在开发环境中使用js include来提高开发和维护效率，而在产品环境中则自动把所有include替换成真真的js文件的内容。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #0000ff;"&gt;都说完了，欢迎大家拍砖讨论。&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1792626.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/08/05/js_include.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/08/04/freemarker_excel_export.html</id><title type="text">基于模板的excel导出</title><summary type="text">产品中有很多模块需要导出excel功能，导出excel几乎都是把页面已经显示出来的数据列表导出为excel。但后台使用poi生成excel却要1个单元格1个单元格的去编写。每个模块都需要单独写导出excel的代码，导致代码里充斥了createRow,createCell,setCellValue的代码。但这不是要命的，要命的是当前台数据列表格式变了的时候，后台生成excel代码的修改非常麻烦，特别是当产品经理要求在excel中也要保留WEB样式的时候(背景色，字体色，宽度)，就只能oh shit！</summary><published>2010-08-04T00:45:00Z</published><updated>2010-08-04T00:45:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/08/04/freemarker_excel_export.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/08/04/freemarker_excel_export.html"/><content type="html">&lt;p&gt;产品中有很多模块需要导出excel功能，导出excel几乎都是把页面已经显示出来的数据列表导出为excel。但后台使用poi生成excel却要1个单元格1个单元格的去编写。每个模块都需要单独写导出excel的代码，导致代码里充斥了createRow,createCell,setCellValue的代码。但这不是要命的，要命的是当前台数据列表格式变了的时候，后台生成excel代码的修改非常麻烦，特别是当产品经理要求在excel中也要保留WEB样式的时候(背景色，字体色，宽度)，就只能oh shit！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;HTML直接另存为excel&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;最开始想的解决办法是直接把数据列表的html代码另存为xls后缀的excel文件，这样是最方便，也最容易维护的方式。&amp;nbsp;&amp;nbsp;&amp;nbsp;可惜因为只是改了文件的后缀，所以当用excel打开的时候就会弹出"您尝试打开的文件格式与文件扩展名指定格式不一致。"的提示。最终放弃了该方法。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;基于模板引擎的excel数据导出&lt;/strong&gt;&lt;br /&gt;在一次跟朋友szyicol(&lt;a href="http://www.cnblogs.com/szyicol/" target="_blank"&gt;http://www.cnblogs.com/szyicol/&lt;/a&gt;)聊天中，聊起该问题，他也碰见了类似的问题，目前也是每个模块都写单独的导出excel代码。但他说想使用xls模板+xml映射文件(类似与hibernate的映射文件)来做通用导出excel。经他提醒，我最终选择使用模板引擎生成html代码，然后把html代码通过poi生成为excel。这样开发人员以后导出excel只需要编写html模板就行。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;选择html的原因&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;选择通过html代码(而不是xml或者其他)生成excel的原因有下：&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;　 &amp;nbsp;1、html对于开发人员来可读性最强，可以说看到这段html代码就知道生成的excel会是什么样子。&lt;br /&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;2、因导出的就是前台的数据列表，所以html代码几乎可以直接从前台页面中copy到模板中就可以了，维护也比较方便，不需要额外比较多的工作量。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;HTML格式&amp;nbsp;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/p&gt;&lt;p&gt;为了易解析和增加可读性，要求生成的html代码只有table tr td标签,而且只能有1个table，类似下面的代码：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&amp;lt;table&amp;gt;&lt;br/&gt;&amp;lt;tr&amp;gt;&lt;br/&gt;&amp;lt;td colspan="7" align="center"&amp;gt;项目名称&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;/tr&amp;gt;&lt;br/&gt;&amp;lt;tr&amp;gt;&lt;br/&gt;&amp;lt;td colspan="7" align="center"&amp;gt;(导出时间：2010-08-01)&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;/tr&amp;gt;&lt;br/&gt;&amp;lt;tr align="center" bgcolor="#9AB0AD"&amp;gt;&lt;br/&gt;&amp;lt;td width="150"&amp;gt;记账人&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;td width="100"&amp;gt;日期&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;td width="80"&amp;gt;金额&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;/tr&amp;gt;&lt;br/&gt;&amp;lt;tr bgcolor="#ABCDC1" color="#14645E"&amp;gt;&lt;br/&gt;&amp;lt;td color="#00000"&amp;gt;x1&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;td&amp;gt;2010-08-01&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;td&amp;gt;100&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;/tr&amp;gt;&lt;br/&gt;  &amp;lt;tr bgcolor="#ABCDC1" color="#14645E"&amp;gt;&lt;br/&gt;&amp;lt;td color="#00000"&amp;gt;x1&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;td&amp;gt;2010-08-01&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;td&amp;gt;100&amp;lt;/td&amp;gt;&lt;br/&gt;&amp;lt;/tr&amp;gt;&lt;br/&gt; &amp;lt;/table&amp;gt;&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;模板引擎&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;要根据一些数据生成上面的html代码，当然需要使用模板引擎，当然选择什么模板引擎就看自己了，我们选择了freemarker&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;html代码转excel&lt;/strong&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;对于html代码的解析，因为我们要求html代码只能有1个table,可以看出我们的html代码也是符合xml格式的，所以我们就使用xml库解析html代码。&lt;br /&gt;通过xml解析循环所有tr,td标签，并调用对应的createRow,createCell就能生成excel了，这里不贴出所有代码，有兴趣的自己研究下，只说说poi的几个问题。&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;1、合并单元格&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;当html中出现colspan的时候，就需要用到合并单元格，HSSFSheet.addMergedRegion 支持合并单元格&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;2、设置颜色&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;poi设置颜色比较麻烦，不能直接设置自定义的颜色值，默认只能使用内置的一些颜色。如果要使用自定义的颜色，需要先把内置的一些颜色替换成自定义颜色。建议先选出一些不常用的poi内置颜色(我们选了15个,应该够用了)，当发现有自定义颜色的时候，就循环进行替换这些不常用的颜色。&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;　 &amp;nbsp;具体可看：&lt;a href="http://poi.apache.org/spreadsheet/quick-guide.html#CustomColors" target="_blank"&gt;http://poi.apache.org/spreadsheet/quick-guide.html#CustomColors&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;3、设置宽度&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;这个在poi文档中没看到很详细的介绍，因为 HSSFSheet.setColumnWidth 方法,使用的并不是像素单位，也不知道是什么单位。经过尝试发现把像素宽度*40，导出的excel列宽刚好是像素宽度。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1791399.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/08/04/freemarker_excel_export.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/07/29/jsp_if_elseif_else_tag.html</id><title type="text">实现if elseif else的jsp标签。</title><summary type="text">相信很多使用jstl的朋友都抱怨过，为什么jstl只有c:if 而没有elseif、else。当需要判断多个条件的时候，只能写多个c:if 或者使用c:choose。</summary><published>2010-07-29T00:46:00Z</published><updated>2010-07-29T00:46:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/29/jsp_if_elseif_else_tag.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/29/jsp_if_elseif_else_tag.html"/><content type="html">&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt; &amp;nbsp;相信很多使用jstl的朋友都抱怨过，为什么jstl只有c:if 而没有elseif、else。当需要判断多个条件的时候，只能写多个c:if 或者使用c:choose。&lt;br /&gt;虽然struts有elseif 和&lt;span&gt;&amp;nbsp;&lt;/span&gt;else标签，不过看着就跟多个c:if 没什么2样，使用如下：&lt;/p&gt;&lt;p&gt;&amp;lt;s:if test=""&amp;gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;　1&lt;/p&gt;&lt;p&gt;&amp;lt;/s:if&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;lt;s:elseif test=""&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;2&lt;/p&gt;&lt;p&gt;&amp;lt;/s:elseif&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;lt;s:else&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 3&lt;/p&gt;&lt;p&gt;&amp;lt;/s:else&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;下面是本人实现的if elseif else。先看看使用代码:&lt;/p&gt;&lt;p&gt;&amp;lt;g:if test=""&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 1&lt;/p&gt;&lt;p&gt;&amp;lt;g:elseif test="" /&amp;gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; 2&lt;/p&gt;&lt;p&gt;&amp;lt;g:else /&amp;gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; 3&lt;/p&gt;&lt;p&gt;&amp;lt;/g:if&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;这样代码结构个人觉得更加清晰简单，类似freemarker的if elseif。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;实现：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;要实现上面说的if elseif，需要继承BodyTagSupport，利用BodyTagSupport的bodyContent的来实现该功能，这里不具体介绍如何实现jsp tag。直接贴出所有代码，有兴趣的自己看看。 &amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class IfTag extends BodyTagSupport{&lt;br/&gt;&lt;br/&gt;public IfTag() {&lt;br/&gt;        super();&lt;br/&gt;        init();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;@Override&lt;br/&gt;    public void release() {&lt;br/&gt;        super.release();&lt;br/&gt;        init();&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    @Override&lt;br/&gt;    public int doStartTag() throws JspException {&lt;br/&gt;    if(test){&lt;br/&gt;    this.succeeded();&lt;br/&gt;    }&lt;br/&gt;return EVAL_BODY_BUFFERED;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    @Override&lt;br/&gt;    public int doEndTag() throws JspException {&lt;br/&gt;    try {&lt;br/&gt;    if(subtagSucceeded)&lt;br/&gt;    pageContext.getOut().write(getBody());&lt;br/&gt;} catch (IOException e) {&lt;br/&gt;throw new JspException("IOError while writing the body: " + e.getMessage(), e);&lt;br/&gt;}&lt;br/&gt;    &lt;br/&gt;init();&lt;br/&gt;    return super.doEndTag();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    private String body = null;//用于存放成功条件后的内容&lt;br/&gt;    public void setBody(){&lt;br/&gt;    if(body == null){&lt;br/&gt;    body = bodyContent.getString().trim();&lt;br/&gt;    }&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    private String getBody(){&lt;br/&gt;    if(body == null)&lt;br/&gt;    return bodyContent.getString().trim();&lt;br/&gt;    else&lt;br/&gt;    return body;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    /**&lt;br/&gt;     * 判断if 或者 子 else if是否提交成功&lt;br/&gt;     */&lt;br/&gt;    private boolean subtagSucceeded;&lt;br/&gt;    &lt;br/&gt;    /**&lt;br/&gt;     * 子条件判断成功&lt;br/&gt;     */&lt;br/&gt;    public void succeeded(){&lt;br/&gt;    subtagSucceeded = true;&lt;br/&gt;    }&lt;br/&gt;    /**&lt;br/&gt;     * 是否已经执行完毕&lt;br/&gt;     * @return&lt;br/&gt;     */&lt;br/&gt;    public boolean isSucceeded(){&lt;br/&gt;    return subtagSucceeded;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    private void init() {&lt;br/&gt;        test = false;&lt;br/&gt;        subtagSucceeded = false;&lt;br/&gt;        body = null;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    private boolean test;  &lt;br/&gt;    &lt;br/&gt;    public void setTest(boolean test) {&lt;br/&gt;        this.test = test;&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class ElseIfTag extends BodyTagSupport{&lt;br/&gt;&lt;br/&gt;public ElseIfTag() {&lt;br/&gt;        super();&lt;br/&gt;        init();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;@Override&lt;br/&gt;public int doStartTag() throws JspException {&lt;br/&gt;    Tag parent = getParent();&lt;br/&gt;&lt;br/&gt;    if(parent==null || !(parent instanceof IfTag)){&lt;br/&gt;            throw new JspTagException("else tag must inside if tag");&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    IfTag ifTag = (IfTag)parent;&lt;br/&gt;    if(ifTag.isSucceeded()){&lt;br/&gt;    // 已经有执行成功的条件，保存之前的html&lt;br/&gt;    ifTag.setBody();&lt;br/&gt;    }else if(test){// 当前条件为true,之前无条件为true&lt;br/&gt;    ifTag.succeeded();&lt;br/&gt;    // 则清除之前的输出&lt;br/&gt;    ifTag.getBodyContent().clearBody();&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;return EVAL_BODY_BUFFERED;&lt;br/&gt;    }&lt;br/&gt; &lt;br/&gt;@Override&lt;br/&gt;    public void release() {&lt;br/&gt;        super.release();&lt;br/&gt;        init();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;private void init() {&lt;br/&gt;        test = false;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    private boolean test;  &lt;br/&gt;    &lt;br/&gt;    public void setTest(boolean test) {&lt;br/&gt;        this.test = test;&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;public class ElseTag extends BodyTagSupport{&lt;br/&gt;&lt;br/&gt;public void release() {&lt;br/&gt;        super.release();&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    public int doStartTag() throws JspException {&lt;br/&gt;    Tag parent = getParent();&lt;br/&gt;&lt;br/&gt;    if(parent==null || !(parent instanceof IfTag)){&lt;br/&gt;            throw new JspTagException("else tag must inside if tag");&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;    IfTag ifTag = (IfTag)parent;&lt;br/&gt;    if(ifTag.isSucceeded()){&lt;br/&gt;    // 已经有执行成功的条件，保存之前的html&lt;br/&gt;    ifTag.setBody();&lt;br/&gt;    }else{&lt;br/&gt;    // 之前没有的判断没有成功条件,则清除之前的输出&lt;br/&gt;    ifTag.getBodyContent().clearBody();&lt;br/&gt;    ifTag.succeeded();&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;return EVAL_BODY_BUFFERED;&lt;br/&gt;    }&lt;br/&gt;    &lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;tld配置就不贴出来了，因为这个太简单了，大家都知道的。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1787035.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/07/29/jsp_if_elseif_else_tag.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/07/16/Tally_Optimization2.html</id><title type="text">记一复杂页面的前端优化(2) - 其他优化</title><summary type="text">上一篇 "记一复杂页面的前端优化(1) - 不一样的延迟加载，"说了下对弹出窗口的优化，接下来说说其他的优化.</summary><published>2010-07-16T00:13:00Z</published><updated>2010-07-16T00:13:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/16/Tally_Optimization2.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/16/Tally_Optimization2.html"/><content type="html">&lt;p&gt;上一篇 "&lt;a target="_blank" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/14/Tally_Optimization.html"&gt;记一复杂页面的前端优化(1) - 不一样的延迟加载&lt;/a&gt;",&lt;span style="white-space: pre;"&gt;&amp;nbsp;&lt;/span&gt;说了下对弹出窗口的优化，接下来说说其他的优化，先把界面图贴出来，方便对照：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img height="544" width="1010" src="http://pic002.cnblogs.com/img/bearstar/201007/2010071317292919.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;下拉列表优化&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;然后创建自己的输入框和弹出框。当页面只有1，2个select的时候，没发现有什么问题，但当页面出现7，8个select的时候，熏染速度明显慢了很多，可以看着1个个select变成input，主要原因还是js执行的太多了(动态生成html，绑定事件)等等。这个是影响页面渲染速度的1个大问题，所以第一个要解决的就是这个select。因原始的select外观是在是不行，而且又不能修改样式，所以我们选择了1个jquery的&lt;a target="_blank" href="http://dervish.wsisiz.edu.pl/~suszynsk/jQuery/demos/jquery-selectbox/"&gt;selectbox插件&lt;/a&gt;，该插件的实现原理：在页面加载完毕后，隐藏原始的select,然后创建自己的输入框和弹出框。当页面只有1，2个select的时候，没发现有什么问题，但当页面出现7，8个select的时候，熏染速度明显慢了很多，可以看着1个个select变成input.主要原因还是js执行的太多了(动态生成html，绑定事件)等等。这个是影响页面渲染速度的1个大问题，所以第一个要解决的就是这个select。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;目前的解决方案是服务器端和js结合使用，通过jsp的标签(net应该叫自定义控件)生成html代码,并不生成任何js来绑定事件，而且当用户第一次点击input的时候，才绑定所有事件，弹出下拉窗口。这样就完全解决了渲染的问题，因为不需要js来生成html，也不需要页面加载的时候去绑定所有事件。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;右下的数据列表延迟加载&lt;/strong&gt;&lt;span style="white-space: pre;"&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;右下方的数据列表，默认只显示基本信息，当用户点击的时候才展开详细信息，一般用户只有在编辑和删除的时候才会用到详细信息，大部分情况可能不会用编辑和删除，也就不需要展开详细信息。之前的做法就是在加载列表的时候就把详细信息的html都生成好，只是隐藏一下，所以加载列表就比较慢。把详细信息改成延迟加载，当用户单击某行数据，才去生成对应的详细信息html代码，并展开显示。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;png图片转gif&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个页面用了很多PNG图片，比如收入、支出的图标，左边分类的图片，选择框的图标。而png图片在ie6下要做单独处理，为了提高性能，跟设计师商量后，把一些图片转成gif的。虽然gif的转了后效果没PNG的好看，但还可以接受，而且也是透明的，于是就通过CSS HACK,让在IE6下使用gif图片，在其他浏览器下使用png图片。这样就可以提高IE6下的速度，而又不用降低其他浏览器的界面效果。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;延迟执行ajax&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt; 左边每个分类前面有个选择框，当用户选择(或去掉选择)某个分类的时候，都会引发ajax刷新右边的数据列表。这里就可能出现这种情况，比如用户想选择3个分类查看，需要点击3次选择，之前的做法，每次点击都会触发一次ajax，这样就触发了3个ajax了，其实对于用户来说，只有最后一次ajax是有用的，前面2次不但浪费资源，而且影响性能。当然你可能会想到我们可以abort前面的ajax请求，但要注意abort只是abort客户端的执行，服务器端还是会接收到请求并执行完毕。于是对这个ajax做了个延迟，每次点击后延迟0.5秒执行，如果用户在0.5秒内再一次点击，则取消之前的ajax。这样就可以避免一些不必要的ajax请求了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;后语&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt; 今天这篇文章只是介绍优化的方法，并没写任何代码，个人觉的这种方法不需要写代码，大家一看应该就知道。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt; 该页面中经过这些优化后，页面总的加载速度(包括资源下载、解析、执行、页面呈现)提高了3倍左右。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div id="_mcePaste" style="position: absolute; left: -10000px; top: 357px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"&gt;目前的解决方案是服务器端和js结合使用，通过jsp的标签(net应该叫自定义控件)生成html代码,并不生成任何js来绑定事件，而且当用户第一次点击input的时候，才绑定所有事件，弹出下拉窗口。&lt;/div&gt;&lt;div id="_mcePaste" style="position: absolute; left: -10000px; top: 357px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"&gt;这样就完全解决了渲染的问题，因为不需要js来生成html，也不需要页面加载的时候去绑定所有事件。目前的解决方案是服务器端和js结合使用，通过jsp的标签(net应该叫自定义控件)生成html代码,并不生成任何js来绑定事件，而且当用户第一次点击input的时候，才绑定所有事件，弹出下拉窗口。这样就完全解决了渲染的问题，因为不需要js来生成html，也不需要页面加载的时候去绑定所有事件。&lt;/div&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1778120.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/07/16/Tally_Optimization2.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/07/14/Tally_Optimization.html</id><title type="text">记一复杂页面的前端优化(1) - 不一样的延迟加载</title><summary type="text">刚刚做完1个复杂页面的前端性能优化，这里的优化是针对这个页面具体的需求单独做的优化，所以这里不会谈哪些减少http请求，合并压缩js,css，图片合并等等。因为这些是所有页面都需要做的，如果需要了解这些，可以参考我这篇文章：</summary><published>2010-07-14T00:32:00Z</published><updated>2010-07-14T00:32:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/14/Tally_Optimization.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/14/Tally_Optimization.html"/><content type="html">&lt;p&gt;刚刚做完1个复杂页面的前端性能优化，这里的优化是针对这个页面具体的需求单独做的优化，所以这里不会谈那些减少http请求，合并压缩js,css，图片合并等等。因为这些是所有页面都需要做的，如果需要了解这些，可以参考我这篇文章：&lt;a target="_blank" href="http://www.cnblogs.com/BearsTaR/archive/2010/05/12/web_performance.html"&gt;web高性能开发系列随笔&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;页面介绍：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;该页面是1个记账类的页面，页面如下：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/img/bearstar/201007/2010071317292919.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;页面主要有4部分组成：&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt;1. 上部的输入部分(有5大不同的类型，每个类型都是1个单独的tab，对应内容也不一样)&lt;span style="white-space: pre;"&gt;&lt;/span&gt; &amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt;2. 左边的分类列表(默认显示一级分类，点击展开子类)&lt;span style="white-space: pre;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt;3. 右边时间选择区(按月，年，季，自定义时间过滤等等)&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt;4. 右边下半部分的数据列表(默认只显示每条数据基本信息，点击展开详细信息)&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;可能看到这里大家不觉的这个页面会很大，那就再细说下，该页面包含记账的所有的功能(添加、删除，修改，分拆，上传图片，显示数据，数据排序)，而且每种下拉列表前面都有个"加号"(见输入部分的下列列表)，点击"加号"都会弹出类似如下的窗口进行添加(总共有8个左右的弹出窗口)，所有的这些都是通过js来实现(js代码总共写了大概2000行，不含注释)：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/img/bearstar/201007/2010071317361234.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;该页面有一些用户反映比较慢，经过测试也发现，因为页面比较复杂，js也比较多，所以在IE下速度会比较慢(特别是IE6)，而chrome和firefox速度还是可以的，所以这次的优化主要针对IE，当然优化后的其他浏览器肯定也会受益。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;优化1：弹出窗口的延迟加载&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本来第1个优化不应该写这个，因为这个优化效果并不是最明显的。把它放在第一位，是因为个人觉得这种延迟加载的想法还不错，比较有新意(目前还没见过网上有人介绍过这种延迟加载)。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;入正题，上面说到，该页面总共有8个弹出窗口，而且每个弹出窗口的都使用了不同的图片(不少是png)，监控发现这些弹出窗口用的png图片虽然设置了缓存头(也使用了document.execCommand("BackgroundImageCache", false, true);)，但是在IE6下每次都不直接使用缓存，而是发生1个请求，并得到304状态回应(原因我估计跟使用DD_belatedPNG来处理png图片有关，因为时间关系还没深入研究)，监控图如下：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/img/bearstar/201007/2010071317382689.jpg" /&gt;&lt;/p&gt;&lt;p&gt;从图中可以看出这几个图片很影响加载速度，其实一开始我们根本用不上这些弹出窗口的图片，因为默认都是隐藏的，而且这些弹出窗口，一般用户都用的比较少。理所当然，我们想到了延迟加载。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;想到延迟加载，第一想到就是先不加载弹出窗口的html代码，这样就不会加载对应的图片了，当用户点击弹出按钮的时候，再去后台加载对应的html代码。但这样就有个问题，当用户点击"加号"按钮，用ajax去加载html代码，用户明显就会感觉到半天窗口还没弹出来，就会连续的点击，这种用户体验肯定是失败的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;我们想要的延迟加载是先加载html代码，但不加载html代码使用的图片。但用户点击"加号"的时候，直接弹出窗口并加载图片，这样用户一点击就可以看到窗口。那如何实现这种功能了，于是我想到了html的注释。我们先把所有弹出窗口的html代码放进注释中(这样就不会加载图片)，当用户点击"加号"时，用js读取注释中的html插入到body中(不需要ajax)，然后弹出窗口。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;比如有2个弹出窗口，代码大概如下(并不是完整代码，不能直接运行)：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt; &amp;lt;script&amp;gt;&lt;br/&gt;  var loaded = new Object();  // 记录哪些html已经append到body中&lt;br/&gt; /**&lt;br/&gt; * 加载html，该html已经以注释的方式嵌入的html中，eg:&lt;br/&gt; * &amp;lt;div id="fast_model_lazy"&amp;gt;&lt;br/&gt; *&amp;lt;!--[lazy]&amp;gt;&lt;br/&gt; *sass&lt;br/&gt; *  &amp;lt;![endlazy]--&amp;gt;&lt;br/&gt; * &amp;lt;/div&amp;gt;&lt;br/&gt; */&lt;br/&gt;function loadHtml(id){&lt;br/&gt;// 已经加载过，不再加载&lt;br/&gt;if(loaded[id])&lt;br/&gt;return false;&lt;br/&gt;&lt;br/&gt;var html = $.trim(document.getElementById(id).innerHTML);&lt;br/&gt;// 去掉注释开头(11位)和结尾(14位)&lt;br/&gt;html = html.substring(11,html.length-14);&lt;br/&gt;$(document.body).append($(html));&lt;br/&gt;&lt;br/&gt;loaded[id]=1;&lt;br/&gt;return true;&lt;br/&gt;}&lt;br/&gt;function click1(){&lt;br/&gt;loadHtml("fast_model_lazy");&lt;br/&gt;// 弹出窗口&lt;br/&gt;$("#fast_model_lazy").showDialog();&lt;br/&gt;}&lt;br/&gt;function click2(){&lt;br/&gt;loadHtml("fast_model2_lazy");&lt;br/&gt;// 弹出窗口&lt;br/&gt;$("#fast_model2_lazy").showDialog();&lt;br/&gt;}&lt;br/&gt; &amp;lt;/script&amp;gt;&lt;br/&gt; &amp;lt;button click="click1()"&amp;gt;弹出第一窗口&amp;lt;/button&amp;gt;&lt;br/&gt; &amp;lt;button click="click2()"&amp;gt;弹出第二窗口&amp;lt;/button&amp;gt;&lt;br/&gt; &lt;br/&gt; &amp;lt;div id="fast_model_lazy"&amp;gt;&lt;br/&gt;   &amp;lt;!--[lazy]&amp;gt;&lt;br/&gt;   &amp;lt;div id="fast_model" class="model"&amp;gt;&lt;br/&gt;   ....这里省略html&lt;br/&gt;   &amp;lt;/div&amp;gt;&lt;br/&gt;  &amp;lt;![endlazy]--&amp;gt;&lt;br/&gt; &amp;lt;/div&amp;gt;&lt;br/&gt;&lt;br/&gt; &amp;lt;div id="fast_model2_lazy"&amp;gt;&lt;br/&gt;   &amp;lt;!--[lazy]&amp;gt;&lt;br/&gt;   &amp;lt;div id="fast_model2" class="model"&amp;gt;&lt;br/&gt;   ....这里省略html&lt;br/&gt;   &amp;lt;/div&amp;gt;&lt;br/&gt;  &amp;lt;![endlazy]--&amp;gt;&lt;br/&gt; &amp;lt;/div&amp;gt;&lt;br/&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt; 这种延迟加载的方式，主要用于延迟图片的加载，css的应用，js的解析和执行等等，并不是为了延迟加载html。如果是大量的html代码，比如分页的数据，&lt;/p&gt;&lt;p&gt;使用这种方式就不太合适。个人觉的这种加载方式还可以在很多地方用的到的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;后语：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt; 今天就写这些，下次再写写对该页面的其他的一些优化。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1776642.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/07/14/Tally_Optimization.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/07/02/tudou_easeOutBounce.html</id><title type="text">名站技术分析 — tudou网首页下列菜单的弹出效果</title><summary type="text">土豆(tudou.com)首页的导航条,当鼠标移到到“社区”菜单时，对应的菜单的弹出效果比较有意思，类似于一个弹球落地的效果，对于有意思的东西，当然要研究研究。有兴趣的朋友可以自己先去看看效果，然后再来看文章。</summary><published>2010-07-02T00:40:00Z</published><updated>2010-07-02T00:40:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/02/tudou_easeOutBounce.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/02/tudou_easeOutBounce.html"/><content type="html">&lt;script type="text/javascript"&gt;// &lt;![CDATA[jQuery.extend(jQuery.easing,{def : "easeOutQuad",swing : function(o, p, n, r, q) {return jQuery.easing[jQuery.easing.def](o, p, n, r,q)},easeOutBounce : function(o, p, n, r, q) {if ((p /= q) &lt; (1 / 2.75)) {return r * (7.5625 * p * p) + n} else {if (p &lt; (2 / 2.75)) {return r * (7.5625 * (p -= (1.5 / 2.75)) * p + 0.75) + n} else {if (p &lt; (2.5 / 2.75)) {return r * (7.5625 * (p -= (2.25 / 2.75))* p + 0.9375) + n} else {return r * (7.5625 * (p -= (2.625 / 2.75)) * p + 0.984375) + n}}}}});function b_showMenu(){b_resetMenu();$("#b_menu").animate({height:100},500,"easeOutBounce");}function b_resetMenu(){$("#b_menu").show();$("#b_menu").height(0);}// ]]&gt;&lt;/script&gt;&lt;style type="text/css"&gt;&lt;!--#b_menu{border:1px solid #F56E0B;width:100px;list-style:none;padding:0;height:0;overflow:hidden;display:none;}#b_menu li{line-height:25px;width:100px;text-align:center;}--&gt;&lt;/style&gt;&lt;p&gt;土豆(tudou.com)首页的导航条,当鼠标移到到&amp;ldquo;社区&amp;rdquo;菜单时，对应的菜单的弹出效果比较有意思，类似于一个弹球落地的效果，对于有意思的东西，当然要研究研究。有兴趣的朋友可以自己先去看看效果，然后再来看文章。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;tudou代码&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 看了tudou的js代码，发现他们也是使用jquery来实现动画效果的，代码如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; f.style.height=0;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; this.style.visibility="visible";&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;$(f).animate({height:g},500,"easeOutBounce");&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; $(i).addClass("hover")&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 最重要的是上面第三行代码，使用jquery的animate的函数，其中重点就是tudou自定义了animate的easing函数，即easeOutBounce函数，easeOutBounce函数如下。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;   easeOutBounce:function(o,p,n,r,q){&lt;br/&gt;if((p/=q)&amp;lt;(1/2.75)){&lt;br/&gt;return r*(7.5625*p*p)+n&lt;br/&gt;}else{&lt;br/&gt;if(p&amp;lt;(2/2.75)){&lt;br/&gt;return r*(7.5625*(p-=(1.5/2.75))*p+0.75)+n&lt;br/&gt;}else{&lt;br/&gt;if(p&amp;lt;(2.5/2.75)){&lt;br/&gt;return r*(7.5625*(p-=(2.25/2.75))*p+0.9375)+n&lt;br/&gt;}else{&lt;br/&gt;return r*(7.5625*(p-=(2.625/2.75))*p+0.984375)+n&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;   }&lt;br/&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;strong&gt;DEMO&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;先不分析代码，先用tudou的easeOutBounce函数做个demo看看效果。&lt;/div&gt;&lt;div&gt;demo(该demo在IE下点击没有效果，可能是跟博客园的其他代码有冲突，不想花时间去解决。要在IE下看效果，请copy后面的代码在本地进行测试)：&lt;/div&gt;&lt;div style="height: 150px; padding-left: 20px;"&gt;&amp;nbsp;&amp;nbsp;&lt;a href="javascript:void(0)" onclick="b_showMenu();"&gt;我的菜单(点击我)&lt;/a&gt;&lt;br /&gt; &lt;ul id="b_menu"&gt;&lt;li&gt;菜单一&lt;/li&gt;&lt;li&gt;菜单二&lt;/li&gt;&lt;li&gt;菜单三&lt;/li&gt;&lt;li&gt;菜单四&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;代码：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br/&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;&lt;br/&gt;&amp;lt;head&amp;gt;&lt;br/&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&amp;gt;&lt;br/&gt;&amp;lt;script type="text/javascript" src="http://common.cnblogs.com/script/jquery.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br/&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br/&gt;jQuery.extend(jQuery.easing,{&lt;br/&gt;def : "easeOutQuad",&lt;br/&gt;swing : function(o, p, n, r, q) {&lt;br/&gt;return jQuery.easing[jQuery.easing.def](o, p, n, r,q)&lt;br/&gt;},&lt;br/&gt;easeOutBounce : function(o, p, n, r, q) {&lt;br/&gt;if ((p /= q) &amp;lt; (1 / 2.75)) {&lt;br/&gt;return r * (7.5625 * p * p) + n&lt;br/&gt;} else {&lt;br/&gt;if (p &amp;lt; (2 / 2.75)) {&lt;br/&gt;return r * (7.5625 * (p -= (1.5 / 2.75)) * p + 0.75) + n&lt;br/&gt;} else {&lt;br/&gt;if (p &amp;lt; (2.5 / 2.75)) {&lt;br/&gt;return r * (7.5625 * (p -= (2.25 / 2.75))* p + 0.9375) + n&lt;br/&gt;} else {&lt;br/&gt;return r * (7.5625 * (p -= (2.625 / 2.75)) * p + 0.984375) + n&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;});&lt;br/&gt;function showMenu(){&lt;br/&gt;resetMenu();&lt;br/&gt;$("#b_menu").animate({height:100},500,"easeOutBounce");&lt;br/&gt;}&lt;br/&gt;function resetMenu(){&lt;br/&gt;$("#b_menu").show();&lt;br/&gt;$("#b_menu").height(0);&lt;br/&gt;}&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;br/&gt;&lt;br/&gt;&amp;lt;style type="text/css"&amp;gt;&lt;br/&gt;#b_menu{border:1px solid #F56E0B;width:100px;list-style:none;padding:0;height:0;overflow:hidden;display:none;}&lt;br/&gt;#b_menu li{line-height:25px;width:100px;text-align:center;}&lt;br/&gt;&amp;lt;/style&amp;gt;&lt;br/&gt;&amp;lt;/head&amp;gt;&lt;br/&gt;&amp;lt;body&amp;gt;&lt;br/&gt;  &amp;lt;a href="javascript:showMenu();void(0)"&amp;gt;我的菜单&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;&lt;br/&gt;  &amp;lt;ul id="b_menu"&amp;gt;&lt;br/&gt;  &amp;lt;li&amp;gt;菜单一&amp;lt;/li&amp;gt;&lt;br/&gt;  &amp;lt;li&amp;gt;菜单二&amp;lt;/li&amp;gt;&lt;br/&gt;  &amp;lt;li&amp;gt;菜单三&amp;lt;/li&amp;gt;&lt;br/&gt;  &amp;lt;li&amp;gt;菜单四&amp;lt;/li&amp;gt;&lt;br/&gt;  &amp;lt;/ul&amp;gt;&lt;br/&gt;  &amp;lt;/body&amp;gt;&lt;br/&gt;&amp;lt;/html&amp;gt;  &lt;br/&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;strong&gt;easing函数&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;jquery默认定义了2个easing函数，分别是swing和linear,easing函数格式如下：function(o, p, n, r, q)&lt;/div&gt;&lt;div&gt;但对于该几个参数的具体说明，jquery官方也没有文档说明(不知道是否是我没有找到)，经过我看源代码和自己的理解，对几个参数理解如下：&lt;/div&gt;&lt;div&gt;o = p/q&lt;/div&gt;&lt;div&gt;p: 当前时间 - animate开始时间的毫秒值&lt;/div&gt;&lt;div&gt;n: 起始值，一直为0&lt;/div&gt;&lt;div&gt;r: 这个个人认为是递增值，一直为1&lt;/div&gt;&lt;div&gt;q: animate中的duration参数，即设置的动画效果运行完毕需要的时间&lt;/div&gt;&lt;div&gt;返回值：返回1个大于0，小于等于1的百分比值，animate方法通过这个百分比去计算各个参数的值&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;知道这几个参数的含义后，再看看tudou的easeOutBounce，就发现其第一行代码写的有问题，if ((p /= q) &amp;lt; (1 / 2.75)) 其实可以直接写成&amp;nbsp;if ((o) &amp;lt; (1 / 2.75)) 。&lt;/div&gt;&lt;div&gt;可以看出tudou的开发人员对easing函数的几个参数也不太理解，不然就不会这样写了(也有可能easeOutBounce函数，tudou也是直接从其他地方copy过来的，呵呵)&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;胡言乱语&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;在查询jquery的easing参数的时候，无意间发现1个专门做easing效果的网站(&lt;a target="_blank" href="http://gsgd.co.uk/sandbox/jquery/easing/"&gt;http://gsgd.co.uk/sandbox/jquery/easing/&lt;/a&gt;)，而土豆的几个easing效果代码跟该网站的easing效果代码是惊人的相似，除了参数名不同外(这也出现我前面copy 代码的猜测),其实是不是copy都无所谓的，偶也是胡言乱语下，大家也别想太多，贴出2段代码，大家自己看看吧。&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;下面tudou的代码：&lt;/div&gt;&lt;div&gt;jQuery.extend(jQuery.easing,{&lt;br/&gt;def : "easeOutQuad",&lt;br/&gt;swing : function(o, p, n, r, q) {&lt;br/&gt;return jQuery.easing[jQuery.easing.def](o, p, n, r,q)&lt;br/&gt;},&lt;br/&gt;easeInQuad : function(o, p, n, r, q) {&lt;br/&gt;return r * (p /= q) * p + n&lt;br/&gt;},&lt;br/&gt;easeOutQuad : function(o, p, n, r, q) {&lt;br/&gt;return -r * (p /= q) * (p - 2) + n&lt;br/&gt;},&lt;br/&gt;easeInOutQuad : function(o, p, n, r, q) {&lt;br/&gt;if ((p /= q / 2) &amp;lt; 1) {&lt;br/&gt;return r / 2 * p * p * p + n&lt;br/&gt;}&lt;br/&gt;return r / 2 * ((p -= 2) * p * p + 2) + n&lt;br/&gt;},&lt;br/&gt;easeInBack : function(o, p, n, u, r, q) {&lt;br/&gt;if (q == undefined) {&lt;br/&gt;q = 1.70158&lt;br/&gt;}&lt;br/&gt;return u * (p /= r) * p * ((q + 1) * p - q) + n&lt;br/&gt;},&lt;br/&gt;easeOutBack : function(o, p, n, u, r, q) {&lt;br/&gt;if (q == undefined) {&lt;br/&gt;q = 1.70158&lt;br/&gt;}&lt;br/&gt;return u * ((p = p / r - 1) * p * ((q + 1) * p + q) + 1) + n&lt;br/&gt;},&lt;br/&gt;easeOutBounce : function(o, p, n, r, q) {&lt;br/&gt;if ((p /= q) &amp;lt; (1 / 2.75)) {&lt;br/&gt;return r * (7.5625 * p * p) + n&lt;br/&gt;} else {&lt;br/&gt;if (p &amp;lt; (2 / 2.75)) {&lt;br/&gt;return r * (7.5625 * (p -= (1.5 / 2.75)) * p + 0.75) + n&lt;br/&gt;} else {&lt;br/&gt;if (p &amp;lt; (2.5 / 2.75)) {&lt;br/&gt;return r * (7.5625 * (p -= (2.25 / 2.75))* p + 0.9375) + n&lt;br/&gt;} else {&lt;br/&gt;return r * (7.5625 * (p -= (2.625 / 2.75)) * p + 0.984375) + n&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;}&lt;br/&gt;});&lt;br/&gt;&lt;/div&gt;&lt;div&gt;&lt;a target="_blank" href="http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js"&gt;http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js&lt;/a&gt; 代码&lt;/div&gt;&lt;div&gt;jQuery.extend( jQuery.easing,{&lt;br/&gt;def: 'easeOutQuad',&lt;br/&gt;swing: function (x, t, b, c, d) {&lt;br/&gt;//alert(jQuery.easing.default);&lt;br/&gt;return jQuery.easing[jQuery.easing.def](x, t, b, c, d);&lt;br/&gt;},&lt;br/&gt;easeInQuad: function (x, t, b, c, d) {&lt;br/&gt;return c*(t/=d)*t + b;&lt;br/&gt;},&lt;br/&gt;easeOutQuad: function (x, t, b, c, d) {&lt;br/&gt;return -c *(t/=d)*(t-2) + b;&lt;br/&gt;},&lt;br/&gt;easeInOutQuad: function (x, t, b, c, d) {&lt;br/&gt;if ((t/=d/2) &amp;lt; 1) return c/2*t*t + b;&lt;br/&gt;return -c/2 * ((--t)*(t-2) - 1) + b;&lt;br/&gt;},&lt;br/&gt;easeInCubic: function (x, t, b, c, d) {&lt;br/&gt;return c*(t/=d)*t*t + b;&lt;br/&gt;},&lt;br/&gt;easeOutCubic: function (x, t, b, c, d) {&lt;br/&gt;return c*((t=t/d-1)*t*t + 1) + b;&lt;br/&gt;},&lt;br/&gt;easeInOutCubic: function (x, t, b, c, d) {&lt;br/&gt;if ((t/=d/2) &amp;lt; 1) return c/2*t*t*t + b;&lt;br/&gt;return c/2*((t-=2)*t*t + 2) + b;&lt;br/&gt;},&lt;br/&gt;easeInQuart: function (x, t, b, c, d) {&lt;br/&gt;return c*(t/=d)*t*t*t + b;&lt;br/&gt;},&lt;br/&gt;easeOutQuart: function (x, t, b, c, d) {&lt;br/&gt;return -c * ((t=t/d-1)*t*t*t - 1) + b;&lt;br/&gt;},&lt;br/&gt;easeInOutQuart: function (x, t, b, c, d) {&lt;br/&gt;if ((t/=d/2) &amp;lt; 1) return c/2*t*t*t*t + b;&lt;br/&gt;return -c/2 * ((t-=2)*t*t*t - 2) + b;&lt;br/&gt;},&lt;br/&gt;easeInQuint: function (x, t, b, c, d) {&lt;br/&gt;return c*(t/=d)*t*t*t*t + b;&lt;br/&gt;},&lt;br/&gt;easeOutQuint: function (x, t, b, c, d) {&lt;br/&gt;return c*((t=t/d-1)*t*t*t*t + 1) + b;&lt;br/&gt;},&lt;br/&gt;easeInOutQuint: function (x, t, b, c, d) {&lt;br/&gt;if ((t/=d/2) &amp;lt; 1) return c/2*t*t*t*t*t + b;&lt;br/&gt;return c/2*((t-=2)*t*t*t*t + 2) + b;&lt;br/&gt;},&lt;br/&gt;easeInSine: function (x, t, b, c, d) {&lt;br/&gt;return -c * Math.cos(t/d * (Math.PI/2)) + c + b;&lt;br/&gt;},&lt;br/&gt;easeOutSine: function (x, t, b, c, d) {&lt;br/&gt;return c * Math.sin(t/d * (Math.PI/2)) + b;&lt;br/&gt;},&lt;br/&gt;easeInOutSine: function (x, t, b, c, d) {&lt;br/&gt;return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;&lt;br/&gt;},&lt;br/&gt;easeInExpo: function (x, t, b, c, d) {&lt;br/&gt;return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;&lt;br/&gt;},&lt;br/&gt;easeOutExpo: function (x, t, b, c, d) {&lt;br/&gt;return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;&lt;br/&gt;},&lt;br/&gt;easeInOutExpo: function (x, t, b, c, d) {&lt;br/&gt;if (t==0) return b;&lt;br/&gt;if (t==d) return b+c;&lt;br/&gt;if ((t/=d/2) &amp;lt; 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;&lt;br/&gt;return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;&lt;br/&gt;},&lt;br/&gt;easeInCirc: function (x, t, b, c, d) {&lt;br/&gt;return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;&lt;br/&gt;},&lt;br/&gt;easeOutCirc: function (x, t, b, c, d) {&lt;br/&gt;return c * Math.sqrt(1 - (t=t/d-1)*t) + b;&lt;br/&gt;},&lt;br/&gt;easeInOutCirc: function (x, t, b, c, d) {&lt;br/&gt;if ((t/=d/2) &amp;lt; 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;&lt;br/&gt;return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;&lt;br/&gt;},&lt;br/&gt;easeInElastic: function (x, t, b, c, d) {&lt;br/&gt;var s=1.70158;var p=0;var a=c;&lt;br/&gt;if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;&lt;br/&gt;if (a &amp;lt; Math.abs(c)) { a=c; var s=p/4; }&lt;br/&gt;else var s = p/(2*Math.PI) * Math.asin (c/a);&lt;br/&gt;return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;&lt;br/&gt;},&lt;br/&gt;easeOutElastic: function (x, t, b, c, d) {&lt;br/&gt;var s=1.70158;var p=0;var a=c;&lt;br/&gt;if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;&lt;br/&gt;if (a &amp;lt; Math.abs(c)) { a=c; var s=p/4; }&lt;br/&gt;else var s = p/(2*Math.PI) * Math.asin (c/a);&lt;br/&gt;return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;&lt;br/&gt;},&lt;br/&gt;easeInOutElastic: function (x, t, b, c, d) {&lt;br/&gt;var s=1.70158;var p=0;var a=c;&lt;br/&gt;if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);&lt;br/&gt;if (a &amp;lt; Math.abs(c)) { a=c; var s=p/4; }&lt;br/&gt;else var s = p/(2*Math.PI) * Math.asin (c/a);&lt;br/&gt;if (t &amp;lt; 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;&lt;br/&gt;return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;&lt;br/&gt;},&lt;br/&gt;easeInBack: function (x, t, b, c, d, s) {&lt;br/&gt;if (s == undefined) s = 1.70158;&lt;br/&gt;return c*(t/=d)*t*((s+1)*t - s) + b;&lt;br/&gt;},&lt;br/&gt;easeOutBack: function (x, t, b, c, d, s) {&lt;br/&gt;if (s == undefined) s = 1.70158;&lt;br/&gt;return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;&lt;br/&gt;},&lt;br/&gt;easeInOutBack: function (x, t, b, c, d, s) {&lt;br/&gt;if (s == undefined) s = 1.70158; &lt;br/&gt;if ((t/=d/2) &amp;lt; 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;&lt;br/&gt;return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;&lt;br/&gt;},&lt;br/&gt;easeInBounce: function (x, t, b, c, d) {&lt;br/&gt;return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;&lt;br/&gt;},&lt;br/&gt;easeOutBounce: function (x, t, b, c, d) {&lt;br/&gt;if ((t/=d) &amp;lt; (1/2.75)) {&lt;br/&gt;return c*(7.5625*t*t) + b;&lt;br/&gt;} else if (t &amp;lt; (2/2.75)) {&lt;br/&gt;return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;&lt;br/&gt;} else if (t &amp;lt; (2.5/2.75)) {&lt;br/&gt;return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;&lt;br/&gt;} else {&lt;br/&gt;return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;&lt;br/&gt;}&lt;br/&gt;},&lt;br/&gt;easeInOutBounce: function (x, t, b, c, d) {&lt;br/&gt;if (t &amp;lt; d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;&lt;br/&gt;return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;&lt;br/&gt;}&lt;br/&gt;});&lt;br/&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;相关链接&lt;/div&gt;&lt;div&gt;&lt;a target="_blank" href="http://www.cnblogs.com/BearsTaR/archive/2010/06/18/facebook_html_chunk.html" class="titlelink"&gt;名站技术分析 &amp;mdash; facebook奇特的页面加载技术&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a target="_blank" href="http://www.cnblogs.com/BearsTaR/archive/2010/05/25/tudou_lazy_image.html"&gt;名站技术分析 - 浅谈tudou.com首页图片延迟加载的效果&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1769591.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/07/02/tudou_easeOutBounce.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/07/01/less.html</id><title type="text">LESS 让css也支持变量，运算符，include,嵌套规则等等</title><summary type="text">最近在网上看到1个很有意思的CSS扩展，这里介绍给大家。LESS 最早是1个ruby的gem，用于扩展css的语法，用了LESS后，可以在css中使用变量，运算符，include,嵌套规则等等。现在LESS出了js版本，让我们一起来看看LESS能为我们带来什么吧?</summary><published>2010-07-01T00:49:00Z</published><updated>2010-07-01T00:49:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/01/less.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/07/01/less.html"/><content type="html">&lt;p&gt;最近在网上看到1个很有意思的CSS扩展，这里介绍给大家。LESS 最早是1个ruby的gem，用于扩展css的语法，用了LESS后，可以在css中使用变量，运算符，include,嵌套规则等等。现在LESS出了js版本，让我们一起来看看LESS能为我们带来什么吧?&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;使用&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 1. 下载js: &lt;a href="http://lesscss.googlecode.com/" target="_blank"&gt;http://lesscss.googlecode.com/&lt;/a&gt; 最新版本好像是 1.0.22&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 2. 使用less，css文件的后缀名需要改为.less。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 3. 在html页面中加入下面代码&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;lt;!-- style.less文件就是样式表文件，并且style.less必须放在less-1.0.22.min.js文件前加载，原理后面介绍 --&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;lt;link rel="stylesheet/less" href="style.less" /&amp;gt; &amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;lt;script src="less-1.0.22.min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;变量&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 变量可以让我们声明1个常量值，并在以后多处地方进行重复使用。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 一般css写法：&lt;/p&gt;   .class1{&lt;br/&gt;      color:#ccc;&lt;br/&gt;      width:100px;&lt;br/&gt;   }&lt;br/&gt;   &lt;br/&gt;   .class2{&lt;br/&gt;      color:#ccc;&lt;br/&gt;      width:120px;&lt;br/&gt;   }&lt;br/&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;LESS写法:&lt;/div&gt;&lt;div&gt;   @color1: #ccc;&lt;br/&gt;   &lt;br/&gt;   .class1{&lt;br/&gt;      color:@color1;&lt;br/&gt;      width:100px;&lt;br/&gt;   }&lt;br/&gt;   &lt;br/&gt;   .class2{&lt;br/&gt;      color:@color1;&lt;br/&gt;      width:120px;&lt;br/&gt;   }&lt;br/&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;inlucde&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;大家一定碰见过再某个规则中需要用的部分样式跟另外1个规则样式一样，但没办法，我们只能copy过来，或者为元素指定多个class。但用了LESS后，我们不再需要这么痛苦了。&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;一般css写法：&lt;/div&gt;&lt;div&gt;   .red{&lt;br/&gt;     color:red;border:1px solid red;&lt;br/&gt;   }&lt;br/&gt;   &lt;br/&gt;   .class2{&lt;br/&gt;      width:100px;font-size:12px;&lt;br/&gt;      /*下面的样式跟red的一样,copy过来的，修改就要修改2处*/&lt;br/&gt;      color:red;border:1px solid red;&lt;br/&gt;   }&lt;br/&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;LESS写法:&lt;/div&gt;&lt;div&gt;   .red{&lt;br/&gt;     color:red;border:1px solid red;&lt;br/&gt;   }&lt;br/&gt;   &lt;br/&gt;   .class2{&lt;br/&gt;      width:100px;font-size:12px;&lt;br/&gt;      /*直接inlcude .red的规则*/&lt;br/&gt;      .red&lt;br/&gt;   }&lt;br/&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;嵌套规则:&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;一般css的写法：&lt;/div&gt;&lt;div&gt;   #header{color:red;}&lt;br/&gt;#header .logo{backgroud-image:url(logo.gif);}&lt;br/&gt;#header li{display:block;} &lt;br/&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;LESS写法:&lt;/div&gt;&lt;div&gt;   #header{&lt;br/&gt;     color:red;&lt;br/&gt;     .logo{&lt;br/&gt;         backgroud-image:url(logo.gif);&lt;br/&gt;      }&lt;br/&gt;      li{&lt;br/&gt;        display:block;&lt;br/&gt;      } &lt;br/&gt;   }&lt;br/&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;运算符：&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;LESS 写法:&lt;/div&gt;&lt;div&gt;    @fontSize 12px;&lt;br/&gt;    .class1{&lt;br/&gt;font-size : @fontSize + 2;&lt;br/&gt;    }&lt;br/&gt;    .class2{&lt;br/&gt;font-size : @fontSize * 2;&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;更多其它功能:&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;请见LESS官方网站：&lt;a href="http://lesscss.org/" target="_blank"&gt;http://lesscss.org/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;原理分析:&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;LESS js版本的实现方式是使用ajax获取style.less文件，然后根据该文件的规则生成最终浏览器能理解的css插入到html代码中。所以就出现前面说过的&amp;lt;link rel="stylesheet/less" href="style.less" /&amp;gt;必须在js前面。&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;总结:&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;LESS JS版本的实现原理，是每次请求都需要通过JS去动态生成原始的css，如果css比较大的话，对于客户端的性能影响比较大，所以个人觉的less的js版本实用性不强。&lt;/div&gt;&lt;div&gt;不知道LESS 的ruby版本的实现原理是怎么样的，我认为如果真的觉得less方式可以提高css的开发效率，到是可以参考它的代码实现一套java或net的源代码，在程序启动的时候一次根据.less文件生成所有的css文件，而不是每次请求都用js动态生成。&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;span style="color: #ff0000;"&gt;PS:刚刚无意间搜索，竟然找到1个net版本的less，大家可以看看这个版本怎么实现的&lt;/span&gt;：&lt;a target="_blank" href="http://www.dotlesscss.com/"&gt;http://www.dotlesscss.com/&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1768741.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/07/01/less.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/06/25/css_tip_round_gradients_shadow.html</id><title type="text">CSS技巧 — 不使用图片实现圆角、阴影、渐变等功能</title><summary type="text">UI要求越来越高，界面越做越华丽，给我们开发人员带来的就是使用大量的背景图片，下面介绍一些通过css(不使用图片或少使用图片)来实现一些很常见的效果:圆角、阴影、渐变等等。</summary><published>2010-06-25T00:51:00Z</published><updated>2010-06-25T00:51:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/06/25/css_tip_round_gradients_shadow.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/06/25/css_tip_round_gradients_shadow.html"/><content type="html">&lt;style type="text/css"&gt;&lt;!--.b_box{text-align:center;width:200px;line-height:60px;border:1px solid #C0C0C0;background-color:#DBEAFF;/*firefox*/-moz-border-radius: 5px;/*css3*/border-radius: 5px;/*webkit*/  -webkit-border-radius: 5px;}.b_shadow{  height:60px;line-height:60px;text-align:center;  width:200px;border:1px solid #C0C0C0;background-color:#DBEAFF;  -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);  -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);  box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);  /*IE6,IE7语法*/  filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=5, OffY=5, Color='gray');  /*IE8语法,可恶的IE，不同的版本还要写的不一样*/  -ms-filter:"progid:DXImageTransform.Microsoft.dropshadow(OffX=5, OffY=5, Color='gray')"  -moz-border-radius: 5px;border-radius: 5px;-webkit-border-radius: 5px;}.gradients{  text-align:center;width:200px;line-height:60px;  background-&lt;mce:script type="text/javascript" mce_src="http://www.cnblogs.com/editor/tiny_mce/themes/advanced/langs/zh.js"&gt;&lt;/mce:script&gt;&lt;mce:script type="text/javascript" mce_src="http://www.cnblogs.com/editor/tiny_mce/plugins/insertCode/langs/zh.js"&gt;&lt;/mce:script&gt;&lt;mce:script type="text/javascript" mce_src="http://www.cnblogs.com/editor/tiny_mce/plugins/syntaxHighlighter/langs/zh.js"&gt;&lt;/mce:script&gt;&lt;mce:script type="text/javascript" mce_src="http://www.cnblogs.com/editor/tiny_mce/plugins/uploadImage/langs/zh.js"&gt;&lt;/mce:script&gt;&lt;mce:script type="text/javascript" mce_src="http://www.cnblogs.com/editor/tiny_mce/plugins/insertMusic/langs/zh.js"&gt;&lt;/mce:script&gt;image: -moz-linear-gradient(top, #BDD738, #7E9516);  background-image: -webkit-gradient(linear, left top, left bottom, from(#BDD738), to(#7E9516));  filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#BDD738,endColorstr=#7E9516);  -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#BDD738,endColorstr=#7E9516)";}.b_btn{padding:5px 10px;color: #fff!important;background:url(http://pic002.cnblogs.com/img/bearstar/201006/2010062420253961.png) repeat-x;text-decoration: none;font-weight: bold;}.b_btn:hover{background:url(http://pic002.cnblogs.com/img/bearstar/201006/2010062420254656.png) repeat-x;}.b_box_ie{text-align:center;width:200px;line-height:60px;background-color:#DBEAFF;position:relative;}.b_r{width:3px;height:3px;font-size:0;background:url(http://pic002.cnblogs.com/img/bearstar/201006/2010062419324216.gif) no-repeat;position:absolute;}.r_1{top:0;left:0;}.r_2{background-position:-3px 0;top:0;right:0;}.r_3{background-position:0 -3px;left:0;bottom:0;}.r_4{background-position:-3px -3px;bottom:0;right:0;}--&gt;&lt;/style&gt;&lt;p&gt;UI要求越来越高，界面越做越华丽，给我们开发人员带来的就是使用大量的背景图片，下面介绍一些通过css(不使用图片或少使用图片)来实现一些很常见的效果，&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;圆角效果&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 圆角用的越来越多，因为圆角确实好看，效果如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;img src="http://pic002.cnblogs.com/img/bearstar/201006/2010062416362898.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 要实现上面的圆角，一般切图是左，右(或上下)各切1个图片做背景，但这样做只适合固定宽度或高度的box,而且如果box背景不一样，图片需要另外切。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 现在很多浏览器都支持圆角的css，css3也支持，代码如下：&lt;/p&gt;    &lt;br/&gt;   .b_box{&lt;br/&gt;   text-align:center;width:200px;line-height:60px;&lt;br/&gt;   border:1px solid #C0C0C0;background-color:#DBEAFF;&lt;br/&gt;   /*firefox*/&lt;br/&gt;   -moz-border-radius: 5px;&lt;br/&gt;   /*css3*/&lt;br/&gt;   border-radius: 5px;&lt;br/&gt;   /*webkit*/&lt;br/&gt;    -webkit-border-radius: 5px;&lt;br/&gt;    }&lt;div style="padding-left: 30px;"&gt;效果：&lt;div class="b_box"&gt;CSS 小技巧&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;但IE9以下的版本都不支持圆角,所以上面的效果在ie9以下显示还是直角的.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;目前我们针对ie9以下的浏览器使用下面的方法实现，切1个透明的圆形图片(这个图片要求圆角内测是透明的，而外侧是不透明的)，用绝对定位来显示4个圆角，这样做的好处是只使用1个图片，即可以实现任何大小，任何背景颜色的box圆角，但缺点就是需要多余的HTML代码，代码如下：&lt;/p&gt;&amp;lt;style type="text/css"&amp;gt;&lt;br/&gt;.b_box_ie{&lt;br/&gt;text-align:center;width:200px;line-height:60px;&lt;br/&gt;background-color:#DBEAFF;&lt;br/&gt;position:relative;&lt;br/&gt;}&lt;br/&gt;.b_r{width:3px;height:3px;font-size:0;background:url(http://pic002.cnblogs.com/img/bearstar/201006/2010062419324216.gif) no-repeat;position:absolute;}&lt;br/&gt;.r_1{top:0;left:0;}&lt;br/&gt;.r_2{background-position:-3px 0;top:0;right:0;}&lt;br/&gt;.r_3{background-position:0 -3px;left:0;bottom:0;}&lt;br/&gt;.r_4{background-position:-3px -3px;bottom:0;right:0;}&lt;br/&gt;&amp;lt;style&amp;gt;&lt;br/&gt;&lt;br/&gt;&amp;lt;div class="b_box_ie"&amp;gt;&lt;br/&gt;CSS 小技巧&lt;br/&gt;&amp;lt;div class="b_r r_1"&amp;gt;&amp;lt;/div&amp;gt;&lt;br/&gt;&amp;lt;div class="b_r r_2"&amp;gt;&amp;lt;/div&amp;gt;&lt;br/&gt;&amp;lt;div class="b_r r_3"&amp;gt;&amp;lt;/div&amp;gt;&lt;br/&gt;&amp;lt;div class="b_r r_4"&amp;gt;&amp;lt;/div&amp;gt;&lt;br/&gt;&amp;lt;/div&amp;gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;因我切的图片是gif，而不是png，所以效果不太好看(不像真真的圆角)。效果如下：&lt;/p&gt;&lt;div style="padding-left: 30px;"&gt;&lt;div style="display: inline-block;" class="b_box_ie"&gt;CSS 小技巧&lt;div class="b_r r_1"&gt;&lt;/div&gt;&lt;div class="b_r r_2"&gt;&lt;/div&gt;&lt;div class="b_r r_3"&gt;&lt;/div&gt;&lt;div class="b_r r_4"&gt;&lt;/div&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp;&lt;div class="b_box_ie" style="background-color: #ccc; display: inline-block;"&gt;CSS 小技巧&lt;div class="b_r r_1"&gt;&lt;/div&gt;&lt;div class="b_r r_2"&gt;&lt;/div&gt;&lt;div class="b_r r_3"&gt;&lt;/div&gt;&lt;div class="b_r r_4"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;阴影效果&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;大家注意我签名的阴影效果，如果要实现这样的效果，使用图片，切图都很麻烦，让我们看看css如何实现吧，代码：&lt;/p&gt;.b_shadow{&lt;br/&gt;  height:60px;line-height:60px;&lt;br/&gt;  width:200px;border:1px solid #C0C0C0;background-color:#DBEAFF;&lt;br/&gt;  -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);&lt;br/&gt;  -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);&lt;br/&gt;  box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);&lt;br/&gt;  /*IE6,IE7语法*/&lt;br/&gt;  filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=5, OffY=5, Color='gray');&lt;br/&gt;  /*IE8语法,可恶的IE，不同的版本还要写的不一样*/&lt;br/&gt;  -ms-filter:"progid:DXImageTransform.Microsoft.dropshadow(OffX=5, OffY=5, Color='gray')"&lt;br/&gt;} &lt;br/&gt;&lt;style type="text/css"&gt;&lt;!----&gt;&lt;/style&gt;&lt;div style="padding-left: 30px;"&gt;结合圆角，实现效果如下：&lt;div&gt;&lt;div class="b_shadow"&gt;      CSS 小技巧   &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #0000ff;"&gt;注：针对IE的filter,再测试过程中发现必须加height和background-color,如果不设置height，则无阴影效果，如果不设置背景色，则阴影效果不是作用在box &amp;nbsp; &amp;nbsp; 上，而是在文字上，原因不是很清楚，有兴趣的同学可以自己测下。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;渐变效果：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 这个效果也应该也是用的最多的，这次先上效果：&lt;/p&gt;&lt;div style="padding-left: 30px;"&gt;&lt;div class="gradients"&gt;  CSS 小技巧&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;代码：&lt;/p&gt;.gradients{&lt;br/&gt;text-align:center;width:200px;line-height:60px;&lt;br/&gt;background-image: -moz-linear-gradient(top, #BDD738, #7E9516);&lt;br/&gt;background-image: -webkit-gradient(linear, left top, left bottom, from(#BDD738), to(#7E9516));&lt;br/&gt;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#BDD738,endColorstr=#7E9516);&lt;br/&gt;-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#BDD738,endColorstr=#7E9516)";&lt;br/&gt;}&lt;br/&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;按钮发光效果&lt;/strong&gt;：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 这个效果在我签名中的评论按钮实现了(我签名的效果没有考虑IE6,IE7)，大家看到那几个按钮，都有些发光效果，而且鼠标移上去也有效果，可能有人看到以为我用了很多图片，其实只用了2个png图片，1个图片是上半部分完全透明，下半部分半透明，另1个图片是上半部分半透明，下半部分完全透明。用这2个图片+背景色就可以实现所有按钮的发光效果。因为我的签名中使用data:image/png;base64嵌入的图片，所以不支持IE6,IE7。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; DEMO效果(该效果在IE6下看不出来，是因为没有对PNG进行处理)：&lt;/p&gt;&lt;div style="padding-left: 30px;"&gt;   &lt;a style="background-color: #2daebf;" href="javascript:void(0);" class="b_btn"&gt;精彩推荐&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;a style="background-color: #e33100;" href="javascript:void(0);" class="b_btn"&gt;水平一般&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 代码：&lt;/p&gt;&amp;lt;style&amp;gt;&lt;br/&gt;.b_btn{&lt;br/&gt;padding:5px 10px;color: #fff;&lt;br/&gt;background:url(http://pic002.cnblogs.com/img/bearstar/201006/2010062420253961.png) repeat-x;&lt;br/&gt;text-decoration: none;font-weight: bold;&lt;br/&gt;}&lt;br/&gt;.b_btn:hover{&lt;br/&gt;background:url(http://pic002.cnblogs.com/img/bearstar/201006/2010062420254656.png) repeat-x;&lt;br/&gt;}&lt;br/&gt;&amp;lt;/style&amp;gt;&lt;br/&gt;&amp;lt;a class="b_btn" href="javascript:void(0);" style="background-color:#2daebf;"&amp;gt;精彩推荐&amp;lt;/a&amp;gt;&amp;nbsp;&amp;nbsp;&lt;br/&gt;&amp;lt;a class="b_btn" href="javascript:void(0);" style="background-color:#e33100;"&amp;gt;水平一般&amp;lt;/a&amp;gt;&lt;br/&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #ff0000;"&gt;PS：本文中只是做一些简单的介绍，每种效果都没做很详细的说明，对于具体方法的使用，请大家自己查查资料。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #ff0000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #ff0000;"&gt;评论更新：本来设置个快捷评论，没想到很多朋友都随便点着玩，虽然赚去了很多评论数，但大部分都是无意义的评论，而不是技术交流的评论，所以决定把快捷评论关闭掉，并以后再也不启用该功能了。希望大家都用心交流。&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1764540.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/06/25/css_tip_round_gradients_shadow.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/BearsTaR/archive/2010/06/18/facebook_html_chunk.html</id><title type="text">名站技术分析 — facebook奇特的页面加载技术</title><summary type="text">  没事使用代理上了下facebook，注册进入个人首页后，习惯性的查看源代码，发现了1个很有意思的现象，首页内容不少，但源代码中HTML的代码却很少，但去多出了很多段的javascript代码，这些js代码都是用于动态生成html的，facebook为什么需要这样做了？出于职业习惯，研究研究：</summary><published>2010-06-18T00:51:00Z</published><updated>2010-06-18T00:51:00Z</updated><author><name>BearRui(AK-47)</name><uri>http://www.cnblogs.com/BearsTaR/</uri></author><link rel="alternate" href="http://www.cnblogs.com/BearsTaR/archive/2010/06/18/facebook_html_chunk.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/BearsTaR/archive/2010/06/18/facebook_html_chunk.html"/><content type="html">&lt;p&gt;没事使用代理上了下facebook，注册进入个人首页后，习惯性的查看源代码，发现了1个很有意思的现象，首页内容不少，但源代码中HTML的代码却很少，但去多出了很多段的javascript代码，这些js代码都是用于动态生成html的，facebook为什么需要这样做了？出于职业习惯，研究研究：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;一、html代码。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 先看看首页查看的源代码，因为源代码比较大，所以把图片压缩了下，可能看不太清楚，只需要注意图中红色是html代码，其余黑压压一片的就全部是JS代码：&lt;/p&gt;&lt;p&gt;&lt;img height="508" width="900" src="http://pic002.cnblogs.com/img/bearstar/201006/2010061221195229.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;二、JS代码&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 看到黑压压的JS代码是不是被吓一跳，下面就截取一段JS来分析(其余段的JS都是类似的)，facebook源代码中充斥了类似于下面的JS代码：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&amp;lt;script&amp;gt;&lt;br/&gt;big_pipe.onPageletArrive({&lt;br/&gt;"id":"pagelet_welcome_box","phase":1,"is_last":false,"append":false,"bootloadable":[],&lt;br/&gt;"css":["lDRwi","eon+N"],&lt;br/&gt;"js":["F+B8D","IdQlc"],&lt;br/&gt;"resource_map":[],"requires":[],"provides":[],&lt;br/&gt;"onload":["window.__UIControllerRegistry[\"c4c13a3ed2dd1e0e349b72\"] = new UIPagelet(\"c4c13a3ed2dd1e0e349b72\", \"\\\/pagelet\\\/generic.php\\\/WelcomeBoxPagelet\\\/\", {}, {});; ;"],&lt;br/&gt;"onafterload":[],"onpagecache":[],"onafterpagecache":[],"refresh_pagelets":[],"invalidate_cache":[],&lt;br/&gt;"content":{&lt;br/&gt;"pagelet_welcome_box":"&amp;lt;div id=\"c4c13a3ed2dd1e0e349b72\"&amp;gt;&amp;lt;div class=\"UIImageBlock clearfix fbxWelcomeBox\"&amp;gt; ...这里省略N多HTML"&lt;br/&gt;},&lt;br/&gt;"page_cache":true&lt;br/&gt;});&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;让我们再看看big_pipe.onPageletArrive函数到底做了什么了？我们只关注参数中的id,js,css,content4个参数，可以看出js和css都是进行过编码，下面是解码后我们关注的代码：&lt;/p&gt;&amp;lt;script&amp;gt;&lt;br/&gt;big_pipe.onPageletArrive({&lt;br/&gt;"id":"pagelet_welcome_box",&lt;br/&gt;"css":{&lt;br/&gt;name: "css/c5mv8gd5gwoc4kk0.pkg.css"&lt;br/&gt;permanent: true&lt;br/&gt;src: "http://static.ak.fbcdn.net/rsrc.php/zBP3B/hash/abee68r4.css"&lt;br/&gt;type: "css"&lt;br/&gt;},&lt;br/&gt;"js":{&lt;br/&gt;name: "js/19khsprwvtvokwow.pkg.js"&lt;br/&gt;permanent: false&lt;br/&gt;src: "http://static.ak.fbcdn.net/rsrc.php/zAVXU/hash/e8mwcqsi.js"&lt;br/&gt;type: "js"&lt;br/&gt;},&lt;br/&gt;"content":{&lt;br/&gt;"pagelet_welcome_box":"&amp;lt;div id=\"c4c13a3ed2dd1e0e349b72\"&amp;gt;&amp;lt;div class=\"UIImageBlock clearfix fbxWelcomeBox\"&amp;gt; ...这里省略N多HTML"&lt;br/&gt;}&lt;br/&gt;});&lt;br/&gt;&amp;lt;/script&amp;gt;&lt;br/&gt;&lt;p&gt;看到还原后的JS，你应该猜出onPageletArrive函数是干嘛的吧，其实onPageletArrive最主要实现就是把"content"中的html内容插入到对应id(上面的"pagelet_welcome_box")的html元素中,并下载对应的css和JS。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;三、chunk、flush&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;看到上面的分析后，大家一定奇怪，facebook为什么要生成那么多段JS，再用js去动态插入html代码，这不是脱了裤子放屁，多此一举吗？还不如直接生成html代码了。facebook当然不会那么笨了，让我们先监控下facebook的http请求，监控图如下：&lt;/p&gt;&lt;p&gt;&lt;img height="164" width="900" src="http://pic002.cnblogs.com/img/bearstar/201006/2010061710080535.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;注意上图中红色部分，原来facebook使用了chunk对页面进行分块输出。这就比较容易理解了，facebook首页的js代码段不是1次就全部输出的，而是一段一段进行输出的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;什么是chunk和如何使用chunk,请参考我的另1篇博文：&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/05/19/flush_chunk_encoding.html" target="_blank"&gt;flush让页面分块,逐步呈现&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; facebook使用chunk技术让页面分块输出成很多JS段，这样做的好处就是服务器和客户端可以并行进行处理，不用等服务器全部处理完毕，客户端才进行处理。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 举个博客园首页的列子，博客园首页分为下面几块("推荐博客排行","首页随笔列表","最新新闻"...),&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 我们一般对该http请求处理如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1. 浏览器发送http请求&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 2. 服务器处理请求(从缓存读取前50个推荐博客，从数据库读取"首页随笔列表",从数据库读取"最新新闻")，生成首页的html代码。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 3. 服务器发送html代码给客户端&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 4、浏览器接收到响应，处理html(下载css,js,image,执行js等等)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;可以看出传统的http请求4个过程中，每个过程都必须等待前1个过程完成后才能执行，这样就存在很大的资源浪费。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;facebook的对该http请求的处理如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1. 浏览器发送http请求&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2. 服务器处理请求(从缓存读取前50个推荐博客,生成"推荐博客"的js代码段，flush输出该代码段,&lt;/p&gt;&lt;p&gt;服务器继续读取"首页随笔列表"，并生成输入js代码段。&lt;/p&gt;&lt;p&gt;服务器继续读取"最新新闻"，并生成输入js代码段。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;3. 浏览器接收到js代码段，下载该代码段所需的js和css。插入html代码。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; 在这个处理流程中，最大的特点就是2,3是并行进行处理的，服务器处理完一部分数据就把已经处理好的数据交给浏览器进行呈现处理，自己再继续处理其他的数据。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #0000ff;"&gt;PS：文章看完了，有些同学可能会想，为什么不像博客园一样，前台全部用ajax来异步读取"推荐博客" ,&amp;ldquo;最新新闻&amp;rdquo;的数据了，这样做就不会出现因为要处理太多数据而让客户端等待太久的问题了。我觉得对于facebook这种并发量巨大的网站，使用这种方法无疑会产生太多的请求，比如facebook首页用了14个chunk，如果使用ajax，则需要多14个request请求，这将增加不少服务器的压力吧。&lt;/span&gt; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;相关文章： &lt;a target="_blank" href="http://www.cnblogs.com/BearsTaR/archive/2010/05/25/tudou_lazy_image.html"&gt;名站技术分析 &amp;mdash;&amp;nbsp;浅谈tudou.com首页图片延迟加载的效果&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/BearsTaR/aggbug/1757393.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/BearsTaR/archive/2010/06/18/facebook_html_chunk.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
