<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>裁纸刀下 &#187; 翻译</title>
	<atom:link href="http://ofcss.com/tags/translation/feed" rel="self" type="application/rss+xml" />
	<link>http://ofcss.com</link>
	<description>独立 自由 诚信 宽容 责任 平常心</description>
	<lastBuildDate>Thu, 19 Jan 2012 14:24:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>对《优化浏览器渲染》的补充【译】</title>
		<link>http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html</link>
		<comments>http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html#comments</comments>
		<pubDate>Mon, 14 Mar 2011 08:06:50 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html</guid>
		<description><![CDATA[<p>ISD Webteam的大布同学（twitter：@tc_bryanzhang）在2010年1月翻译了google Page Speed系列中的Optimize browser rendering，很是方便了大家。在此基础上，google又有了更新，我且在此把google新增的部分翻译一下，作为对大布同学译稿的补充。 google这篇文章关注的是资源被下载到客户端以后，在浏览器加载、解释、渲染HTML、CSS和JavaScript阶段的性能优化，提出了5个要点： 使用高效率的CSS选择器 避免CSS expressions 将样式表放在页面顶部 指定图像尺寸 尽早指定文档的字符编码 前四点大布同学已经翻译过了，没拜读过的同学可以点击上面的链接到涛哥的博客学习，第五点的翻译如下： 概述 为HTML文档尽早指定字符编码，可以让浏览器立刻开始执行脚本。 细节 HTML文档是作为带有字符编码信息的字节流序列在互联网中传送的。字符编码信息可以在随文档发送的HTTP响应头信息中指定，也可以在文档的HTML标签中指定。浏览器根据字符编码信息将字节流转换为显示在浏览器上的字符。如果不知道如何构造一个页面的字符，浏览器自然也不能正确地渲染页面。绝大部分浏览器在开始执行任何JavaScript代码或者绘制页面之前都要缓冲一定数量的字节流，缓冲的同时它们也要查找相关的字符编码设定（一个值得注意的例外是IE6/7/8）。 不同浏览器需要缓冲的字节流数量不同，另外如果找不到编码设定，各浏览器默认的编码也不同。但是不管哪一种浏览器，如果在已经缓冲了足够的字节流、开始渲染页面之后才发现指定的编码设定与其默认值不同，都会导致重新解析文档并重绘页面。如果编码的变化影响到了外部资源（例如css\js\media），浏览器甚至会重新对资源进行请求。 为了避免这些延迟，对任何超过1k（精确地说是1024字节，这是我们测试过的所有浏览器的最大缓冲限制）的HTML文档，要尽早指定字符编码。 建议 通过HTTP头信息或meta标签指定编码 为HTML文档指定编码设定有几种方式： 服务器端：通过web服务器的配置来指定编码参数，为所有text/html类型的文档指定带有正确编码信息的Content-Type头信息。例如 Content-Type: text/html;charset=UTF-8 客户端：在HTML代码中包含http-equiv=&#34;content-type&#34;的meta标签，并指定字符编码。例如 。 如果可能的话，为你的web服务器做指定字符编码的HTTP头信息配置。某些浏览器（例如Firefox）在执行JavaScript之前会用（比其它浏览器）更短的延迟缓冲来检查头信息中是否指定字符编码。这意味着它们可以跳过对HTML标签的检查，缩短缓冲的字节数和延迟时间。 把meta标签放在head区域的最前面 如果你不能对web服务器配置进行修改，又需要通过meta标签指定编码，要确保你用于指定编码的meta标签是文档中head标签的第一个子元素。浏览器会在文档的前1024字节中寻找字符编码参数，因此为了避免性能损耗，编码参数在文档头部越早出现越好（译注：在IE6以下的版本中，特定情况下，如果该meta标签不是head的第一个子元素，则会被忽略。具体触发情况尚未进行仔细测试，初步估计是与web服务器配置的默认编码或浏览器默认编码有关）。 始终指定文档类型 在浏览器开始检查字符编码设定前，它们必须先检测将被处理的文档是什么类型。如果没有在头信息或meta标签中指定文档类型（content-type），浏览器就会通过很复杂的算法去“嗅探”文档的类型。这个过程会造成额外的延迟，而且还会带来安全漏洞。 务必指定正确的字符编码 你在HTTP头信息或meta标签中指定的字符编码设置一定要和编辑HTML文档时的实际字符编码一致，这非常重要。另外，如果同时通过HTTP头信息和Meta标签两种方式指定了字符编码，它们一定要保持一致。否则浏览器发现两者相互矛盾，会造成页面渲染错误或者为了重绘页面而造成额外的延迟。有关这一点，你可以阅读HTML 4.01规范（英文）中的5.2节：字符编码（英文）。 扩展阅读 如果需要进一步了解content-type以及字符编码设定存在/缺少的不同情况下浏览器行为的细节，可以参阅以下资料（英文）： Page Speed &#8230; <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>ISD Webteam的大布同学（twitter：<a href="http://twitter.com/tc_bryanzhang">@tc_bryanzhang</a>）在2010年1月翻译了google Page Speed系列中的<a href="http://code.google.com/intl/zh-CN/speed/page-speed/docs/rendering.html">Optimize browser rendering</a>，很是方便了大家。在此基础上，google又有了更新，我且在此把google新增的部分翻译一下，作为对大布同学译稿的补充。</p>
<p>google这篇文章关注的是资源被下载到客户端以后，在浏览器加载、解释、渲染HTML、CSS和JavaScript阶段的性能优化，提出了5个要点：</p>
<ol>
<li><a href="http://www.99css.com/archives/275#UseEfficientCSSSelectors">使用高效率的CSS选择器</a> </li>
<li><a href="http://www.99css.com/archives/275#AvoidCSSExpressions">避免CSS expressions</a> </li>
<li><a href="http://www.99css.com/archives/275#PutCSSInHead">将样式表放在页面顶部</a> </li>
<li><a href="http://www.99css.com/archives/275#SpecifyImageDimensions">指定图像尺寸</a> </li>
<li>尽早指定文档的字符编码 </li>
</ol>
<p><span id="more-1084"></span>
<p>前四点大布同学已经翻译过了，没拜读过的同学可以点击上面的链接到涛哥的博客学习，第五点的翻译如下：</p>
<h4>概述</h4>
<p>为HTML文档尽早指定字符编码，可以让浏览器立刻开始执行脚本。</p>
<h4>细节</h4>
<p>HTML文档是作为带有字符编码信息的字节流序列在互联网中传送的。字符编码信息可以在随文档发送的HTTP响应头信息中指定，也可以在文档的HTML标签中指定。浏览器根据字符编码信息将字节流转换为显示在浏览器上的字符。如果不知道如何构造一个页面的字符，浏览器自然也不能正确地渲染页面。绝大部分浏览器在开始执行任何JavaScript代码或者绘制页面之前都要缓冲一定数量的字节流，缓冲的同时它们也要查找相关的字符编码设定（一个值得注意的例外是IE6/7/8）。</p>
<p>不同浏览器需要缓冲的字节流数量不同，另外如果找不到编码设定，各浏览器默认的编码也不同。但是不管哪一种浏览器，如果在已经缓冲了足够的字节流、开始渲染页面之后才发现指定的编码设定与其默认值不同，都会导致重新解析文档并重绘页面。如果编码的变化影响到了外部资源（例如css\js\media），浏览器甚至会重新对资源进行请求。</p>
<p>为了避免这些延迟，对任何超过1k（精确地说是1024字节，这是我们测试过的所有浏览器的最大缓冲限制）的HTML文档，要尽早指定字符编码。</p>
<h4>建议</h4>
<p><strong>通过HTTP头信息或meta标签指定编码</strong></p>
<dl style="margin-left: 2em">
<dt>为HTML文档指定编码设定有几种方式： </dt>
<dd style="margin-left: 2em">服务器端：通过web服务器的配置来指定编码参数，为所有text/html类型的文档指定带有正确编码信息的Content-Type头信息。例如 <font color="#9bbb59">Content-Type: text/html;charset=UTF-8</font> </dd>
<dd style="margin-left: 2em">客户端：在HTML代码中包含<font color="#9bbb59">http-equiv=&quot;content-type&quot;</font>的meta标签，并指定字符编码。例如 <meta content="text/html;charset=utf-8" http-equiv="Content-Type" />。 </dd>
</dl>
<p>如果可能的话，为你的web服务器做指定字符编码的HTTP头信息配置。某些浏览器（例如Firefox）在执行JavaScript之前会用（比其它浏览器）更短的延迟缓冲来检查头信息中是否指定字符编码。这意味着它们可以跳过对HTML标签的检查，缩短缓冲的字节数和延迟时间。</p>
<p><strong>把meta标签放在head区域的最前面</strong></p>
<p>如果你不能对web服务器配置进行修改，又需要通过meta标签指定编码，要确保你用于指定编码的meta标签是文档中head标签的第一个子元素。浏览器会在文档的前1024字节中寻找字符编码参数，因此为了避免性能损耗，编码参数在文档头部越早出现越好（译注：在IE6以下的版本中，特定情况下，如果该meta标签不是head的第一个子元素，则会被忽略。具体触发情况尚未进行仔细测试，初步估计是与web服务器配置的默认编码或浏览器默认编码有关）。</p>
<p><strong>始终指定文档类型</strong></p>
<p>在浏览器开始检查字符编码设定前，它们必须先检测将被处理的文档是什么类型。如果没有在头信息或meta标签中指定文档类型（content-type），浏览器就会通过很复杂的算法去“嗅探”文档的类型。这个过程会造成额外的延迟，而且还会带来安全漏洞。</p>
<p><strong>务必指定正确的字符编码</strong></p>
<p>你在HTTP头信息或meta标签中指定的字符编码设置一定要和编辑HTML文档时的实际字符编码一致，这非常重要。另外，如果同时通过HTTP头信息和Meta标签两种方式指定了字符编码，它们一定要保持一致。否则浏览器发现两者相互矛盾，会造成页面渲染错误或者为了重绘页面而造成额外的延迟。有关这一点，你可以阅读HTML 4.01规范（英文）中的5.2节：字符编码（英文）。</p>
<p><strong>扩展阅读</strong></p>
<p>如果需要进一步了解content-type以及字符编码设定存在/缺少的不同情况下浏览器行为的细节，可以参阅以下资料（英文）：</p>
<ul>
<li><a href="http://code.google.com/p/page-speed/wiki/SpecifyCharsetEarly" target="_blank">Page Speed wiki</a> </li>
<li><a href="http://zoompf.com/blog/2009/12/browser-performance-issues-with-charsets/" target="_blank">Browser Performance Issues with Charsets</a> </li>
<li><a href="http://www.kylescholz.com/blog/2010/01/performance_implications_of_charset.html" target="_blank">Performance Implications of &quot;charset&quot;</a> </li>
</ul>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2010-06-09 -- <a href="http://ofcss.com/2010/06/09/my-rencent-booklist.html" title="最近的书单">最近的书单</a></li><li>2009-06-22 -- <a href="http://ofcss.com/2009/06/22/whatever-hover-pseudo-class-without-javascript.html" title="Whatever:hover &#8211; 无需javascript让IE支持丰富伪类">Whatever:hover &#8211; 无需javascript让IE支持丰富伪类</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-22 -- <a href="http://ofcss.com/2010/10/22/the-value-of-html-validation-translation.html" title="HTML验证的价值探讨【译】">HTML验证的价值探讨【译】</a></li><li>2010-10-20 -- <a href="http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html" title="clearfix改良及overflow:hidden详解【译】">clearfix改良及overflow:hidden详解【译】</a></li><li>2009-12-21 -- <a href="http://ofcss.com/2009/12/21/web-developer-understand-css-box-model.html" title="前台开发从头说起：理解css盒模型">前台开发从头说起：理解css盒模型</a></li><li>2009-12-16 -- <a href="http://ofcss.com/2009/12/16/web-developer-about-css-selector.html" title="前台开发从头说起：谈谈CSS选择符">前台开发从头说起：谈谈CSS选择符</a></li><li>2009-12-15 -- <a href="http://ofcss.com/2009/12/15/web-developer-from-web-standard.html" title="前台开发从头说起：关于web标准化">前台开发从头说起：关于web标准化</a></li><li>2009-04-13 -- <a href="http://ofcss.com/2009/04/13/portable-interchangeable-jquery-based-tabs.html" title="简单、通用的JQuery Tab实现">简单、通用的JQuery Tab实现</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CSS边框实现&#8220;无图化&#8221;设计【译】</title>
		<link>http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html</link>
		<comments>http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html#comments</comments>
		<pubDate>Wed, 09 Mar 2011 16:41:21 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://ofcss.com/?p=1078</guid>
		<description><![CDATA[<p>原文：http://www.yuiblog.com/blog/2011/03/08/css-border-tricks-with-collapsed-boxes/ 译文：http://ofcss.com/?p=1078 作者：Thierry Koblentz （雅虎前端工程师） 用css边框实现小三角的技巧现在已经被越来越多的网站所采用，减少图片、减少HTTP请求的低碳设计越来越受欢迎。这次，来自雅虎的前端工程师又给我们带来了一组新的CSS边框设计技巧，原文列出了三种（双色背景导航条、水平排列元素间的点线分隔符、带左右箭头的垂直导航条），实际上除了这三种外，其范例页中还给出了额外的两种（水平分页导航条、垂直分组导航条）。以下是译文： 双色背景 原文并未直接给出IE6/7的处理说明，但是在范例页的样式中包含了IE6/7的Hack，这里我把它们摘出来放在下方，你也可以狠狠点击原文范例页面自行查看。 #menuBar-A { display: inline-block; text-align: center; border: 1px solid #cecece; } .child { display: inline-block; line-height: 0; height: 0; border-top: 1em solid #ffc; border-bottom: 1em solid #fdcf46; padding: 0 .6em; vertical-align: bottom; &#8230; <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>原文：<a href="http://www.yuiblog.com/blog/2011/03/08/css-border-tricks-with-collapsed-boxes/">http://www.yuiblog.com/blog/2011/03/08/css-border-tricks-with-collapsed-boxes/</a></p>
<p>译文：<a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">http://ofcss.com/?p=1078</a></p>
<p>作者：<em>Thierry Koblentz （雅虎前端工程师）</em></p>
<p>用css边框实现小三角的技巧现在已经被越来越多的网站所采用，减少图片、减少HTTP请求的低碳设计越来越受欢迎。这次，来自雅虎的前端工程师又给我们带来了一组新的CSS边框设计技巧，原文列出了三种（双色背景导航条、水平排列元素间的点线分隔符、带左右箭头的垂直导航条），实际上除了这三种外，其范例页中还给出了额外的两种（水平分页导航条、垂直分组导航条）。以下是译文：</p>
<p><span id="more-1078"></span><br />
<h4>双色背景</h4>
<p>原文并未直接给出IE6/7的处理说明，但是在范例页的样式中包含了IE6/7的Hack，这里我把它们摘出来放在下方，你也可以狠狠点击<a href="http://tjkdesign.com/Y!/YUIBlog/border_hacks/demo.html">原文范例页面</a>自行查看。</p>
<p align="center"><img title="bi-color-background" border="0" alt="bi-color-background" src="http://file.wukangrui.com/attachments/2011/03/bi-color-background.png"></p>
<pre style="background: #3f3f3f" class="code"><span style="color: #e3ceab">#menuBar-A </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">display</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">inline-block</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">text-align</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">center</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">border</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">1px solid #cecece</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">.child </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">display</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">inline-block</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">line-height</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">height</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">border-top</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">1em solid #ffc</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">border-bottom</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">1em solid #fdcf46</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">padding</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0 .6em</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">vertical-align</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">bottom</span><span style="color: #dcdccc">;
}</span><span></pre>
<pre style="background: #3f3f3f" class="code"><span style="color: #efef8f">&lt;</span><span style="color: #e3ceab">ul </span><span style="color: #dfdfbf">id</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"menuBar-A"</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">About Us</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">li </span><span style="color: #dfdfbf">class</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"selected"</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Contact Us</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Services</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Products</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
&lt;/</span><span style="color: #e3ceab">ul</span><span style="color: #efef8f">&gt;</span><span></pre>
<p></span><span></span>
<pre style="background: #3f3f3f" class="code"><span style="color: #7f9f7f">/*
 * IE6/7 Hacks
 * 用display:inline + zoom来模拟display:inline-block;
 * 基于IE对列表元素的样式渲染方式，不能对其使用垂直边框，因此用它的背景色代替 */
</span><span style="color: #e3ceab">#menuBar-A </span><span style="color: #dcdccc">{
    #</span><span style="color: #c3bf9f">display</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">inline</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">zoom</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">1</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">padding</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">1px 0 1px 1px</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">background</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">#BD9E43</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-A li </span><span style="color: #dcdccc">{
    #</span><span style="color: #c3bf9f">background</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">#ffc</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">margin-right</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">1px</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border-bottom</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">1em solid #fdcf46</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-A a </span><span style="color: #dcdccc">{
    #</span><span style="color: #c3bf9f">line-height</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">1</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">position</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">relative</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">top</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">-.65em</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">_top</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">.3em</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-A li:hover a </span><span style="color: #dcdccc">{
    #</span><span style="color: #c3bf9f">color</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">#fff</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-A a:hover</span><span style="color: #dcdccc">,
</span><span style="color: #e3ceab">#menuBar-A a:active </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">_color</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">#333</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-A .selected</span><span style="color: #dcdccc">,
</span><span style="color: #e3ceab">#menuBar-A li:hover </span><span style="color: #dcdccc">{
    #</span><span style="color: #c3bf9f">background</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">#c789d9</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border-bottom-color</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">#83358B</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-A .selected a:hover</span><span style="color: #dcdccc">, {
    #</span><span style="color: #c3bf9f">color</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">#fff</span><span style="color: #dcdccc">;
}</span><span></pre>
<p></span><br />
<h4>列表元素之间的点/线分隔符</h4>
<p>这个例子只需要做少量的IE Hack就可以完美实现跨浏览器兼容。
<p align="center"><img title="dots-and-pipes" border="0" alt="dots-and-pipes" src="http://file.wukangrui.com/attachments/2011/03/dots-and-pipes.png" width="458" height="67"></p>
<pre style="background: #3f3f3f" class="code"><span style="color: #e3ceab">ul.one</span><span style="color: #dcdccc">, </span><span style="color: #e3ceab">ul.two </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">margin-left</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">display</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">inline-block</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">display</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">inline</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">zoom</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">1</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">height</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">12px</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">line-height</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">12px</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">padding</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
}

</span><span style="color: #e3ceab">li </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">float</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">left</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">display</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">inline</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">height</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">2px</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">line-height</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">2px</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">position</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">relative</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">top</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">.3em</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">li.selected </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">font-weight</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">bold</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">ul.two </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">border-left</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">1px solid #333</span><span style="color: #dcdccc">;
}

</span><span style="color: #e3ceab">ul.one li </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">border-left</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">2px solid #333</span><span style="color: #dcdccc">;
}

</span><span style="color: #e3ceab">ul.two li </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">border-right</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">2px solid #333</span><span style="color: #dcdccc">;
}

</span><span style="color: #e3ceab">ul.one li.first-child</span><span style="color: #dcdccc">, </span><span style="color: #e3ceab">ul.two li.last-child </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">border</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
}

</span><span style="color: #e3ceab">a </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">color</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">#000</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">padding</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">.4em .9em</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">position</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">relative</span><span style="color: #dcdccc">;
}</span><span></pre>
<p></span><span><span></span>
<pre style="background: #3f3f3f" class="code"><span style="color: #efef8f">&lt;</span><span style="color: #e3ceab">div </span><span style="color: #dfdfbf">id</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"menuBar-B"</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">ul </span><span style="color: #dfdfbf">class</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"one"</span><span style="color: #efef8f">&gt;
        &lt;</span><span style="color: #e3ceab">li </span><span style="color: #dfdfbf">class</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"first-child"</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">About Us</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
        &lt;</span><span style="color: #e3ceab">li </span><span style="color: #dfdfbf">class</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"selected"</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Contact Us</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
    &lt;/</span><span style="color: #e3ceab">ul</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">ul </span><span style="color: #dfdfbf">class</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"two"</span><span style="color: #efef8f">&gt;
        &lt;</span><span style="color: #e3ceab">li </span><span style="color: #dfdfbf">class</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"last-child"</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Services</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
        &lt;</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Products</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
    &lt;/</span><span style="color: #e3ceab">ul</span><span style="color: #efef8f">&gt;
&lt;/</span><span style="color: #e3ceab">div</span><span style="color: #efef8f">&gt;</span><span></pre>
<p></span><br />
<h4>左右三角图标</h4>
<p>原文并未直接给出IE6/7的处理说明，但是在范例页的样式中包含了IE6/7的Hack，这里我把它们摘出来放在下方，你也可以狠狠点击<a href="http://tjkdesign.com/Y!/YUIBlog/border_hacks/demo.html">原文范例页面</a>自行查看。
<p align="center"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="left-and-right-triangles" border="0" alt="left-and-right-triangles" src="http://file.wukangrui.com/attachments/2011/03/left-and-right-triangles.png" width="193" height="157"></p>
<pre style="background: #3f3f3f" class="code"><span style="color: #e3ceab">#box </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">line-height</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">height</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">border</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">.4em solid transparent</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">border-left-color</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">#333</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">border-right-color</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">#333</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">padding</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0 .3em</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">display</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">inline-block</span><span style="color: #dcdccc">;
}</span></pre>
<pre style="background: #3f3f3f" class="code"><span style="color: #efef8f">&lt;</span><span style="color: #e3ceab">ul </span><span style="color: #dfdfbf">id</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"menuBar-C"</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">About Us</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">li </span><span style="color: #dfdfbf">class</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"selected"</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Contact Us</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Services</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
    &lt;</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;&lt;</span><span style="color: #e3ceab">a </span><span style="color: #dfdfbf">href</span><span style="color: #efef8f">=</span><span style="color: #cc9393">"#"</span><span style="color: #efef8f">&gt;</span><span style="color: #dcdccc">Products</span><span style="color: #efef8f">&lt;/</span><span style="color: #e3ceab">a</span><span style="color: #efef8f">&gt;&lt;/</span><span style="color: #e3ceab">li</span><span style="color: #efef8f">&gt;
&lt;/</span><span style="color: #e3ceab">ul</span><span style="color: #efef8f">&gt;</span></pre>
<pre style="background: #3f3f3f" class="code"><span style="color: #7f9f7f">/* IE6/7 Hacks */
</span><span style="color: #e3ceab">#menuBar-C </span><span style="color: #dcdccc">{
    #</span><span style="color: #c3bf9f">display</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">inline</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">zoom</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">1</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">width</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">10em</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-C li </span><span style="color: #dcdccc">{
    #</span><span style="color: #c3bf9f">padding</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">margin</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">.4em</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">list-style-type</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">none</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">height</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border-top</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">.4em solid #fff</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border-bottom</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">.4em solid #fff</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border-left</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">.4em solid #2F2876</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">border-right</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">.4em solid #2F2876</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">_position</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">relative</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-C a</span><span style="color: #dcdccc"> {
    #</span><span style="color: #c3bf9f">border</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">height</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">auto</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">line-height</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">1</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">top</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">-.4em</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">position</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">relative</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">_position</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">absolute</span><span style="color: #dcdccc">;
    #</span><span style="color: #c3bf9f">left</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">-.4em</span><span style="color: #dcdccc">;
}
</span><span style="color: #e3ceab">#menuBar-C li:hover</span><span style="color: #dcdccc"> {
    #</span><span style="color: #c3bf9f">border-left</span><span style="color: #dcdccc">:</span><span style="color: #dfdfbf">.4em solid #f60</span><span style="color: #dcdccc">;
}</span><span></pre>
<p></span><br />
<h4>IE6与透明边框</h4>
<p>IE6不支持用于边框颜色的“transparent”关键字。如果在IE6下指定边框颜色为透明（transparent），IE6将会绘制成黑色边框。
<p>解决办法是使用 <a href="http://msdn.microsoft.com/zh-cn/library/ms532982(VS.85).aspx">chroma filter</a>，它可以让对象内容中的指定颜色显示为透明色（译者注：针对IE6，还有其它的解决办法，参见<a href="http://www.99css.com/?p=15">IE 6 的边框不透明 bug</a>）。例如，创建一个向右箭头，可以这样做：
<pre style="background: #3f3f3f" class="code"><span style="color: #e3ceab">#Box </span><span style="color: #dcdccc">{
    </span><span style="color: #c3bf9f">height</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">width</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">border</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">10px solid transparent</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">font-size</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">0</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">_border-color</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">pink</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">_filter</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">chroma(color="pink")</span><span style="color: #dcdccc">;
    </span><span style="color: #c3bf9f">border-left-color</span><span style="color: #dcdccc">: </span><span style="color: #dfdfbf">#333</span><span style="color: #dcdccc">;
}</span></pre>
<p>规则中的font-size的定义是为了解决IE6下自动撑开元素高度的问题。<br />
<h4>译注：</h4>
<ol>
<li>原文给出的css样式和html结构不对应，在译文中已做修正。
<li>原文作者对IE6/7的注释采用两种方式：*号引导属性名、以及规则最后一个选择符带逗号，在译文中我统一使用了#号引导属性名的方式。为了部分原来不清楚这些hacks方式的读者，下面再把作为本文背景知识的IE6/7、IE6 Hacks符号简单说明一下：
<ul>
<li>IE6/7 均支持以“*”号、“#”号引导的属性名称，其它浏览器不支持。因此，针对IE6/7的Hack可以写为：<br /><font color="#ff0000">#</font>zoom:1或<font color="#ff0000">*</font>zoom:1
<li>IE6/7 均支持最后一个选择符后面跟逗号的规则，其它浏览器不支持。因此，针对IE6/7的Hack也可以写为：<br />.selector<font color="#ff0000">, </font>{zoom:1}
<li>IE6 支持以下划线引导的属性名，其它浏览器不支持。因此，针对IE6的Hack可以写为：<br /><font color="#ff0000">_</font>width:600px;</li>
</ul>
</li>
</ol>
<p>以上只是用边框实现“无图化”设计的众多技巧中的一小部分，实际上我们还可以做得更多。如果有兴趣，你可以继续阅读：
<p>《<a href="http://www.99css.com/archives/146">自适应圆角</a>》
<p>《<a href="http://www.zhangxinxu.com/wordpress/?p=794">CSS Border三角、圆角图形生成技巧</a>》</p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2011-03-20 -- <a href="http://ofcss.com/2011/03/20/misunderstood-of-overflow-hidden.html" title="容易被误解的overflow:hidden">容易被误解的overflow:hidden</a></li><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2011-03-12 -- <a href="http://ofcss.com/2011/03/12/flexible-two-column-layout-reloaded.html" title="自适应的多列图文混排改进">自适应的多列图文混排改进</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-20 -- <a href="http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html" title="clearfix改良及overflow:hidden详解【译】">clearfix改良及overflow:hidden详解【译】</a></li><li>2009-06-22 -- <a href="http://ofcss.com/2009/06/22/whatever-hover-pseudo-class-without-javascript.html" title="Whatever:hover &#8211; 无需javascript让IE支持丰富伪类">Whatever:hover &#8211; 无需javascript让IE支持丰富伪类</a></li><li>2011-05-26 -- <a href="http://ofcss.com/2011/05/26/css-cascade-specificity.html" title="深入解析CSS样式层叠权重值">深入解析CSS样式层叠权重值</a></li><li>2011-03-07 -- <a href="http://ofcss.com/2011/03/07/ie8-compatibility-settings.html" title="IE8/9兼容性设置">IE8/9兼容性设置</a></li><li>2011-03-04 -- <a href="http://ofcss.com/2011/03/04/the-hacktastic-zoom-fix-translation.html" title="在非IE浏览器中模拟zoom创建块级上下文【译】">在非IE浏览器中模拟zoom创建块级上下文【译】</a></li><li>2010-10-30 -- <a href="http://ofcss.com/2010/10/30/bfc-element-margin-bug-in-webkit.html" title="webkit中BFC元素临近浮动元素时的边距bug">webkit中BFC元素临近浮动元素时的边距bug</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</title>
		<link>http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html</link>
		<comments>http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html#comments</comments>
		<pubDate>Sun, 31 Oct 2010 14:05:04 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[浏览器]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html</guid>
		<description><![CDATA[<p>原文：http://www.yuiblog.com/?p=2820 译文：http://ofcss.com/?p=1028 作者：Thierry Koblentz 尽管这种情况通常被称为&#34;浮动下坠&#34;或者&#34;浮动下沉&#34;,但实际上下坠或下沉的列并不一定是浮动的……只要它比预留给它的空间更宽就有可能出现下沉。请记住这是一种特定情况下才会发生的在跨浏览器时很常见的行为——网页的某一栏太宽了，于是它下沉了。 IE 6的问题之所以突出，是因为它对 width 这个属性的支持不完整（height 也好不到哪里去）。因此，IE 6会让容器扩展以适应内容。而为这个容器设计的宽度却没法随之变宽，于是IE 6对容器宽度的自动扩展就造成了它的下沉。 通常情况下，罪魁祸首是那些无法包围的元素（比如图片、url等），但是文字样式（例如 IE 和 斜体）也有可能造成这种情况。 例如，要让YUIBlog的右栏在IE 6中下沉，我只需要让右栏中的某个图片的宽度大于210px。这张图将会强迫IE 6增加右栏的宽度，这样右栏就无法再保持在左栏旁边了。 常见修复方法： word-wrap: break-word;//强制文字截断（译注：主要针对非双字节语言，把单词强制截断）。 wbr with wbr:after {content:&#34;\00200B&#34;}; //针对 Opera，wbr属性代表行截断的机会。在长文字中添加wbr以便在必要时允许浏览器换行。 overflow-x:hidden;//隐藏溢出容器的所有内容。 要注意的是前两种方式只适用于文字，不能放置图片撑开容器。 已知会导致修复失败的情况 几周前，我遇到要为yahoo!财经的页面修复“浮动下沉”的bug。在现代浏览器中，一行长文字超出了容器显示在容器右侧外部（查看截图），但是在IE 6下，同样的文字造成了右栏下沉到主栏下方（查看截图）。麻烦的是，这部分内容是由外部提供，因此没办法对HTML代码进行修改。 由于这行文字是一组由逗号分隔的标签列表，因此之前提到的几种修复方法都不能满足需要。在这行文字内部任意位置强行截断当然比隐藏溢出部分要好，但这也不是可行的解决方案。 让IE 6正常显示 要让IE 6像其它现代浏览器一样显示这行文字，方法是给文字的容器的右边距设置一个负值（同时还要设置相对定义position:relative）。 效果演示 没有修正时 &#8230; <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>原文：<a href="http://www.yuiblog.com/?p=2820">http://www.yuiblog.com/?p=2820</a></p>
<p>译文：<a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">http://ofcss.com/?p=1028</a></p>
<p>作者：Thierry Koblentz</p>
<p>尽管这种情况通常被称为&quot;<a href="http://www.positioniseverything.net/explorer/expandingboxbug.html">浮动下坠</a>&quot;或者&quot;浮动下沉&quot;,但实际上下坠或下沉的列并不一定是浮动的……只要它比预留给它的空间更宽就有可能出现下沉。请记住这是一种特定情况下才会发生的在跨浏览器时很常见的行为——网页的某一栏太宽了，于是它下沉了。</p>
<p>  <span id="more-1028"></span>
<p>IE 6的问题之所以突出，是因为它对 width 这个属性的支持不完整（height 也好不到哪里去）。因此，IE 6会让容器扩展以适应内容。而为这个容器设计的宽度却没法随之变宽，于是IE 6对容器宽度的自动扩展就造成了它的下沉。</p>
<p>通常情况下，罪魁祸首是那些无法包围的元素（比如图片、url等），但是文字样式（例如 <a href="http://www.positioniseverything.net/explorer/italicbug-ie.html">IE 和 斜体</a>）也有可能造成这种情况。</p>
<p>例如，要让<a href="http://yuiblog.com/">YUIBlog</a>的右栏在IE 6中下沉，我只需要让右栏中的某个图片的宽度大于210px。这张图将会强迫IE 6增加右栏的宽度，这样右栏就无法再保持在左栏旁边了。</p>
<p align="center"><a href="http://file.wukangrui.com/attachments/2010/10/column-drop.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="column-drop" border="0" alt="column-drop" src="http://file.wukangrui.com/attachments/2010/10/column-drop_thumb.png" width="496" height="500" /></a></p>
<h4>常见修复方法：</h4>
<ul>
<li><code>word-wrap: break-word;</code>//强制文字截断（译注：主要针对非双字节语言，把单词强制截断）。 </li>
<li><code>wbr with wbr:after {content:&quot;\00200B&quot;};</code> //针对 Opera，wbr属性代表行截断的机会。在长文字中添加wbr以便在必要时允许浏览器换行。 </li>
<li><code>overflow-x:hidden;//</code>隐藏溢出容器的所有内容。</li>
</ul>
<p>要注意的是前两种方式只适用于文字，不能放置图片撑开容器。</p>
<h4>已知会导致修复失败的情况</h4>
<p>几周前，我遇到要为yahoo!财经的页面修复“浮动下沉”的bug。在现代浏览器中，一行长文字超出了容器显示在容器右侧外部（<a href="http://yuiblog.com/assets/dropfloat/modern-browsers.png">查看截图</a>），但是在IE 6下，同样的文字造成了右栏下沉到主栏下方（<a href="http://yuiblog.com/assets/dropfloat/ie6.png">查看截图</a>）。麻烦的是，这部分内容是由外部提供，因此没办法对HTML代码进行修改。</p>
<p>由于这行文字是一组由逗号分隔的标签列表，因此之前提到的几种修复方法都不能满足需要。在这行文字内部任意位置强行截断当然比隐藏溢出部分要好，但这也不是可行的解决方案。</p>
<h4>让IE 6正常显示</h4>
<p>要让IE 6像其它现代浏览器一样显示这行文字，方法是给文字的容器的右边距设置一个<strong>负值</strong>（同时还要设置相对定义position:relative）。</p>
<h4>效果演示</h4>
<p><strong>没有修正时</strong></p>
<p align="center"><a href="http://file.wukangrui.com/attachments/2010/10/demo-1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="demo-1" border="0" alt="demo-1" src="http://file.wukangrui.com/attachments/2010/10/demo-1_thumb.png" width="425" height="340" /></a></p>
<p><strong>fix 修正以后</strong></p>
<p align="center"><a href="http://file.wukangrui.com/attachments/2010/10/demo-2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="demo-2" border="0" alt="demo-2" src="http://file.wukangrui.com/attachments/2010/10/demo-2_thumb.png" width="510" height="183" /></a></p>
<p><strong>代码示例：</strong></p>
<pre><code>.fixMe {
  margin-right:-100px;
  position:relative;
}
</code></pre>
<p>负边距可以设置为任意大的值，只要大于实际所需宽度和指定宽度的差值即可。这就是我所说的放置浮动下沉的方法。设置相对定位（position:relative）的目的是让IE能够显示超出了父元素边缘的内容。</p>
<h4>Things to consider 补充说明</h4>
<p>这个hack能保证每一栏都呆在应该在的位置上，但是无法阻止溢出内容的容器变宽。因此你不能在该容器上应用背景或者边框样式，否则这些样式都会显示到父元素外部。下面有个截图，演示了在IE 6下使用这个方法同时设置边框和背景的效果：</p>
<p align="center"><a href="http://file.wukangrui.com/attachments/2010/10/demo-with-background.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="demo-with-background" border="0" alt="demo-with-background" src="http://file.wukangrui.com/attachments/2010/10/demo-with-background_thumb.png" width="509" height="200" /></a></p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-30 -- <a href="http://ofcss.com/2010/10/30/bfc-element-margin-bug-in-webkit.html" title="webkit中BFC元素临近浮动元素时的边距bug">webkit中BFC元素临近浮动元素时的边距bug</a></li><li>2010-10-20 -- <a href="http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html" title="clearfix改良及overflow:hidden详解【译】">clearfix改良及overflow:hidden详解【译】</a></li><li>2009-06-22 -- <a href="http://ofcss.com/2009/06/22/whatever-hover-pseudo-class-without-javascript.html" title="Whatever:hover &#8211; 无需javascript让IE支持丰富伪类">Whatever:hover &#8211; 无需javascript让IE支持丰富伪类</a></li><li>2011-05-26 -- <a href="http://ofcss.com/2011/05/26/css-cascade-specificity.html" title="深入解析CSS样式层叠权重值">深入解析CSS样式层叠权重值</a></li><li>2011-03-20 -- <a href="http://ofcss.com/2011/03/20/misunderstood-of-overflow-hidden.html" title="容易被误解的overflow:hidden">容易被误解的overflow:hidden</a></li><li>2011-03-12 -- <a href="http://ofcss.com/2011/03/12/flexible-two-column-layout-reloaded.html" title="自适应的多列图文混排改进">自适应的多列图文混排改进</a></li><li>2011-03-07 -- <a href="http://ofcss.com/2011/03/07/ie8-compatibility-settings.html" title="IE8/9兼容性设置">IE8/9兼容性设置</a></li><li>2011-03-04 -- <a href="http://ofcss.com/2011/03/04/the-hacktastic-zoom-fix-translation.html" title="在非IE浏览器中模拟zoom创建块级上下文【译】">在非IE浏览器中模拟zoom创建块级上下文【译】</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】</title>
		<link>http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html</link>
		<comments>http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html#comments</comments>
		<pubDate>Mon, 25 Oct 2010 12:09:41 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[Google Analytics]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[交互研究]]></category>
		<category><![CDATA[用户行为]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://ofcss.com/?p=990</guid>
		<description><![CDATA[<p>作者:Brian Cray 原文:http://briancray.com/?p=1584 【作者简介】Brian Cray 居住在俄亥俄州的哥伦布市，是位于圣弗朗西斯科的Topsy公司的一名前端工程师。 本文主要介绍如何使用谷歌分析的高级事件跟踪能力，深入了解用户如何浏览你的网站、如何与你的网页进行交互。 =========== 以下为译文正文=============== Google分析服务的设置，对于访问者浏览行为和偏好的信息，仅记录和分析了他们的来路和被访问的页面。但这些信息就足够告诉你访问者在网页中的用户行为了吗？不够！这些只是帮助我们分析用户行为的最基础的信息。 我想请你根据你目前的Google分析的设定回答以下问题： 你的用户是通过主菜单还是通过其它方式来查找你站内的内容？ 你的用户在查看较长的页面时向下滚动和点击底部的链接吗？ 你的用户是点击文章的标题还是点击“查看详情”链接？ 你的用户真的会使用下拉菜单里的项目吗？还是根本没注意到下拉菜单？ 你的用户接受你建议的的相关文章吗？ 现在让我来帮助你回答其中的一部分问题 借助Google分析服务的事件追踪，可以跟踪在你网页上发生的任意事件——包括用户的行为。 在开始之前，有两个重要步骤需要先做： 把你的Google分析的跟踪代码改为异步跟踪的代码。 把jQuery代码移到页面的&#60;head&#62;标签里（我知道，这是违背优化标准的，但是如果你使用良好的缓存技术的话，后面的数据回报是绝对值得你这样做的）。 代码 把以下代码添加到你的网页的&#60;head&#62;标签中或者你当前的jQuery代码中（只有该代码在&#60;head&#62;标签中时才可以）。 $(function () { $(&#8216;a&#8217;).click(function () { // 通知分析服务存储事件 try { _gaq.push(['_trackEvent', thisel.parents('[id!=&#34;&#34;]:first&#8217;).get(0).id, &#8216;clicked&#8217;, (thisel.text() &#124;&#124; thisel.children(&#8216;img:first&#8217;).attr(&#8216;alt&#8217;))]); } &#8230; <a href="http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>作者:<a href="http://briancray.com/" rel="tag">Brian Cray</a></p>
<p>原文:<a href="http://briancray.com/?p=1584">http://briancray.com/?p=1584</a></p>
<p>【作者简介】Brian Cray 居住在俄亥俄州的哥伦布市，是位于圣弗朗西斯科的<a href="http://www.google.com/url?q=http%3A%2F%2Ftopsy.com%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFHGPfLgD2N7e35m-6aqFDYAa1BQg">Topsy</a>公司的一名前端工程师。</p>
<p>本文主要介绍如何使用谷歌分析的高级事件跟踪能力，深入了解用户如何浏览你的网站、如何与你的网页进行交互。</p>
<p>  <span id="more-990"></span>
<p>=========== 以下为译文正文===============</p>
<p>Google分析服务的设置，对于访问者浏览行为和偏好的信息，仅记录和分析了他们的来路和被访问的页面。但这些信息就<strong>足够</strong>告诉你访问者<strong>在网页中</strong>的用户行为了吗？不够！这些只是帮助我们分析用户行为的最基础的信息。</p>
<h4>我想请你根据你目前的Google分析的设定回答以下问题：</h4>
<ul>
<li>你的用户是通过主菜单还是通过其它方式来查找你站内的内容？ </li>
<li>你的用户在查看较长的页面时向下滚动和点击底部的链接吗？ </li>
<li>你的用户是点击文章的标题还是点击“查看详情”链接？ </li>
<li>你的用户真的会使用下拉菜单里的项目吗？还是根本没注意到下拉菜单？ </li>
<li>你的用户接受你建议的的相关文章吗？ </li>
</ul>
<p align="center"><a href="http://file.wukangrui.com/attachments/2010/10/b01.png"><img title="b01" border="0" alt="b01" src="http://file.wukangrui.com/attachments/2010/10/b01_thumb.png" /></a></p>
<h4>现在让我来帮助你回答其中的一部分问题</h4>
<p>借助Google分析服务的<a href="http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html" rel="tag">事件追踪</a>，可以跟踪<strong>在你网页上</strong>发生的任意事件——包括用户的行为。</p>
<p>在开始之前，有两个<strong>重要步骤</strong>需要先做：</p>
<ul>
<li>把你的Google分析的跟踪代码改为<a href="http://www.google.com/url?q=http%3A%2F%2Fbriancray.com%2F2009%2F12%2F20%2Fasynchronous-tracking-google-analytics%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNHnPBbNLRha5QZAMMkJD0S7CLqg4w">异步跟踪</a>的代码。</li>
<li>把<a href="http://www.google.com/url?q=http%3A%2F%2Fjquery.com%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGtx3hYIQpONgUoQvrnRm8YULAPpA">jQuery</a>代码移到页面的&lt;head&gt;标签里（我知道，这是违背<a href="http://www.google.com/url?q=http%3A%2F%2Fdeveloper.yahoo.com%2Fperformance%2Frules.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNG29Nlpb9nSQXhNjB5G0ZMVzCnnYA">优化标准</a>的，但是如果你使用<a href="http://www.google.com/url?q=http%3A%2F%2Fwww.mnot.net%2Fcache_docs%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFnJ-X7s5Ux_3Kg822gi-DVc5X6vg">良好的缓存技术</a>的话，后面的数据回报是绝对值得你这样做的）。</li>
</ul>
<h4>代码</h4>
<p>把以下代码添加到你的网页的&lt;head&gt;标签中或者你当前的jQuery代码中（只有该代码在&lt;head&gt;标签中时才可以）。</p>
<pre class="code">$(<span style="color: blue">function </span>() {
    $(<span style="color: maroon">'a'</span>).click(<span style="color: blue">function </span>() {
    <span style="color: #006400">// 通知分析服务存储事件
        </span><span style="color: blue">try </span>{
            _gaq.push([<span style="color: maroon">'_trackEvent'</span>, thisel.parents(<span style="color: maroon">'[id!=&quot;&quot;]:first'</span>).get(0).id, <span style="color: maroon">'clicked'</span>, (thisel.text() || thisel.children(<span style="color: maroon">'img:first'</span>).attr(<span style="color: maroon">'alt'</span>))]);
        }
        <span style="color: blue">catch </span>(err) { }

        <span style="color: #006400">// pause to allow google script to run
        </span><span style="color: blue">var </span>date = <span style="color: blue">new </span>Date();
        <span style="color: blue">var </span>curDate = <span style="color: blue">null</span>;
        <span style="color: blue">do </span>{
            curDate = <span style="color: blue">new </span>Date();
        } <span style="color: blue">while </span>(curDate - date &lt; 300);
    });
});</pre>
<h4>添加代码后对事件按分类查看的截图</h4>
<p>在添加以上的代码后，可以看到网站的那些部分被点击得最多（基于元素的id属性或者父元素）。</p>
<p align="center"><a href="http://file.wukangrui.com/attachments/2010/10/b02.png"><img title="b02" border="0" alt="b02" src="http://file.wukangrui.com/attachments/2010/10/b02_thumb.png" /></a></p>
<h4>添加代码后对事件按标签查看的截图</h4>
<p>在添加以上的代码后，从左边的下拉菜单中选择某一个事件分类，可以看到被点击过的链接的标题，例如下图中能够看到的菜单项中的链接文字。</p>
<p align="center"><a href="http://file.wukangrui.com/attachments/2010/10/b03.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="b03" border="0" alt="b03" src="http://file.wukangrui.com/attachments/2010/10/b03_thumb.png" width="384" height="347" /></a></p>
<h4>通过事件追踪获得有关用户行为分析的更多信息</h4>
<p>前面所讲的，只是对这个强大技术的一点点入门介绍。借助用户行为分析方面的知识和恰当的jQuery技术，你还能以更丰富、更深入的方式使用它。例如：</p>
<ul>
<li>追踪用户的表单行为和鼠标行为。</li>
<li>追踪用户的操作和操作之间的时间。</li>
<li>改变设计，然后观察这些改变如何影响用户的行为（类似于A/B测试）。</li>
</ul>
<p><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.fabianpimminger.com%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNGInfju6T5mo3B-vh31v-9z8zYJMw">Fabian Pimminge</a> 已经在 MooTools 上重写了这些代码，如果你使用的是 MoonTools 框架，可以参考<a href="http://www.google.com/url?q=http%3A%2F%2Fwww.fabianpimminger.com%2Fweb-development%2Ftracking-user-behaviour-with-google-analytics-event-tracking-and-mootools%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNH5eKmcjT9OZjWLPCSVIUjC0x4m0A" rel="tag">这篇文章</a>。</p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-22 -- <a href="http://ofcss.com/2010/10/22/the-value-of-html-validation-translation.html" title="HTML验证的价值探讨【译】">HTML验证的价值探讨【译】</a></li><li>2010-10-20 -- <a href="http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html" title="clearfix改良及overflow:hidden详解【译】">clearfix改良及overflow:hidden详解【译】</a></li><li>2009-07-08 -- <a href="http://ofcss.com/2009/07/08/asp-net-mvc-best-practices-part-4.html" title="ASP.NET MVC 最佳实践（四）">ASP.NET MVC 最佳实践（四）</a></li><li>2009-07-07 -- <a href="http://ofcss.com/2009/07/07/asp-net-mvc-best-practices-part-3.html" title="ASP.NET MVC 最佳实践（三）">ASP.NET MVC 最佳实践（三）</a></li><li>2009-07-01 -- <a href="http://ofcss.com/2009/07/01/asp-net-mvc-best-practices-part-2.html" title="ASP.NET MVC 最佳实践（二）">ASP.NET MVC 最佳实践（二）</a></li><li>2009-06-28 -- <a href="http://ofcss.com/2009/06/28/asp-net-mvc-best-practices-part-1.html" title="ASP.NET MVC 最佳实践（一）">ASP.NET MVC 最佳实践（一）</a></li><li>2009-06-22 -- <a href="http://ofcss.com/2009/06/22/whatever-hover-pseudo-class-without-javascript.html" title="Whatever:hover &#8211; 无需javascript让IE支持丰富伪类">Whatever:hover &#8211; 无需javascript让IE支持丰富伪类</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML验证的价值探讨【译】</title>
		<link>http://ofcss.com/2010/10/22/the-value-of-html-validation-translation.html</link>
		<comments>http://ofcss.com/2010/10/22/the-value-of-html-validation-translation.html#comments</comments>
		<pubDate>Fri, 22 Oct 2010 08:47:01 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Validation]]></category>
		<category><![CDATA[网页]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://ofcss.com/2010/10/22/the-value-of-html-validation-translation.html</guid>
		<description><![CDATA[<p>作者：Nicholas C. Zakas 原文：http://www.nczonline.net/blog/2010/08/17/the-value-of-html-validation/ 这篇文章我已经酝酿了很久，期间还拜读了 Chris Heilmann 关于 Remy Sharp’s site 的这篇大作。我和Chris曾就这个话题多次交换意见，最终我们彼此的观点都有所改变，接受了一些过去无法接受的意见。我曾经在公开的、私下的各种场合直言不讳地表示过，目前的HTML验证状况对我来说纯粹是浮云。要了解我的看法，你需要先明白HTML验证到底是什么。 &#160; 什么是HTML验证 HTML验证是对你的网页代码执行一系列验证任务，主要包括： 代码语法验证 &#8211; 检查语法错误。从技术上说，尽管 &#60;foo&#62; 不是HTML规范中的一个标签，&#60;foo bar=&#34;baz&#34;&#62; 在语法上也是正确的，所以语法验证唯一的作用就是确保编写出合法的HTML代码。 标签嵌套验证 &#8211; 检查标签是否正确地按照打开的先后顺序关闭。比如一个&#60;div&#62;标签没有被正确关闭的话，在这项检查中就会报错。 DTD定义验证 &#8211; 检查你的代码是否遵循了指定的DTD的定义。这项验证检查的内容包括标签名称、属性名称、以及标签包含关系（某个标签是否允许被嵌套在另一个内部）。 异常实体验证* &#8211; 检查是否存在DTD规范中不曾提及的任何东西。通常自定义标签和自定义属性就会在这一项验证中报错。 （*译者注：关于原文中的Outlier Validation，指的是对不属于DTD定义范围内的实体的验证。在数学上，把这种游离于基准之外的值成为离群值，因而在数学上有Outlier Validation &#8211; 离群验证的概念。但是在HTML中，对于DTD中的元素、属性，均是实体，这项验证要做的是找出不在定义范围内的异常实体，因此暂译为“异常实体验证”，若您有更好的翻译方案，欢迎探讨。） 请记住：以上这四项验证任务只是为了便于理解而进行的逻辑划分，而不一定是验证器真正的实现方式。如果在某个验证任务上失败了，就说明HTML代码在该项对应的方面存在问题，是不符合规范的。 关于HTML验证的争论 HTML验证的支持者的主要观点是：HTML验证能够保证网页在不同浏览器下的互用性。不同核心的浏览器拥有不同的语法分析器以及HTML验证的具体实现。只有同时满足所有浏览器的要求，你的代码才能始终正常工作。由于每个浏览器在其语法分析器中各自以不同方式来实现纠错功能，因此对于不规范的代码，我们无法预计浏览器会如何呈现它。 而HTML验证的反对者则认为：HTML验证过于严格，而且没有考虑到浏览器的真实工作情况。HTML中的某些情况虽然从技术角度看可能是不合规范的，但是所有的浏览器都能按照相同的方式处理它们（注：并不总是相同的方式）。如果我自己能对自己编写的不规范代码负责，那我就不需要担心什么HTML验证——我真正关注的只是让这个网页正确呈现。 &#8230; <a href="http://ofcss.com/2010/10/22/the-value-of-html-validation-translation.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>作者：<a href="http://www.nczonline.net/about/" rel="tag">Nicholas C. Zakas</a></p>
<p>原文：<a href="http://www.nczonline.net/blog/2010/08/17/the-value-of-html-validation/">http://www.nczonline.net/blog/2010/08/17/the-value-of-html-validation/</a></p>
<p>这篇文章我已经酝酿了很久，期间还拜读了 <a href="http://www.wait-till-i.com/" rel="tag">Chris Heilmann</a> 关于 <a href="http://doesvalidationmatter.com/">Remy Sharp’s site</a> 的<a href="http://www.wait-till-i.com/2010/08/17/validate-dont/" rel="enclosure">这篇大作</a>。我和Chris曾就这个话题多次交换意见，最终我们彼此的观点都有所改变，接受了一些过去无法接受的意见。我曾经在公开的、私下的各种场合直言不讳地表示过，目前的HTML验证状况对我来说纯粹是浮云。要了解我的看法，你需要先明白HTML验证到底是什么。</p>
<p>  <span id="more-973"></span>
<p>&#160;</p>
<h3>什么是HTML验证</h3>
<p><a href="http://validator.w3.org/" rel="tag">HTML验证</a>是对你的网页代码执行一系列验证任务，主要包括：</p>
<ol>
<li><strong>代码语法验证</strong> - 检查语法错误。从技术上说，尽管 <em>&lt;foo&gt; </em>不是HTML规范中的一个标签<em>，&lt;foo bar=&quot;baz&quot;&gt;</em> 在语法上也是正确的，所以语法验证唯一的作用就是确保编写出合法的HTML代码。 </li>
<li><strong>标签嵌套验证</strong> - 检查标签是否正确地按照打开的先后顺序关闭。比如一个&lt;div&gt;标签没有被正确关闭的话，在这项检查中就会报错。 </li>
<li><strong>DTD定义验证</strong> - 检查你的代码是否遵循了指定的DTD的定义。这项验证检查的内容包括标签名称、属性名称、以及标签包含关系（某个标签是否允许被嵌套在另一个内部）。 </li>
<li><strong><font style="background-color: #ffc000"></font></strong><strong><font color="#f79646">异常实体验证*</font></strong><strong><font style="background-color: #ffc000"></font></strong> - 检查是否存在DTD规范中不曾提及的任何东西。通常自定义标签和自定义属性就会在这一项验证中报错。 （<font color="#f79646">*译者注：关于原文中的Outlier Validation，指的是对不属于DTD定义范围内的实体的验证。在数学上，把这种游离于基准之外的值成为离群值，因而在数学上有Outlier Validation - 离群验证的概念。但是在HTML中，对于DTD中的元素、属性，均是实体，这项验证要做的是找出不在定义范围内的异常实体，因此暂译为“异常实体验证”，若您有更好的翻译方案，欢迎探讨。</font><font style="background-color: #ffc000"></font>） </li>
</ol>
<p>请记住：以上这四项验证任务只是为了便于理解而进行的逻辑划分，而不一定是验证器真正的实现方式。如果在某个验证任务上失败了，就说明HTML代码在该项对应的方面存在问题，是不符合规范的。   </p>
<h3>关于HTML验证的争论</h3>
<p>HTML验证的支持者的主要观点是：HTML验证能够保证网页在不同浏览器下的互用性。不同核心的浏览器拥有不同的语法分析器以及HTML验证的具体实现。只有同时满足所有浏览器的要求，你的代码才能始终正常工作。由于每个浏览器在其语法分析器中各自以不同方式来实现纠错功能，因此对于不规范的代码，我们无法预计浏览器会如何呈现它。</p>
<p>而HTML验证的反对者则认为：HTML验证过于严格，而且没有考虑到浏览器的真实工作情况。HTML中的某些情况虽然从技术角度看可能是不合规范的，但是所有的浏览器都能按照相同的方式处理它们（注：并不总是相同的方式）。如果我自己能对自己编写的不规范代码负责，那我就不需要担心什么HTML验证——我真正关注的只是让这个网页正确呈现。</p>
<p>&#160;</p>
<h3>我的观点</h3>
<p>我很少会就某个争论的问题公开表态，这恰好是其中之一，希望你喜欢。基于“HTML验证过份严格，不符合实际工作场景”的原因，我一直都属于反对HTML验证的阵营。有一些被浏览器广泛支持的东西（&lt;head&gt;里面的&lt;noscript&gt;，&lt;/html&gt;之后的&lt;script&gt;）居然也不符合规范，而为了得到正确的用户体验，它们有时候却是必不可少的。</p>
<p>总的来说，HTML验证给我造成的麻烦主要集中在第四项（异常实体验证）。我喜欢在HTML中用自定义属性为特定元素提供额外元数据，而且坚持这种做法。对我来说，要为某个元素提供关联数据时，只需给它增加一个相应的属性。某些人某种时候使用一个合法的属性的目的纯粹是为了让代码能够通过验证，哪怕这个属性根本不是设计来在这种情况下用的。我绝不认同这种做法。</p>
<p>浏览器有个恶心的小秘密，那就是它们根本不会按照DTD文档定义去做HTML验证。你加在网页顶部的文档类型（doctype）只是让语法分析器切换到某种指定的工作模式，但是没有任何一种工作模式会去下载该文档类型的DTD然后验证代码是否符合DTD规定。这是什么意思呢？这就是说，浏览器只是用一个简单的语法分析器来处理HTML，而这个简单的语法分析器只包含一些关于自关闭标签、块元素对行内元素的指定异常而已（我相信其它情况也是如此）。</p>
<p>就自定义属性而言，所有的浏览器都会把它们当作正确的属性一样处理，并因此使得JavaScript可以通过DOM对它们进行操作。浏览器不仅在分析自定义属性的时候不报错，而且在处理阶段也会像把它们当作正常的属性来处理！那么，即使这些自定义属性不能通过HTML验证，我们又何须在意呢？我还会继续使用自定义属性，而且我们都看到HTML5已经正式把自定义属性作为数据集了，哥很欣慰。</p>
<p>还有个很好的例子：<a href="http://www.w3.org/WAI/intro/aria" rel="tag">ARIA</a>是一项却极其重要的技术，但是按照验证器的检查结果，ARIA却是不规范的HTML。ARIA 技术是在HTML4的基础上添加自定义属性实现的。这些元素为HTML元素提供额外的语义，浏览器能够把这些语义传递给专为不健全人士设计的辅助设备，帮助他们更方便地使用web。当今所有的主流浏览器都支持 ARIA 标签，然而如果你在网页里添加这些属性，你的网页就不能通过HTML验证了。</p>
<p>此外还有被当作错误修正的一部分而被抛弃的自定义标签。我对此没有很强烈的体会，但是个人而言，我觉得如果语义正确的话，在页面中使用自定义标签应该是可以的，只是目前未知我还没有遇到这方面的很好的案例。</p>
<p>再明确一下我的立场：我坚决认同HTML验证的第一项（译注：代码语法验证）和第二项（译注：标签嵌套验证）是很基础、很重要的，应该进行验证并确保通过。第三项（译注：DTD定义验证）也还算重要但是不如前两项。第四项（译注：异常实体验证）的重要性我是不认可的，因为它涉及到自定义属性的使用。异常实体验证顶多只能标记为警告级别，以提醒我们做二次检查看是不是拼错了属性名称。把自定义标签标记为错误或许是个好主意，但是会有一些不利影响——因为它关系到一些其它内容的嵌入标签，例如SVG和MathML(本质上，这些每一种情况都需要成为解析器里的一种特殊异常)。</p>
<p>&#160;</p>
<h3>为了验证而验证？</h3>
<p>我要以最强烈的方式表达这个观点：为了验证而验证纯属有病！规范的HTML意味着通过了全部四项检查，但是还有很多东西是仅靠“规范的HTML”不能保证的：</p>
<ul>
<li>规范的HTML不能保证可用性 </li>
<li>规范的HTML不能保证良好的用户体验 </li>
<li>规范的HTML不能保证网站功能正常运作 </li>
<li>规范的HTML不能保证正确的布局 </li>
</ul>
<p>拥有规范的HTML代码或许可以看作一枚荣誉勋章，带给你病态的满足感。但是它本身不是一种成功，更不是衡量成功与否的标准。你的（通过验证的）代码实际运行起来未必比我的（未通过验证的）代码效果更好。</p>
<p>&#160;</p>
<h3>HTML5 验证</h3>
<p>HTML5验证修正了我和其他人在HTML4验证中遇到的一些问题。它明确地支持ARIA属性，你也可以添加自定义属性，只要它们以“data-”开头即可。这些情况在HTML5中都被认为是合乎规范的。与HTML4验证相比，这令我满意。要声明的一点是，HTML5验证器中仍有一些我不赞成的部分。尽管如此，我还是认为HTML5验证器比HTML4验证器更好地反映了实际的工作用例。</p>
<p>&#160;</p>
<h3>学术问题，文明探讨</h3>
<p>我确实认为HTML验证服务中的某些部分是非常有用的，但是我不想被它挟持，因为我要用自定义属性。我在日常工作中很自豪地使用着ARIA规则，并且根本不在乎它们会让HTML4验证器不爽。再说一次：验证器总共有四个任务，只有一个让我不爽，而HTML5验证器注意到了我的需求。</p>
<p>我知道我谈论的是一个热点问题，它将会引出更多的帖子和博文。我已经在评论表单前做了免责声明，但还是要提醒大家在今后的讨论中保持文明，提供建设性的意<u>见</u>。我还知道双方接下来肯定会有非常强烈的争论并且每个人都会有各自的重<u>点</u>（作者注：我没有刻意押韵；译者注：我也没有刻意押韵）。在评论中出现良性的、强烈的辩论非常好，但让我们都约束一下自己的火爆脾气。这是一个知识性的辩论，不是一个感性的辩论。我要声明，我会比以往更加严格地审核评论 —— 所以希望大家都规矩点。</p>
<p>免责声明：本文所表达的任何观点和看法都仅代表 Nicholas C. Zakas 个人，与 <a href="http://www.yahoo.com/" rel="nofollow">Yahoo！</a>，<a href="http://www.wrox.com/" rel="nofollow">Wrox 出版社</a>，<a href="http://www.wrox.com/" rel="nofollow">O'Reilly 出版社</a> 无关，与其它任何人无关。我仅代表我自己，不代表他们。</p>
<p>你可以在我的站点<a href="http://www.nczonline.net/blog/2010/08/17/the-value-of-html-validation/#respond" rel="nofollow">留言</a>，或者从你自己的站点发送 <a href="http://www.nczonline.net/blog/2010/08/17/the-value-of-html-validation/trackback/" rel="nofollow">trackback</a>。</p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2010-10-20 -- <a href="http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html" title="clearfix改良及overflow:hidden详解【译】">clearfix改良及overflow:hidden详解【译】</a></li><li>2009-06-22 -- <a href="http://ofcss.com/2009/06/22/whatever-hover-pseudo-class-without-javascript.html" title="Whatever:hover &#8211; 无需javascript让IE支持丰富伪类">Whatever:hover &#8211; 无需javascript让IE支持丰富伪类</a></li><li>2011-03-12 -- <a href="http://ofcss.com/2011/03/12/flexible-two-column-layout-reloaded.html" title="自适应的多列图文混排改进">自适应的多列图文混排改进</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-30 -- <a href="http://ofcss.com/2010/10/30/bfc-element-margin-bug-in-webkit.html" title="webkit中BFC元素临近浮动元素时的边距bug">webkit中BFC元素临近浮动元素时的边距bug</a></li><li>2010-10-25 -- <a href="http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html" title="借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】">借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】</a></li><li>2010-10-24 -- <a href="http://ofcss.com/2010/10/24/running-scripts-in-webkit-translation.html" title="在WebKit中并行加载外部脚本【译】">在WebKit中并行加载外部脚本【译】</a></li><li>2010-06-09 -- <a href="http://ofcss.com/2010/06/09/my-rencent-booklist.html" title="最近的书单">最近的书单</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2010/10/22/the-value-of-html-validation-translation.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>clearfix改良及overflow:hidden详解【译】</title>
		<link>http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html</link>
		<comments>http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html#comments</comments>
		<pubDate>Wed, 20 Oct 2010 06:03:23 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[乱七八糟]]></category>
		<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[网页]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html</guid>
		<description><![CDATA[<p>原文:clearfix Reloaded + overflow:hidden Demystified clearfix 和 overflow:hidden 可算得上是不增加额外标签清除浮动的两个最流行的技术了。 这篇短文介绍了如何改进clearfix进行增强，同时对overflow:hidden进行了深入的解释。 clearfix 曾经在网上流行的一种clearfix的方法： .clearfix:after { content: &#34;.&#34;; display: block; height: 0; clear: both; visibility: hidden; } * html .clearfix { zoom: 1; } /* IE6 */ *:first-child+html .clearfix { zoom: 1; &#8230; <a href="http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p>原文:<a href="http://www.yuiblog.com/blog/2010/09/27/clearfix-reloaded-overflowhidden-demystified/">clearfix Reloaded + overflow:hidden Demystified</a></p>
<p>clearfix 和 overflow:hidden 可算得上是不增加额外标签清除浮动的两个最流行的技术了。</p>
<p>这篇短文介绍了如何改进clearfix进行增强，同时对overflow:hidden进行了深入的解释。</p>
<p> <span id="more-969"></span><br />
<h3>clearfix</h3>
<p>曾经在网上流行的一种clearfix的方法：</p>
<div class="code">
<pre><span style="color: maroon">.clearfix:after </span>{
    <span style="color: red">content</span>: <span style="color: blue">&quot;.&quot;</span>;
    <span style="color: red">display</span>: <span style="color: blue">block</span>;
    <span style="color: red">height</span>: <span style="color: blue">0</span>;
    <span style="color: red">clear</span>: <span style="color: blue">both</span>;
    <span style="color: red">visibility</span>: <span style="color: blue">hidden</span>;
    }
<span style="color: maroon">* html .clearfix </span>{ <span style="color: red">zoom</span>: <span style="color: blue">1</span>; } <span style="color: #006400">/* IE6 */
</span><span style="color: maroon">*:first-child+html .clearfix </span>{ <span style="color: red">zoom</span>: <span style="color: blue">1</span>; } <span style="color: #006400">/* IE7 */
</span></pre>
</div>
<p>在作者的另一篇文章 <a href="http://www.tjkdesign.com/articles/clearfix_block-formatting-context_and_hasLayout.asp">everything you know about clearfix is wrong</a> 中，他介绍了这种方法在跨浏览器兼容时会造成的问题，并建议仅对不邻近浮动元素的元素应用clearfix（例如弹出窗口），尽管这样做我们还需要处理由clearfix造成的边距折叠bug（译者注：指clearfix的盒子内部元素的垂直边距被扩展到盒子之外）。有一个<a href="http://www.tjkdesign.com/lab/clearfix/new-clearfix.html">demo页面</a>解释了这个问题。</p>
<p>该页面中最开始的两个盒模型的边距叠加行为（底边距保留在盒子内部，顶边距则到了盒子外部）说明：生成的内容将盒子内部元素的边距保留保留在了盒子内部，而在其它浏览器下边距将被扩展到盒子边缘之外。</p>
<p>因此，为了创建跨浏览器兼容的同样的盒模型布局，我们可以把原来的清除浮动的方法改良一下，采用伪类:before 和 :after：</p>
<div class="code">
<pre><span style="color: maroon">.clearfix:before</span>,
<span style="color: maroon">.clearfix:after </span>{
  <span style="color: red">content</span>: <span style="color: blue">&quot;.&quot;</span>;
  <span style="color: red">display</span>: <span style="color: blue">block</span>;
  <span style="color: red">height</span>: <span style="color: blue">0</span>;
  <span style="color: red">visibility</span>: <span style="color: blue">hidden</span>;
}
<span style="color: maroon">.clearfix:after </span>{<span style="color: red">clear</span>: <span style="color: blue">both</span>;}
<span style="color: maroon">.clearfix </span>{<span style="color: red">zoom</span>: <span style="color: blue">1</span>;} <span style="color: #006400">/* IE &lt; 8 */
</span></pre>
</div>
<p>如此一来可以使顶边距和底边距都保留在盒子内部，符合<a href="http://www.w3.org/TR/CSS2/box.html#collapsing-margins">w3c关于垂直边距叠加的说明</a>。但是不要在现有的项目中简单地用这些代码替换你的clearfix规则，否则可能会与你原来为了解决边距重叠问题采取的解决方案产生冲突。</p>
<p>&#160;</p>
<h3>overflow</h3>
<p>在众多关于清除浮动的讨论中，出现了overflow:hidden的方法，并且这种方法总是被“如果你把绝对定位元素置于div内部，这些元素（超出的部分）将会被隐藏”的观点击败。但事实并非如此。overflow:hidden 会修剪相对定位（position:relative）的元素，但并不总是会隐藏绝对定位元素。这是因为是否隐藏绝对定位元素实际上取决其包含块（containing block）：</p>
<p>10.1 &quot;containing block&quot; 的定义：</p>
<blockquote>
<p>4. If the element has 'position:absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative', or 'fixed'. …</p>
<p>翻译：如果一个元素有&quot;position:absolute&quot;的定义，则其包含块由最近的拥有&quot;position:absolute|relative|fixed&quot;属性的祖先元素确定。…</p>
</blockquote>
<p>这意味着一个带有overflow:hidden样式的盒子，它所包含的绝对定位子元素如果溢出，并不会被隐藏——除非该绝对定位元素的包含块（containing block）就是这个盒子本身或位于该盒子内部。也就是说，如果这个绝对定位元素的包含块的层级高于拥有overflow:hidden样式的盒子，那么这个盒子里面的绝对定位元素不会被截断或隐藏。</p>
<p>作者提供了一个<a href="http://www.tjkdesign.com/lab/clearfix/overflow-and-ap.html">demo 页面</a>演示这个原理（页面上的wrapper设定了overflow:hidden，但是绝对定位的子元素box1却显示在了wrapper外面的左上角，并没有被隐藏）。</p>
<p>&#160;</p>
<h3>更好的选择</h3>
<p>如果你可以对包含浮动的元素应用宽度，那么更好的办法是用下面的样式来清除浮动：</p>
<div class="code">
<pre><span style="color: maroon">display: inline-block;
width: </span>&lt;<span style="color: maroon">any explicit value&gt;</span>;</pre>
</div>
<p>&#160;</p>
<h3>引申阅读</h3>
<ul>
<li><a href="http://csscreator.com/attributes/containedfloat.php">Contained Floats, enclosing floats with pure CSS known as the clearfix technique</a> </li>
<li><a href="http://www.positioniseverything.net/easyclearing.html">How To Clear Floats Without Structural Markup</a> </li>
<li><a href="http://perishablepress.com/press/2009/12/06/new-clearfix-hack/">The New Clearfix Method</a> </li>
<li><a href="http://www.w3.org/TR/CSS2/visudet.html#containing-block-details">10.1 Definition of &quot;containing block&quot;</a> </li>
</ul>
<p><em><strong>关于作者:</strong> Thierry Koblentz 是 Yahoo! 的一位前端工程师。他负责的项目有 <a href="http://www.tjkdesign.com/">TJK Design</a> 和 <a href="http://www.ez-css.org/">ez-css.org</a>. 你可以在twitter上follow他： <a href="http://twitter.com/thierrykoblentz">@thierrykoblentz</a> </em>.</p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2009-06-22 -- <a href="http://ofcss.com/2009/06/22/whatever-hover-pseudo-class-without-javascript.html" title="Whatever:hover &#8211; 无需javascript让IE支持丰富伪类">Whatever:hover &#8211; 无需javascript让IE支持丰富伪类</a></li><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2011-03-12 -- <a href="http://ofcss.com/2011/03/12/flexible-two-column-layout-reloaded.html" title="自适应的多列图文混排改进">自适应的多列图文混排改进</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-30 -- <a href="http://ofcss.com/2010/10/30/bfc-element-margin-bug-in-webkit.html" title="webkit中BFC元素临近浮动元素时的边距bug">webkit中BFC元素临近浮动元素时的边距bug</a></li><li>2010-10-22 -- <a href="http://ofcss.com/2010/10/22/the-value-of-html-validation-translation.html" title="HTML验证的价值探讨【译】">HTML验证的价值探讨【译】</a></li><li>2009-12-21 -- <a href="http://ofcss.com/2009/12/21/web-developer-understand-css-box-model.html" title="前台开发从头说起：理解css盒模型">前台开发从头说起：理解css盒模型</a></li><li>2009-12-16 -- <a href="http://ofcss.com/2009/12/16/web-developer-about-css-selector.html" title="前台开发从头说起：谈谈CSS选择符">前台开发从头说起：谈谈CSS选择符</a></li><li>2009-12-15 -- <a href="http://ofcss.com/2009/12/15/web-developer-from-web-standard.html" title="前台开发从头说起：关于web标准化">前台开发从头说起：关于web标准化</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2010/10/20/clearfix-reloaded-overflowhidden-demystified-translation.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC 最佳实践（四）</title>
		<link>http://ofcss.com/2009/07/08/asp-net-mvc-best-practices-part-4.html</link>
		<comments>http://ofcss.com/2009/07/08/asp-net-mvc-best-practices-part-4.html#comments</comments>
		<pubDate>Tue, 07 Jul 2009 17:34:45 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[开发]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://wukangrui.net/2009/07/08/asp-net-mvc-best-practices-part-4.html</guid>
		<description><![CDATA[<p>本系列翻译自 Kazi Manzur Rashid 的博客，由于篇幅关系，原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第二部分第18-21节。 <a href="http://ofcss.com/2009/07/08/asp-net-mvc-best-practices-part-4.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p><em>本系列翻译自 </em><a href="http://weblogs.asp.net/rashid/default.aspx"><em>Kazi Manzur Rashid</em></a><em> 的博客，由于翻译水平有限，本系列可能存在误解偏差或者翻译不准的地方，建议对比<a href="http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx">原文</a>进行阅读。由于篇幅关系，原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第二部分第18-21节。如果你没有看过之前的第一部分，也许你想先看看 <a href="http://wukangrui.net/2009/06/28/asp-net-mvc-best-practices-part-1.html">《ASP.NET MVC 最佳实践（一）》</a>、《<a href="http://wukangrui.net/2009/06/28/asp-net-mvc-best-practices-part-1.html">ASP.NET MVC 最佳实践（二）</a>》和《<a href="http://wukangrui.net/2009/07/07/asp-net-mvc-best-practices-part-1-2.html" rel="prev" target="_blank">ASP.NET MVC 最佳实践（三）</a>》。</em></p>
</p>
<p><em></em></p>
</p>
<p> <span id="more-858"></span>
</p>
<h4>18. HtmlHelper 扩展</h4>
<p>首先，参考一下 <a href="http://blog.wekeroad.com/" rel="external" target="_blank">Rob Conery</a> 的<a href="http://blog.wekeroad.com/blog/asp-net-mvc-avoiding-tag-soup/" rel="external" target="_blank">这篇文章</a>，我完全同意他的观点，你应该为每种情况创建 Helper 方法，此外我还建议你像 <a href="http://www.asp.net/mvc/" rel="tag" target="_blank">ASP.NET MVC</a> 团队那样为可重用的 UI 元素创建 Helper 方法，但是对于在哪里放置我们正在实践的这些方法，我有不同的建议。</p>
<h6>应用程序开发者</h6>
<p>只为你需要在多个视图中重复使用的HtmlHealper创建单独的扩展方法。对于只在一个视图中使用的帮助方法，你可以为整个视图创建一个Helper类，然后创建一个HtmlHelper来返回这个视图Helper类，而把只在这个视图中使用的扩展方法作为类内部的方法。（这部分未按原文翻译，请自行参照原文）例如：</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">DashboardHtmlHelper </span>{
    <span style="color: blue">private readonly </span><span style="color: #2b91af">HtmlHelper </span>_htmlHelper;

    <span style="color: blue">public </span>DashboardHtmlHelper(<span style="color: #2b91af">HtmlHelper </span>htmlHelper) {
        _htmlHelper = htmlHelper;
    }

    <span style="color: blue">public string </span>DoThis() {
        <span style="color: green">//Your Code
    </span>}

    <span style="color: blue">public string </span>DoThat() {
        <span style="color: green">//Your Code
    </span>}
}

<span style="color: blue">public static class </span><span style="color: #2b91af">HtmlHelperExtension </span>{
    <span style="color: blue">public static </span><span style="color: #2b91af">DashboardHtmlHelper </span>Dashboard(<span style="color: blue">this </span><span style="color: #2b91af">HtmlHelper </span>htmlHelper) {
        <span style="color: blue">return new </span><span style="color: #2b91af">DashboardHtmlHelper</span>(htmlHelper);
    }
}</pre>
<p>然后在视图中这样调用：</p>
<pre class="code"><span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Html.Dashboard().DoThis() <span style="background: #ffee62">%&gt;</span></pre>
<h6>UI 组件开发人员</h6>
<p>如果你在开发的是可以在多个 <a href="http://www.asp.net/mvc/" rel="tag" target="_blank">ASP.NET MVC</a> 应用程序中重用的 UI 组件系列，你可以像上面那样为你的整个系列组件创建一个单一名字的Helper。假如你开发的是商业组件，那你可以用你的公司名字来为这个单一的Helper命名，然后在这个Helper中添加方法。否则很容易出现方法的命名冲突。</p>
<p>要是你正在学习 <a href="http://mvccontrib.codeplex.com" rel="external" target="_blank">MVCContrib.org</a> 的做法，为 IViewDataContainer 做扩展的话，道理也是一样的。</p>
<h4>19. Html编码</h4>
<p>在从用户端获取信息的任何情况下，总是使用 Html.Encode(“User Input”) 来编码文本节点，用 Html.AttributeEncode(“User Input”) 来编码Html 元素属性。</p>
<h4>20. 不要把Javascript脚本放在你的视图中</h4>
<p>不要把你的javascript脚本和html混杂在一起，创建一个单独的 js 文件，把脚本代码放在里面。有时候你可能需要在你的 javascript 代码中传递视图数据，这种特殊的情况下，也只把初始化代码放在视图中。例如，你正在开发 web 2.0 风格的应用，你需要在这个应用中传递 ajax 方法的url，并且需要在 javascript 脚本中传递一些其它的模型数据，这种情况下，你可以参考下面的方式：</p>
<p>视图：</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">=&quot;sideBar&quot; </span><span style="color: red">class</span><span style="color: blue">=&quot;column&quot;&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">script </span><span style="color: red">type</span><span style="color: blue">=&quot;text/javascript&quot;&gt;
            </span>$(document).ready(<span style="color: blue">function</span>(){
                Story.init(<span style="color: #a31515">'&lt;%= Model.UrlFormat %&gt;'</span>, <span style="color: #a31515">'&lt;%= Url.NoIcon() %&gt;'</span>, &lt;%= Model.PageCount %&gt;, &lt;%= Model.StoryPerPage %&gt;, &lt;%= Model.CurrentPage %&gt;, <span style="color: #a31515">'&lt;%= Model.SelectedTab %&gt;'</span>, <span style="color: #a31515">'&lt;%= Model.SelectedOrderBy %&gt;'</span>);
            });
        <span style="color: blue">&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Javascript：</p>
<pre class="code"><span style="color: blue">var </span>Story = {
    _urlFormat: <span style="color: #a31515">''</span>,
    _noIconUrl: <span style="color: #a31515">''</span>,
    _pageCount: 0,
    _storyPerPage: 0,
    _currentPage: 0,
    _currentTab: <span style="color: #a31515">''</span>,
    _currentOrderBy: <span style="color: #a31515">''</span>,

    init: <span style="color: blue">function</span>(urlFormat, noIconUrl, pageCount, storyPerPage, currentPage, currentTab, currentOrderBy) {
        Story._urlFormat = urlFormat;
        Story._noIconUrl = noIconUrl;
        Story._pageCount = pageCount;
        Story._storyPerPage = storyPerPage;
        Story._currentPage = currentPage;
        Story._currentTab = currentTab;
        Story._currentOrderBy = currentOrderBy;

        <span style="color: green">//More Codes
    </span>}
}</pre>
<p>这里要为不太熟悉上面的 javascript 的同学解释一下，这是一个在javascript中创建静态类的示例代码。对了，我还差点忘了提一点，永远不要在你的javascript文件中硬编码 ajax 方法的url，虽然 <a href="http://videos.visitmix.com/MIX09/T62F" rel="external" target="_blank">Rob Conery</a> 和 <a href="http://aspnetpodcast.com/CS11/blogs/asp.net_podcast/archive/2008/07/28/asp-net-podcast-show-121-phil-haack-with-an-asp-net-mvc-demo-video.aspx" rel="external" target="_blank">Phil Haack</a> 在他们的教程中是这样干的。这是一个很不好的方式，它破坏了 ASP.NET 路径重写的优雅性。</p>
<h4>21. 使用 jQuery 和 jQuery UI</h4>
<p>使用 jQuery 和 jQuery UI，它是最好的js库，并且可以使用 Google CDN 托管服务来加载这些库（对于国内用户，如果使用 google 托管的库一定要有承担风险的准备，具体原因嘛，看看国内6月24日左右的IT新闻就知道了）。</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">link </span><span style="color: red">type</span><span style="color: blue">=&quot;text/css&quot; </span><span style="color: red">href</span><span style="color: blue">=&quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/themes/{YOUR Prefered Theme}/jquery-ui.css&quot; </span><span style="color: red">rel</span><span style="color: blue">=&quot;stylesheet&quot;/&gt;
&lt;</span><span style="color: #a31515">script </span><span style="color: red">type</span><span style="color: blue">=&quot;text/javascript&quot; </span><span style="color: red">src</span><span style="color: blue">=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&quot;&gt;&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">script </span><span style="color: red">type</span><span style="color: blue">=&quot;text/javascript&quot; </span><span style="color: red">src</span><span style="color: blue">=&quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.js&quot;&gt;&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;</span></pre>
<p>还有一种更好的方式：</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">link </span><span style="color: red">type</span><span style="color: blue">=&quot;text/css&quot; </span><span style="color: red">href</span><span style="color: blue">=&quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/themes/{YOUR Prefered Theme}/jquery-ui.css&quot; </span><span style="color: red">rel</span><span style="color: blue">=&quot;stylesheet&quot;/&gt;
&lt;</span><span style="color: #a31515">script </span><span style="color: red">type</span><span style="color: blue">=&quot;text/javascript&quot; </span><span style="color: red">src</span><span style="color: blue">=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">script </span><span style="color: red">type</span><span style="color: blue">=&quot;text/javascript&quot;&gt;
    </span>google.load(<span style="color: #a31515">&quot;jquery&quot;</span>, <span style="color: #a31515">&quot;1.3.2&quot;</span>);
    google.load(<span style="color: #a31515">&quot;jqueryui&quot;</span>, <span style="color: #a31515">&quot;1.7.1&quot;</span>);
<span style="color: blue">&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;</span></pre>
<p>以上就是这一次的全部内容。</p>
<p>最后，我要祝贺 <a href="http://www.asp.net/mvc/" rel="tag" target="_blank">ASP.NET MVC</a> 团队开发了如此杰出的框架，尤其是他们从社区接受反馈的方式。我希望能用这个框架开发出<a href="http://dotnetshoutout.com/" rel="external" target="_blank">更多</a>杀手级的应用（注：杀手级的应用程序，一般指极其优秀的应用程序，这类程序超越了语言本身，比语言更有吸引力而且能增加语言的吸引力）。</p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2009-07-07 -- <a href="http://ofcss.com/2009/07/07/asp-net-mvc-best-practices-part-3.html" title="ASP.NET MVC 最佳实践（三）">ASP.NET MVC 最佳实践（三）</a></li><li>2009-07-01 -- <a href="http://ofcss.com/2009/07/01/asp-net-mvc-best-practices-part-2.html" title="ASP.NET MVC 最佳实践（二）">ASP.NET MVC 最佳实践（二）</a></li><li>2009-06-28 -- <a href="http://ofcss.com/2009/06/28/asp-net-mvc-best-practices-part-1.html" title="ASP.NET MVC 最佳实践（一）">ASP.NET MVC 最佳实践（一）</a></li><li>2009-04-13 -- <a href="http://ofcss.com/2009/04/13/aspnetmvc-hands-on-labs-develop-application.html" title="[翻译]ASP.NET MVC动手实验1-3：开发ASP.NET MVC应用">[翻译]ASP.NET MVC动手实验1-3：开发ASP.NET MVC应用</a></li><li>2009-04-09 -- <a href="http://ofcss.com/2009/04/09/aspnetmvc-hands-on-labs-create-application.html" title="[翻译]ASP.NET MVC动手实验1-2：创建ASP.NET MVC应用">[翻译]ASP.NET MVC动手实验1-2：创建ASP.NET MVC应用</a></li><li>2009-04-09 -- <a href="http://ofcss.com/2009/04/09/aspnetmvc-hands-on-labs-introduction.html" title="[翻译]ASP.NET MVC动手系列1-1：ASP.NET MVC概述">[翻译]ASP.NET MVC动手系列1-1：ASP.NET MVC概述</a></li><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-25 -- <a href="http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html" title="借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】">借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2009/07/08/asp-net-mvc-best-practices-part-4.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC 最佳实践（三）</title>
		<link>http://ofcss.com/2009/07/07/asp-net-mvc-best-practices-part-3.html</link>
		<comments>http://ofcss.com/2009/07/07/asp-net-mvc-best-practices-part-3.html#comments</comments>
		<pubDate>Mon, 06 Jul 2009 17:21:16 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[开发]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://wukangrui.net/2009/07/07/asp-net-mvc-best-practices-part-1-2.html</guid>
		<description><![CDATA[<p>本系列翻译自 Kazi Manzur Rashid 的博客，由于翻译水平有限，本系列可能存在误解偏差或者翻译不准的地方，建议对比原文进行阅读。由于篇幅关系，原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第二部分。如果你没有看过之前的第一部分，也许你想先看看 《ASP.NET MVC 最佳实践（一）》和《ASP.NET MVC 最佳实践（二）》。 <a href="http://ofcss.com/2009/07/07/asp-net-mvc-best-practices-part-3.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p><em>本系列翻译自 </em><a href="http://weblogs.asp.net/rashid/default.aspx"><em>Kazi Manzur Rashid</em></a><em> 的博客，由于翻译水平有限，本系列可能存在误解偏差或者翻译不准的地方，建议对比<a href="http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx">原文</a>进行阅读。由于篇幅关系，原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第二部分。如果你没有看过之前的第一部分，也许你想先看看 <a rel="prev" href="http://wukangrui.net/2009/06/28/asp-net-mvc-best-practices-part-1.html">《ASP.NET MVC 最佳实践（一）》</a>和《<a rel="prev" href="http://wukangrui.net/2009/06/28/asp-net-mvc-best-practices-part-2.html">ASP.NET MVC 最佳实践（二）</a>》。</em> <span id="more-848"></span><em></em></p>
<h4>15. 关于路由的思考</h4>
<p>如果你在开发的是一个纯 ASP.NET MVC 的应用程序，可以先关闭已有的路由文件检查，这样可以去除不必要的文件系统检查。如果你这样做了，那么就还需要考虑另外的一些事情。请记住如果你的应用程序运行于 IIS 7集成模式，那么 ASP.NET 应用程序将会拦截所有的请求，不管文件的后缀名是什么。所以你必须要在过滤列表中加一些东西，以便让 <a rel="tag" href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> 应用程序不处理它们。这其中可能包括静态文件，例如 html、htm、文本文件(尤其是robots.txt)、favicon.ico、脚本、图片和css等等。这也是我在<a rel="prev" href="http://wukangrui.net/2009/06/28/asp-net-mvc-best-practices-part-1.html">第一部分第2节</a>中提到不喜欢默认文件结构的原因之一。以下是我为 IIS7 定制的路由定义标准模板：</p>
<pre class="code">_routes.Clear();

<span style="color: green">// Turns off the unnecessary file exists check
</span>_routes.RouteExistingFiles = <span style="color: blue">true</span>;

<span style="color: green">// Ignore text, html, files.
</span>_routes.IgnoreRoute(<span style="color: #a31515">"{file}.txt"</span>);
_routes.IgnoreRoute(<span style="color: #a31515">"{file}.htm"</span>);
_routes.IgnoreRoute(<span style="color: #a31515">"{file}.html"</span>);

<span style="color: green">// Ignore axd files such as assest, image, sitemap etc
</span>_routes.IgnoreRoute(<span style="color: #a31515">"{resource}.axd/{*pathInfo}"</span>);

<span style="color: green">// Ignore the assets directory which contains images, js, css &amp; html
</span>_routes.IgnoreRoute(<span style="color: #a31515">"assets/{*pathInfo}"</span>);

<span style="color: green">// Ignore the error directory which contains error pages
</span>_routes.IgnoreRoute(<span style="color: #a31515">"ErrorPages/{*pathInfo}"</span>);

<span style="color: green">//Exclude favicon (google toolbar request gif file as fav icon which is weird)
</span>_routes.IgnoreRoute(<span style="color: #a31515">"{*favicon}"</span>, <span style="color: blue">new </span>{ favicon = <span style="color: #a31515">@"(.*/)?favicon.([iI][cC][oO]|[gG][iI][fF])(/.*)?" </span>});

<span style="color: green">//Actual routes of my application</span></pre>
<p>接下来是我的一些不同于手册指南的个人偏好。默认情况下 <a rel="tag" href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> 产生的 url 形如 {controller}/{action}，在你开发一个多模块的应用程序是这是不错的选择，但是对于一些很小的应用程序，我通常喜欢从 url 中去掉控制器(controller)只留下方法名(action name)。如此一来，原来的“www.yourdomain.com/Story/Dashboard” 及 “www.yourdomain.com/Membership/Signin” 就会变成 “www.yourdomain.com/Dashboard” 和“www.yourmain.com/Signin”。所以我要添加一些新路由：</p>
<pre class="code">_routes.MapRoute(<span style="color: #a31515">"SignUp"</span>, <span style="color: #a31515">"SignUp"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Membership"</span>, action = <span style="color: #a31515">"SignUp" </span>});
_routes.MapRoute(<span style="color: #a31515">"SignIn"</span>, <span style="color: #a31515">"SignIn"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Membership"</span>, action = <span style="color: #a31515">"SignIn" </span>});
_routes.MapRoute(<span style="color: #a31515">"ForgotPassword"</span>, <span style="color: #a31515">"ForgotPassword"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Membership"</span>, action = <span style="color: #a31515">"ForgotPassword" </span>});
_routes.MapRoute(<span style="color: #a31515">"SignOut"</span>, <span style="color: #a31515">"SignOut"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Membership"</span>, action = <span style="color: #a31515">"SignOut" </span>});
_routes.MapRoute(<span style="color: #a31515">"Profile"</span>, <span style="color: #a31515">"Profile"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Membership"</span>, action = <span style="color: #a31515">"Profile" </span>});
_routes.MapRoute(<span style="color: #a31515">"ChangePassword"</span>, <span style="color: #a31515">"ChangePassword"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Membership"</span>, action = <span style="color: #a31515">"ChangePassword" </span>});

_routes.MapRoute(<span style="color: #a31515">"Dashboard"</span>, <span style="color: #a31515">"Dashboard/{tab}/{orderBy}/{page}"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Story"</span>, action = <span style="color: #a31515">"Dashboard"</span>, tab = StoryListTab.Unread.ToString(), orderBy = OrderBy.CreatedAtDescending.ToString(), page = 1 });
_routes.MapRoute(<span style="color: #a31515">"Update"</span>, <span style="color: #a31515">"Update"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Story"</span>, action = <span style="color: #a31515">"Update" </span>});
_routes.MapRoute(<span style="color: #a31515">"Submit"</span>, <span style="color: #a31515">"Submit"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Story"</span>, action = <span style="color: #a31515">"Submit" </span>});

_routes.MapRoute(<span style="color: #a31515">"Home"</span>, <span style="color: #a31515">"{controller}/{action}/{id}"</span>, <span style="color: blue">new </span>{ controller = <span style="color: #a31515">"Home"</span>, action = <span style="color: #a31515">"Index"</span>, id = <span style="color: blue">string</span>.Empty });</pre>
<h4> </h4>
<h4>16. 如果需要的话，创建新的ActionResult</h4>
<p><a rel="tag" href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> 包含有很多种用于不同目的的 ActionResult，但我们仍有可能会需要新的 ActionResult。例如xml、rss、atom等等。在这种情况下，我的建议是不要使用通用的 ContentResult， 而是创建一种新的 ActionResult. <a rel="external" href="http://mvccontrib.codeplex.com" target="_blank">MVCContrib</a> 项目中有一个 XmlResult，你可以用它来返回 xml，但是不支持 feed。显然依靠它来将未知对象转换为 rss/atom 是很困难的，这时你就可以创建一个定义ActionResult的模型。例如：</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">AtomResult </span>: <span style="color: #2b91af">ActionResult </span>{
    <span style="color: blue">public </span>AtomResult(<span style="color: blue">string </span>siteTitle, <span style="color: blue">string </span>feedTitle, <span style="color: #2b91af">IEnumerable</span>&lt;IStory&gt; stories) {
        SiteTitle = siteTitle;
        FeedTitle = feedTitle;
        Stories = stories;
    }

    <span style="color: blue">public string </span>SiteTitle {
        <span style="color: blue">get</span>;
        <span style="color: blue">private set</span>;
    }

    <span style="color: blue">public string </span>FeedTitle {
        <span style="color: blue">get</span>;
        <span style="color: blue">private set</span>;
    }

    <span style="color: blue">public </span><span style="color: #2b91af">IEnumerable</span>&lt;IStory&gt; Stories {
        <span style="color: blue">get</span>;
        <span style="color: blue">private set</span>;
    }

    <span style="color: blue">public override void </span>ExecuteResult(<span style="color: #2b91af">ControllerContext </span>context) {
        <span style="color: blue">string </span>xml = Build(context);

        <span style="color: #2b91af">HttpResponseBase </span>response = context.HttpContext.Response;
        response.ContentType = <span style="color: #a31515">"application/atom+xml"</span>;
        response.Write(xml);
    }
}</pre>
<p>然后在控制器中就可以这样写：<a href="http://11011.net/software/vspaste"></a></p>
<pre class="code">[<span style="color: #2b91af">AcceptVerbs</span>(<span style="color: #2b91af">HttpVerbs</span>.Get), <span style="color: #2b91af">OutputCache</span>(CacheProfile = <span style="color: #a31515">"Atom"</span>)]
<span style="color: blue">public </span><span style="color: #2b91af">ActionResult </span>Shared() {
    <span style="color: #2b91af">IEnumerable</span>&lt;stories&gt; stories = GetSharedStories();

    <span style="color: blue">return new </span><span style="color: #2b91af">AtomResult</span>(<span style="color: #a31515">"My Site"</span>, <span style="color: #a31515">"My shared stories in atom"</span>, stories);
}</pre>
<h4>17. 把你的视图拆分为多个视图控件</h4>
<p>如果你的视图文件变得越来越大，那你可以考虑把它拆分为多个视图控件。至于视图空间是否在多个页面中重用，并没有关系。因为这样做可以让真正的视图文件变得更加具有可读性。考虑一下下面的视图：</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content </span><span style="color: red">ID</span><span style="color: blue">="Content1" </span><span style="color: red">ContentPlaceHolderID</span><span style="color: blue">="TitleContent" </span><span style="color: red">runat</span><span style="color: blue">="server"&gt;
    </span>My Secret App : Dashboard
<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content </span><span style="color: red">ID</span><span style="color: blue">="Content2" </span><span style="color: red">ContentPlaceHolderID</span><span style="color: blue">="MainContent" </span><span style="color: red">runat</span><span style="color: blue">="server"&gt;
    &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">="heading"&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">div </span><span style="color: red">class</span><span style="color: blue">="columns"&gt;
        &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">="main" </span><span style="color: red">class</span><span style="color: blue">="column"&gt;
            &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">="storyListTabs" </span><span style="color: red">class</span><span style="color: blue">="ui-tabs ui-widget ui-widget-content ui-corner-all"&gt;
                </span><span style="background: #ffee62">&lt;%</span> Html.RenderPartial(<span style="color: #a31515">"TabHeader"</span>, Model);<span style="background: #ffee62">%&gt;
</span>                <span style="color: blue">&lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">="tabContent" </span><span style="color: red">class</span><span style="color: blue">="ui-tabs-panel ui-widget-content ui-corner-bottom"&gt;
                    &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">="storyList"&gt;
                        </span><span style="background: #ffee62">&lt;%</span> Html.RenderPartial(<span style="color: #a31515">"SortBar"</span>, Model);<span style="background: #ffee62">%&gt;
</span>                        <span style="color: blue">&lt;</span><span style="color: #a31515">div </span><span style="color: red">class</span><span style="color: blue">="clear"&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
                        </span><span style="background: #ffee62">&lt;%</span> Html.RenderPartial(<span style="color: #a31515">"NoLinkMessage"</span>, Model);<span style="background: #ffee62">%&gt;
</span>                        <span style="color: blue">&lt;</span><span style="color: #a31515">form </span><span style="color: red">id</span><span style="color: blue">="update" </span><span style="color: red">action</span><span style="color: blue">="</span><span style="background: #ffee62">&lt;%</span>= Url.Update()<span style="background: #ffee62">%&gt;</span><span style="color: blue">" </span><span style="color: red">method</span><span style="color: blue">="post"&gt;
                            </span><span style="background: #ffee62">&lt;%</span> Html.RenderPartial(<span style="color: #a31515">"List"</span>, Model);<span style="background: #ffee62">%&gt;
</span>                            <span style="background: #ffee62">&lt;%</span> Html.RenderPartial(<span style="color: #a31515">"ActionBar"</span>, Model);<span style="background: #ffee62">%&gt;
</span>                            <span style="background: #ffee62">&lt;%</span> Html.RenderPartial(<span style="color: #a31515">"Pager"</span>, Model);<span style="background: #ffee62">%&gt;
</span>                        <span style="color: blue">&lt;/</span><span style="color: #a31515">form</span><span style="color: blue">&gt;
                    &lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
                &lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
            </span><span style="background: #ffee62">&lt;%</span>Html.RenderPartial(<span style="color: #a31515">"Submit"</span>, <span style="color: blue">new </span>StorySubmitViewModel());<span style="background: #ffee62">%&gt;
</span>        <span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">="sideBar" </span><span style="color: red">class</span><span style="color: blue">="column"&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content</span><span style="color: blue">&gt;</span></pre>
<p>继续阅读：《<a rel="next" href="http://wukangrui.net/2009/07/08/asp-net-mvc-best-practices-part-4.html">ASP.NET MVC 最佳实践（四）</a>》</p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2009-07-08 -- <a href="http://ofcss.com/2009/07/08/asp-net-mvc-best-practices-part-4.html" title="ASP.NET MVC 最佳实践（四）">ASP.NET MVC 最佳实践（四）</a></li><li>2009-07-01 -- <a href="http://ofcss.com/2009/07/01/asp-net-mvc-best-practices-part-2.html" title="ASP.NET MVC 最佳实践（二）">ASP.NET MVC 最佳实践（二）</a></li><li>2009-06-28 -- <a href="http://ofcss.com/2009/06/28/asp-net-mvc-best-practices-part-1.html" title="ASP.NET MVC 最佳实践（一）">ASP.NET MVC 最佳实践（一）</a></li><li>2009-04-13 -- <a href="http://ofcss.com/2009/04/13/aspnetmvc-hands-on-labs-develop-application.html" title="[翻译]ASP.NET MVC动手实验1-3：开发ASP.NET MVC应用">[翻译]ASP.NET MVC动手实验1-3：开发ASP.NET MVC应用</a></li><li>2009-04-09 -- <a href="http://ofcss.com/2009/04/09/aspnetmvc-hands-on-labs-create-application.html" title="[翻译]ASP.NET MVC动手实验1-2：创建ASP.NET MVC应用">[翻译]ASP.NET MVC动手实验1-2：创建ASP.NET MVC应用</a></li><li>2009-04-09 -- <a href="http://ofcss.com/2009/04/09/aspnetmvc-hands-on-labs-introduction.html" title="[翻译]ASP.NET MVC动手系列1-1：ASP.NET MVC概述">[翻译]ASP.NET MVC动手系列1-1：ASP.NET MVC概述</a></li><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-25 -- <a href="http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html" title="借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】">借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2009/07/07/asp-net-mvc-best-practices-part-3.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC 最佳实践（二）</title>
		<link>http://ofcss.com/2009/07/01/asp-net-mvc-best-practices-part-2.html</link>
		<comments>http://ofcss.com/2009/07/01/asp-net-mvc-best-practices-part-2.html#comments</comments>
		<pubDate>Tue, 30 Jun 2009 21:03:41 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[开发]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://wukangrui.net/2009/07/01/asp-net-mvc-best-practices-part-2.html</guid>
		<description><![CDATA[<p>本系列翻译自 Kazi Manzur Rashid 的博客，由于翻译水平有限，本系列可能存在误解偏差或者翻译不准的地方，建议对比原文进行阅读。由于篇幅关系，原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第一部分中的7-14节。如果你没有看过之前的第一部分，也许你想先看看 《ASP.NET MVC 最佳实践（一）》。 <a href="http://ofcss.com/2009/07/01/asp-net-mvc-best-practices-part-2.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p><em>本系列翻译自 </em><a href="http://weblogs.asp.net/rashid/default.aspx"><em>Kazi Manzur Rashid</em></a><em> 的博客，由于翻译水平有限，本系列可能存在误解偏差或者翻译不准的地方，建议对比<a href="http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx">原文</a>进行阅读。由于篇幅关系，原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第一部分中的7-14节。如果你没有看过之前的第一部分，也许你想先看看 <a rel="prev" href="http://wukangrui.net/2009/06/28/asp-net-mvc-best-practices-part-1.html">《ASP.NET MVC 最佳实践（一）》</a>。</em></p>
<p><span id="more-829"></span></p>
<h4>7. 不要在控制器中使用HttpContext类及其派生类</h4>
<p>在你的控制器中不要引用到HttpContext以及它的派生类。这让你能比较容易地进行控制器的单元测试。如果你需要访问与HttpContext相关的对象比如User、QueryString、Cookie等，你可以使用自定义的行为过滤器（<a rel="external" href="http://www.cnblogs.com/" target="_blank">博客园</a>的<a rel="external" href="http://www.cnblogs.com/JeffreyZhao/" target="_blank">老赵</a>有<a rel="external" href="http://www.cnblogs.com/JeffreyZhao/archive/2009/03/09/no-dependency-to-httpcontext.html" target="_blank">一篇文章</a>对这一条进行了深入的论述，并提出了自己的解决方案，建议阅读）或者创建一些接口和容器，并把它传入控制器的构造函数。例如，下面的路由：</p>
<pre class="code">routes.MapRoute(
    <span style="color: #a31515">"Dashboard"</span>,
    <span style="color: #a31515">"Dashboard/{tab}/{orderBy}/{page}"</span>,
    <span style="color: blue">new </span>{
        controller = <span style="color: #a31515">"Story"</span>,
        action = <span style="color: #a31515">"Dashboard"</span>,
        tab = StoryListTab.Unread.ToString(),
        orderBy = OrderBy.CreatedAtDescending.ToString(),
        page = 1
    }
);</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>而控制器的行为方法则定义为：</p>
<pre class="code">[<span style="color: #2b91af">AcceptVerbs</span>(<span style="color: #2b91af">HttpVerbs</span>.Get),<span style="color: #2b91af">OutputCache</span>(CacheProfile = <span style="color: #a31515">"Dashboard"</span>),UserNameFilter]
<span style="color: blue">public </span><span style="color: #2b91af">ActionResult </span>Dashboard(<span style="color: blue">string </span>userName, StoryListTab tab, OrderBy orderBy, <span style="color: blue">int</span>? page) {
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>UserNameFilter这个过滤器负责传递UserName：</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">UserNameFilter </span>: <span style="color: #2b91af">ActionFilterAttribute </span>{
    <span style="color: blue">public override void </span>OnActionExecuting(<span style="color: #2b91af">ActionExecutingContext </span>filterContext) {
        <span style="color: blue">const string </span>Key = <span style="color: #a31515">"userName"</span>;

        <span style="color: blue">if </span>(filterContext.ActionParameters.ContainsKey(Key)) {
            <span style="color: blue">if </span>(filterContext.HttpContext.User.Identity.IsAuthenticated) {
                filterContext.ActionParameters[Key] = filterContext.HttpContext.User.Identity.Name;
            }
        }

        <span style="color: blue">base</span>.OnActionExecuting(filterContext);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><strong>[更新：一定要明确你已经对控制器或者是对控制器中的行为添加了 Authorize 属性，参见<a rel="external" href="http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx#comments" target="_blank">原文评论</a>。]</strong></p>
<h4>8. 用行为控制器来转换行为方法参数</h4>
<p>用行为过滤器来把传入值转换为你的控制器行为方法参数，再看一下 Dashboard方法的代码，我们以 Enum 类型接受 tab 和 orderBy这两个参数。</p>
<pre class="code">[<span style="color: #2b91af">AcceptVerbs</span>(<span style="color: #2b91af">HttpVerbs</span>.Get), <span style="color: #2b91af">OutputCache</span>(CacheProfile = <span style="color: #a31515">"Dashboard"</span>), StoryListFilter]
<span style="color: blue">public </span><span style="color: #2b91af">ActionResult </span>Dashboard(<span style="color: blue">string </span>userName, StoryListTab tab, OrderBy orderBy, <span style="color: blue">int</span>? page) {
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p> </p>
<p>过滤器 StoryListFilter 将负责把它由 路由的值/查询字符串 转换为适当的数据类型。</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">StoryListFilter </span>: <span style="color: #2b91af">ActionFilterAttribute </span>{
    <span style="color: blue">public override void </span>OnActionExecuting(<span style="color: #2b91af">ActionExecutingContext </span>filterContext) {
        <span style="color: blue">const string </span>TabKey = <span style="color: #a31515">"tab"</span>;
        <span style="color: blue">const string </span>OrderByKey = <span style="color: #a31515">"orderBy"</span>;

        NameValueCollection queryString = filterContext.HttpContext.Request.QueryString;

        StoryListTab tab = <span style="color: blue">string</span>.IsNullOrEmpty(queryString[TabKey]) ?
                            filterContext.RouteData.Values[TabKey].ToString().ToEnum(StoryListTab.Unread) :
                            queryString[TabKey].ToEnum(StoryListTab.Unread);

        filterContext.ActionParameters[TabKey] = tab;

        OrderBy orderBy = <span style="color: blue">string</span>.IsNullOrEmpty(queryString[OrderByKey]) ?
                            filterContext.RouteData.Values[OrderByKey].ToString().ToEnum(OrderBy.CreatedAtDescending) :
                            queryString[OrderByKey].ToEnum(OrderBy.CreatedAtDescending);

        filterContext.ActionParameters[OrderByKey] = orderBy;

        <span style="color: blue">base</span>.OnActionExecuting(filterContext);
    }
}</pre>
<p>你也可以用自定义模型绑定器来达到同样的目的。如果要那样做的话，你需要为每个枚举创建一个独立的模型绑定器，而不是用一个行为过滤器来处理所有的枚举参数。用模型绑定器还有一个问题，一旦你注册了一个类型，在行为中它就总是被使用，而行为过滤器则是可以根据需要选择使用的。</p>
<h4>9. 行为过滤器的位置</h4>
<p>如果你要对你的控制器的所有行为方法应用同一个行为过滤器，你可以把这个过滤器放在控制器的定义上而不必给每个行为方法应用。如果你要对你的所有控制器应用同一个行为过滤器，你应该创建一个基控制器，对它应用该过滤器，并让所有的控制器继承这个基控制器。例如 story 控制器应该只在用户已经登陆的情况下才可以使用，并且我们需要把当前用户的用户名传入 story 控制器下的方法，另外Story控制器应该压缩返回的数据：</p>
<pre class="code">[<span style="color: #2b91af">Authorize</span>, <span style="color: #2b91af">UserNameFilter</span>]
<span style="color: blue">public class </span><span style="color: #2b91af">StoryController </span>: <span style="color: #2b91af">BaseController </span>{
}

[CompressFilter]
<span style="color: blue">public class </span><span style="color: #2b91af">BaseController </span>: <span style="color: #2b91af">Controller </span>{
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>但是如果继承的层次达到或者高于2层，应该另找方法来应用过滤器。最新的 <a rel="external" href="http://oxite.codeplex.com/" target="_blank">Oxite</a> 代码里有一些非常出色的动态应用过滤器的方法，我强烈推荐你去看一下。</p>
<h4>10. 小心使用UpdateModel</h4>
<p>我要再次强调 Justin Ethredge 在他的文章中已经提过的这个问题，开发中一定小心，避免陷进UpdateModel的陷阱里去。</p>
<h4>11.控制器不要包含任何域逻辑</h4>
<p>控制器应该只负责：</p>
<ul>
<li>验证输入</li>
<li>调用Model层来为显示视图准备数据</li>
<li>返回视图或者跳转到另一个行为</li>
</ul>
<p>如果你在控制器中坐了其它的事情，那就说明你把它们放错了地方。你在控制器中坐的这些事情或许更应该交给模型去处理。只要你遵守了这条规则，你的每个控制器方法代码应该不会超过20到25行。 <a rel="external" href="http://codebetter.com/blogs/ian_cooper/default.aspx" target="_blank">Ian Cooper</a> 有一篇很棒的文章《<a rel="external" href="http://codebetter.com/blogs/ian_cooper/archive/2008/12/03/the-fat-controller.aspx" target="_blank">Skin Controller Fat Model</a>》，有空的时候你一定要读一下。</p>
<h4>12. 避免使用 ViewData，尽量使用ViewData.Model</h4>
<p>依赖于数据字典不仅使你的代码难以重构，而且你还不得不在试图中编写转换代码。实际上即使你给你的控制器的每个方法都单独编写一个类作为数据模型，那也是完全可以的。如果你觉得编写这些视图数据模型类是一项非常乏味的工作的话，你可以使用 MVCContrib 项目中 ViewDataExtensions，它包含一些用于返回强类型对象的不错的扩展。但是如果你的视图数据的数据字典中包含了多个数据类型的话，你还是没办法摆脱数据字典和他的字符串名。</p>
<h4>13. 用 PRG 模式来修改数据</h4>
<p>Tim Barcz, Matt Hawley, Stephen Wather 甚至 Scott Gu 都写了这方面的文章，你可以在 <a rel="external" href="http://devlicio.us/blogs/tim_barcz/archive/2008/08/22/prg-pattern-in-the-asp-net-mvc-framework.aspx" target="_blank">这里</a>、<a rel="external" href="http://blog.eworldui.net/post/2008/05/ASPNET-MVC---Using-Post2c-Redirect2c-Get-Pattern.aspx" target="_blank">这里</a>、<a rel="external" href="http://stephenwalther.com/blog/archive/2008/06/20/asp-net-mvc-tip-6-call-redirecttoaction-after-submitting-a-form.aspx" target="_blank">这里</a>和<a rel="external" href="http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx" target="_blank">这里</a>找到它们。这个模式的一个问题是当一项验证失败或者发生任何错误的时候，你不得不把ModelState复制到TempData里面。如果你是手动来做这件事，请不要再那样做了，你可以用行为过滤器自动处理它，就像下面这样：</p>
<pre class="code">[<span style="color: #2b91af">AcceptVerbs</span>(<span style="color: #2b91af">HttpVerbs</span>.Get), <span style="color: #2b91af">OutputCache</span>(CacheProfile = <span style="color: #a31515">"Dashboard"</span>), StoryListFilter, ImportModelStateFromTempData]
<span style="color: blue">public </span><span style="color: #2b91af">ActionResult </span>Dashboard(<span style="color: blue">string </span>userName, StoryListTab tab, OrderBy orderBy, <span style="color: blue">int</span>? page)
{
    <span style="color: green">//Other Codes
    </span><span style="color: blue">return </span>View();
}

[<span style="color: #2b91af">AcceptVerbs</span>(<span style="color: #2b91af">HttpVerbs</span>.Post), ExportModelStateToTempData]
<span style="color: blue">public </span><span style="color: #2b91af">ActionResult </span>Submit(<span style="color: blue">string </span>userName, <span style="color: blue">string </span>url)
{
    <span style="color: blue">if </span>(ValidateSubmit(url))
    {
        <span style="color: blue">try
        </span>{
            _storyService.Submit(userName, url);
        }
        <span style="color: blue">catch </span>(Exception e)
        {
            ModelState.AddModelError(ModelStateException, e);
        }
    }

    <span style="color: blue">return </span>Redirect(Url.Dashboard());
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>还有行为过滤器的代码：</p>
<pre class="code"><span style="color: blue">public abstract class </span><span style="color: #2b91af">ModelStateTempDataTransfer </span>: <span style="color: #2b91af">ActionFilterAttribute </span>{
    <span style="color: blue">protected static readonly string </span>Key = <span style="color: blue">typeof</span>(<span style="color: #2b91af">ModelStateTempDataTransfer</span>).FullName;
}

<span style="color: blue">public class </span><span style="color: #2b91af">ExportModelStateToTempData </span>: <span style="color: #2b91af">ModelStateTempDataTransfer </span>{
    <span style="color: blue">public override void </span>OnActionExecuted(<span style="color: #2b91af">ActionExecutedContext </span>filterContext) {
        <span style="color: green">//Only export when ModelState is not valid
        </span><span style="color: blue">if </span>(!filterContext.Controller.ViewData.ModelState.IsValid) {
            <span style="color: green">//Export if we are redirecting
            </span><span style="color: blue">if </span>((filterContext.Result <span style="color: blue">is </span><span style="color: #2b91af">RedirectResult</span>) || (filterContext.Result <span style="color: blue">is </span><span style="color: #2b91af">RedirectToRouteResult</span>)) {
                filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;
            }
        }

        <span style="color: blue">base</span>.OnActionExecuted(filterContext);
    }
}

<span style="color: blue">public class </span><span style="color: #2b91af">ImportModelStateFromTempData </span>: <span style="color: #2b91af">ModelStateTempDataTransfer </span>{
    <span style="color: blue">public override void </span>OnActionExecuted(<span style="color: #2b91af">ActionExecutedContext </span>filterContext) {
        <span style="color: #2b91af">ModelStateDictionary </span>modelState = filterContext.Controller.TempData[Key] <span style="color: blue">as </span><span style="color: #2b91af">ModelStateDictionary</span>;

        <span style="color: blue">if </span>(modelState != <span style="color: blue">null</span>) {
            <span style="color: green">//Only Import if we are viewing
            </span><span style="color: blue">if </span>(filterContext.Result <span style="color: blue">is </span><span style="color: #2b91af">ViewResult</span>) {
                filterContext.Controller.ViewData.ModelState.Merge(modelState);
            } <span style="color: blue">else </span>{
                <span style="color: green">//Otherwise remove it.
                </span>filterContext.Controller.TempData.Remove(Key);
            }
        }

        <span style="color: blue">base</span>.OnActionExecuted(filterContext);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p><a rel="external" href="http://mvccontrib.codeplex.com" target="_blank">MVCContrib</a> 项目也有这个功能，但是我不喜欢他们在用一个单独类来处理的方式，我喜欢对“哪个方法输出”和“哪个方法输入”有更多的控制权。</p>
<h4>14. 为你的视图模型创建父类层并用行为过滤器来构成公共部分</h4>
<p>为你的视图模型类编写一个父类层，并用过滤器来构成它的公共部分。例如我正在开发的这个非常小的应用程序，我需要知道用户是否已经认证，已及用户名。</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">ViewModel </span>{
    <span style="color: blue">public bool </span>IsUserAuthenticated {
        <span style="color: blue">get</span>;
        <span style="color: blue">set</span>;
    }

    <span style="color: blue">public string </span>UserName {
        <span style="color: blue">get</span>;
        <span style="color: blue">set</span>;
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>还有行为过滤器的代码：</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">UserNameFilter </span>: <span style="color: #2b91af">ActionFilterAttribute </span>{
    <span style="color: blue">public override void </span>OnActionExecuting(<span style="color: #2b91af">ActionExecutingContext </span>filterContext) {
        <span style="color: blue">const string </span>Key = <span style="color: #a31515">"userName"</span>;

        <span style="color: blue">if </span>(filterContext.ActionParameters.ContainsKey(Key)) {
            <span style="color: blue">if </span>(filterContext.HttpContext.User.Identity.IsAuthenticated) {
                filterContext.ActionParameters[Key] = filterContext.HttpContext.User.Identity.Name;
            }
        }

        <span style="color: blue">base</span>.OnActionExecuting(filterContext);
    }
}

<span style="color: blue">public class </span><span style="color: #2b91af">ViewModelUserFilter </span>: <span style="color: #2b91af">ActionFilterAttribute </span>{
    <span style="color: blue">public override void </span>OnActionExecuted(<span style="color: #2b91af">ActionExecutedContext </span>filterContext) {
        ViewModel model;

        <span style="color: blue">if </span>(filterContext.Controller.ViewData.Model == <span style="color: blue">null</span>) {
            model = <span style="color: blue">new </span>ViewModel();
            filterContext.Controller.ViewData.Model = model;
        } <span style="color: blue">else </span>{
            model = filterContext.Controller.ViewData.Model <span style="color: blue">as </span>ViewModel;
        }

        <span style="color: blue">if </span>(model != <span style="color: blue">null</span>) {
            model.IsUserAuthenticated = filterContext.HttpContext.User.Identity.IsAuthenticated;

            <span style="color: blue">if </span>(model.IsUserAuthenticated) {
                model.UserName = filterContext.HttpContext.User.Identity.Name;
            }
        }

        <span style="color: blue">base</span>.OnActionExecuted(filterContext);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>正如你所看到的，如果在控制器里预先设定它的话，它并没有替换模型，而是在它发现模型与它符合的时候，才作为控制器的公共部分起作用。另一个好处是，由于视图只依赖于父类层，你可以不必返回具体的model，而只需要返回 View()。</p>
<p>继续阅读：《<a rel="prev" href="http://wukangrui.net/2009/07/07/asp-net-mvc-best-practices-part-1-2.html">ASP.NET MVC 最佳实践（三）</a>》</p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2009-07-08 -- <a href="http://ofcss.com/2009/07/08/asp-net-mvc-best-practices-part-4.html" title="ASP.NET MVC 最佳实践（四）">ASP.NET MVC 最佳实践（四）</a></li><li>2009-07-07 -- <a href="http://ofcss.com/2009/07/07/asp-net-mvc-best-practices-part-3.html" title="ASP.NET MVC 最佳实践（三）">ASP.NET MVC 最佳实践（三）</a></li><li>2009-06-28 -- <a href="http://ofcss.com/2009/06/28/asp-net-mvc-best-practices-part-1.html" title="ASP.NET MVC 最佳实践（一）">ASP.NET MVC 最佳实践（一）</a></li><li>2009-04-13 -- <a href="http://ofcss.com/2009/04/13/aspnetmvc-hands-on-labs-develop-application.html" title="[翻译]ASP.NET MVC动手实验1-3：开发ASP.NET MVC应用">[翻译]ASP.NET MVC动手实验1-3：开发ASP.NET MVC应用</a></li><li>2009-04-09 -- <a href="http://ofcss.com/2009/04/09/aspnetmvc-hands-on-labs-create-application.html" title="[翻译]ASP.NET MVC动手实验1-2：创建ASP.NET MVC应用">[翻译]ASP.NET MVC动手实验1-2：创建ASP.NET MVC应用</a></li><li>2009-04-09 -- <a href="http://ofcss.com/2009/04/09/aspnetmvc-hands-on-labs-introduction.html" title="[翻译]ASP.NET MVC动手系列1-1：ASP.NET MVC概述">[翻译]ASP.NET MVC动手系列1-1：ASP.NET MVC概述</a></li><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-25 -- <a href="http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html" title="借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】">借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2009/07/01/asp-net-mvc-best-practices-part-2.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC 最佳实践（一）</title>
		<link>http://ofcss.com/2009/06/28/asp-net-mvc-best-practices-part-1.html</link>
		<comments>http://ofcss.com/2009/06/28/asp-net-mvc-best-practices-part-1.html#comments</comments>
		<pubDate>Sun, 28 Jun 2009 06:18:23 +0000</pubDate>
		<dc:creator>小李刀刀</dc:creator>
				<category><![CDATA[所谓技术]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[开发]]></category>
		<category><![CDATA[最佳实践]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://wukangrui.net/2009/06/28/asp-net-mvc-best-practices-part-1.html</guid>
		<description><![CDATA[<p>本系列翻译自 Kazi Manzur Rashid 的博客，由于翻译水平有限，本系列可能存在误解偏差或者翻译不准的地方，建议对比原文进行阅读。由于篇幅关系，原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第一部分中的1-6节。 <a href="http://ofcss.com/2009/06/28/asp-net-mvc-best-practices-part-1.html">Continue reading <span class="meta-nav">&#8594;</span></a></p>
]]></description>
			<content:encoded><![CDATA[<p><em>本系列翻译自 </em><a rel="external" href="http://weblogs.asp.net/rashid/default.aspx" target="_blank"><em>Kazi Manzur Rashid</em></a><em> 的博客，由于翻译水平有限，本系列可能存在误解偏差或者翻译不准的地方，建议对比<a rel="external" href="http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx" target="_blank">原文</a>进行阅读。由于篇幅关系，原文中的一篇文章在本系列中将拆解成多篇发布。本篇包括原文第一部分中的1-6节。</em></p>
<p><span id="more-821"></span></p>
<h4>1. 创建UrlHelper的扩展方法来生成url</h4>
<p>尽量避免以字符串方式直接传递controller, action 或者 route name，最好是为创建为UrlHelper创建扩展方法来封装url。例如：</p>
<pre class="code"><span style="color: blue">public static class </span><span style="color: #2b91af">UrlHelperExtension </span>{
    <span style="color: blue">public static string </span>Home(<span style="color: blue">this </span>UrlHelper helper) {
        <span style="color: blue">return </span>helper.Content(<span style="color: #a31515">"~/"</span>);
    }

    <span style="color: blue">public static string </span>SignUp(<span style="color: blue">this </span>UrlHelper helper) {
        <span style="color: blue">return </span>helper.RouteUrl(<span style="color: #a31515">"Signup"</span>);
    }

    <span style="color: blue">public static string </span>Dashboard(<span style="color: blue">this </span>UrlHelper helper) {
        <span style="color: blue">return </span>Dashboard(helper, StoryListTab.Unread);
    }

    <span style="color: blue">public static string </span>Dashboard(<span style="color: blue">this </span>UrlHelper helper, StoryListTab tab) {
        <span style="color: blue">return </span>Dashboard(helper, tab, OrderBy.CreatedAtDescending, 1);
    }

    <span style="color: blue">public static string </span>Dashboard(<span style="color: blue">this </span>UrlHelper helper, StoryListTab tab, OrderBy orderBy, <span style="color: blue">int </span>page) {
        <span style="color: blue">return </span>helper.RouteUrl(<span style="color: #a31515">"Dashboard"</span>, <span style="color: blue">new </span>{ tab = tab.ToString(), orderBy = orderBy.ToString(), page });
    }

    <span style="color: blue">public static string </span>Update(<span style="color: blue">this </span>UrlHelper helper) {
        <span style="color: blue">return </span>helper.RouteUrl(<span style="color: #a31515">"Update"</span>);
    }

    <span style="color: blue">public static string </span>Submit(<span style="color: blue">this </span>UrlHelper helper) {
        <span style="color: blue">return </span>helper.RouteUrl(<span style="color: #a31515">"Submit"</span>);
    }
}</pre>
<p>这样，如果在你的视图中有类似这样的代码：</p>
<pre class="code">    <span style="background: #ffee62">&lt;%</span><span style="color: blue">= </span>Html.ActionLink(<span style="color: #a31515">"Dashboard"</span>, <span style="color: #a31515">"Dashboard"</span>, <span style="color: #a31515">"Story"</span>) <span style="background: #ffee62">%&gt;
</span>    <span style="color: blue">&lt;</span><span style="color: #a31515">a </span><span style="color: red">href</span><span style="color: blue">="</span><span style="background: #ffee62">&lt;%</span>= Url.RouteUrl("Profile")<span style="background: #ffee62">%&gt;</span><span style="color: blue">"&gt;</span>Profile<span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></pre>
<p>你就可以用下面的这种方式来代替它们：</p>
<p><a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">a </span><span style="color: red">href</span><span style="color: blue">="</span><span style="background: #ffee62">&lt;%</span>= Url.Dashboard() <span style="background: #ffee62">%&gt;</span><span style="color: blue">"&gt;</span>Dashboard<span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;
&lt;</span><span style="color: #a31515">a </span><span style="color: red">href</span><span style="color: blue">="</span><span style="background: #ffee62">&lt;%</span>= Url.Profile() <span style="background: #ffee62">%&gt;</span><span style="color: blue">"&gt;</span>Profile<span style="color: blue">&lt;/</span><span style="color: #a31515">a</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>在控制器里也可以用，原来的代码：</p>
<pre class="code"><span style="color: blue">return </span>RedirectToAction(
    <span style="color: #a31515">"Dashboard"</span>,
    <span style="color: #a31515">"Story"</span>,
    <span style="color: blue">new </span>{
        tab = StoryListTab.Favorite,
        orderBy = OrderBy.CreatedAtAscending,
        page = 1
    }
);</pre>
<p>可以写成：</p>
<pre class="code"><span style="color: blue">return </span>Redirect(Url.Dashboard(StoryListTab.Favorite,
                                OrderBy.CreatedAtAscending, 1));</pre>
<p>当然了，你也可以使用 <a rel="external" href="http://www.tampadev.org/News/Details/DownloadASPNETMVCFuturesMicrosoftWebMvcAssembly" target="_blank">future assembly</a> 中的强类型版本来获得控制器、方法以及参数值，或者创建你自己的强类型版本以免将来进行重构时太过于痛苦，但是请一定记住，它没有官方支持并且将来有可能会发生改变。上面的方式也可以和强类型版本搭配使用。当然“另外增加一个间接层”（Scott Ha 喜欢用的引语）有一些好处，在编写单元测试的时候还有一个好处是你只需处理 <a rel="tag" href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.redirectresult.aspx" target="_blank">RedirectResult</a> 而无须同时处理 RedirectResult 和 <a rel="tag" href="http://msdn.microsoft.com/zh-cn/library/system.web.mvc.redirecttorouteresult.aspx" target="_blank">RedirectToRouteResult</a>。</p>
<h4>2. Create Extension Method of UrlHelper to map your JavaScript, Stylesheet and Image Folder</h4>
<p>默认情况下 <a rel="tag" href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> 创建Content、Scripts文件夹来做这些事，这一点我不喜欢，我更喜欢下面的这种文件夹结构，这样在IIS里我可以只让静态文件缓存在Assets文件夹而不是多个文件夹：</p>
<ul>
<li>Assets</li>
<li>+images</li>
<li>+scripts</li>
<li>+stylesheets</li>
</ul>
<p>无论是结构是什么样的，还是要为UrlHelper创建一些扩展方法来映射这些文件夹，以便你在视图中可以很方便地指向它们，这样以后如果你要改变目录结构，你就无须做大量查找替换的工作。我还建议你为所有经常在视图中用到的资源创建UrlHelper的扩展方法。例如：</p>
<pre class="code"><span style="color: blue">public static string </span>Image(<span style="color: blue">this </span>UrlHelper helper, <span style="color: blue">string </span>fileName) {
    <span style="color: blue">return </span>helper.Content(<span style="color: #a31515">"~/assets/images/{0}"</span>.FormatWith(fileName));
}

<span style="color: blue">public static string </span>Stylesheet(<span style="color: blue">this </span>UrlHelper helper, <span style="color: blue">string </span>fileName) {
    <span style="color: blue">return </span>helper.Content(<span style="color: #a31515">"~/assets/stylesheets/{0}"</span>.FormatWith(fileName));
}

<span style="color: blue">public static string </span>NoIcon(<span style="color: blue">this </span>UrlHelper helper) {
    <span style="color: blue">return </span>Image(helper, <span style="color: #a31515">"noIcon.png"</span>);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>然后当需要用到这些路径的时候，原来的代码</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">link </span><span style="color: red">href</span><span style="color: blue">="../../Content/Site.css" </span><span style="color: red">rel</span><span style="color: blue">="stylesheet" </span><span style="color: red">type</span><span style="color: blue">="text/css" /&gt;</span></pre>
<p>就可以写成这样：<a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">link </span><span style="color: red">href</span><span style="color: blue">="</span><span style="background: #ffee62">&lt;%</span>= Url.Stylesheet("site.css")<span style="background: #ffee62">%&gt;</span><span style="color: blue">" </span><span style="color: red">rel</span><span style="color: blue">="stylesheet" </span><span style="color: red">type</span><span style="color: blue">="text/css" /&gt;</span></pre>
<h4>3. 中使用启动加载器</h4>
<p>我在<a rel="prev" href="http://weblogs.asp.net/rashid/archive/2009/02/17/use-bootstrapper-in-your-asp-net-mvc-application-and-reduce-code-smell.aspx" target="_blank">以前的文章</a>中已经提到过这一点，总的来说就是：如果你要在 Global.asax 的 Application_Start 中做很多处理，比如 注册路由规则(Routers)、注册控制器工厂(Controller Factory)、模型绑定(Model Binders)、视图引擎(View Engine)、启动程序级的特定<a rel="external" href="http://weblogs.asp.net/rashid/archive/2009/03/05/use-event-aggregator-to-make-your-application-more-extensible.aspx" target="_blank">后台服务</a>或者为特定部分创建独立任务等，那就用<a rel="prev" href="http://weblogs.asp.net/rashid/archive/2009/03/05/use-event-aggregator-to-make-your-application-more-extensible.aspx" target="_blank">启动加载器</a>来执行这些操作。这会让你的代码更简洁，更可测。这一点在用 <a rel="tag" href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> 构建门户级应用时尤其有用，因为这类应用中的每个模块都可能有一些不影响到其他模块的启动初始化操作。但是如果你只是开发一个小应用，上面提到的这些对你来说都不是问题，你当然也可以继续用默认的 global.asax。</p>
<h4>4. 不要硬编码对依赖注入容器的调用，用通用服务定位器来代替。</h4>
<p>不要让任何特定的依赖注入容器(DI Container)打乱你的代码，更好的办法是使用通用服务定位器(<a rel="external" href="http://commonservicelocator.codeplex.com/" target="_blank">Common Service Locator</a>)，它是对底层依赖注入进行的抽象，已经支持几乎所有流行的依赖注入容器，它让你可以任意替换底层的依赖注入对象而无须修改代码，因为每个依赖注入容器都具有一些不同于其它容器的特性。<a rel="external" href="http://devlicio.us/blogs/tim_barcz/" target="_blank">Tim Barcz</a> 最近写了一篇关于这个话题的<a rel="external" href="http://devlicio.us/blogs/tim_barcz/archive/2009/03/29/your-ioc-container-choice-is-not-a-feature-of-your-application.aspx" target="_blank">很棒的文章</a>，我不太明白他为什么没有提到我们对我们偏爱的依赖注入容器有多痴迷。通用服务定位器对绝大部分常用情景都提供了支持，而对一些特殊情况比如对已实体化对象的依赖注入，我印象里有 <a rel="external" href="http://codebetter.com/blogs/jeremy.miller/archive/2009/01/16/quot-buildup-quot-existing-objects-with-structuremap.aspx" target="_blank">StructureMap</a>、<a rel="external" href="http://codeclimber.net.nz/archive/2009/02/10/how-to-use-ninject-to-inject-dependencies-into-asp.net-mvc.aspx" target="_blank">Ninject</a> 和 Unity，你可以调用静态方法 ServiceLocator.Current.GetInstance 来代替。 通用服务定位器 是 <a rel="external" href="http://codebetter.com/blogs/jeremy.miller/archive/2008/08/16/it-s-time-for-ioc-container-detente.aspx" target="_blank">Jeremy D Miller</a> 发起的 依赖注入容器开发者(the DI Containers creators)的集体作品。</p>
<p>用通用服务定位器创建控制器工厂非常容易：</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">CommonServiceLocatorControllerFactory </span>: <span style="color: #2b91af">DefaultControllerFactory </span>{
    <span style="color: blue">protected override </span><span style="color: #2b91af">IController </span>GetControllerInstance(<span style="color: #2b91af">Type </span>controllerType) {
        <span style="color: blue">return </span>(controllerType == <span style="color: blue">null</span>) ? <span style="color: blue">base</span>.GetControllerInstance(controllerType) : ServiceLocator.Current.GetInstance(controllerType) <span style="color: blue">as </span><span style="color: #2b91af">IController</span>;
    }
}</pre>
<p>我希望 MVCContrib 的成员们也用这样的方式，而不是为每个容器创建一个独立的控制器工厂。</p>
<h4>5. 用恰当的的AcceptVerbs属性来修饰你的控制器方法</h4>
<p><a rel="tag" href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> 比 Web Forms 更容易遭受攻击。所以务必让对数据进行修改的控制器方法只接受 Post 方式请求（HttpVerbs.Post）。如果安全对你来说至关重要，你还可以用 ValidateAntiForgeryToken 或者 Captcha。我强烈推荐 <a rel="external" href="http://devlicio.us/blogs/derik_whittaker/" target="_blank">Derik Whittaker</a> 写的一篇 <a rel="external" href="http://devlicio.us/blogs/derik_whittaker/archive/2008/12/02/using-recaptcha-with-asp-net-mvc.aspx" target="_blank">很好的文章</a> 以及<a rel="external" href="http://www.dimecasts.net/Casts/CastDetails/76" target="_blank">视频</a>介绍了怎么把 reCaptcha 整合到 <a rel="tag" href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> 应用程序（作者注：不要错过了 <a rel="external" href="http://www.dimecasts.net/" target="_blank">DimeCasts.net</a> 的另一个短片，我从中学到了很多）。我的经验法则是对所有数据修改方法使用 HttpVerbs.Post，对所有数据读取操作使用 HttpVerbs.Get。</p>
<h4>6. 用OutputCache修饰你的频繁调用的操作方法</h4>
<p>当你需要返回不频繁更新的数据时使用 OutputCache 属性，最常见的例子是首页、Feed等。你在返回Html以及Json数据类型的方法中都可以使用这个属性。在使用的时候，注意只指定CacheProfile参数，不要指定任何其它东西，用 web.config 输出缓存控制节可以很好地调整它。例如：</p>
<pre class="code">[<span style="color: #2b91af">AcceptVerbs</span>(<span style="color: #2b91af">HttpVerbs</span>.Get), <span style="color: #2b91af">OutputCache</span>(CacheProfile = <span style="color: #a31515">"Dashboard"</span>)]
<span style="color: blue">public </span><span style="color: #2b91af">ActionResult </span>Dashboard(<span style="color: blue">string </span>userName, StoryListTab tab, OrderBy orderBy, <span style="color: blue">int</span>? page) {
}</pre>
<p>在 web.config 文件中的配置：<a href="http://11011.net/software/vspaste"></a></p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">caching</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">outputCacheSettings</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">outputCacheProfiles</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">clear</span><span style="color: blue">/&gt;
                &lt;!-- </span><span style="color: green">15 Seconds </span><span style="color: blue">--&gt;
                &lt;</span><span style="color: #a31515">add
                    </span><span style="color: red">name</span><span style="color: blue">=</span>"<span style="color: blue">Dashboard</span>"
                    <span style="color: red">duration</span><span style="color: blue">=</span>"<span style="color: blue">15</span>"
                    <span style="color: red">varyByParam</span><span style="color: blue">=</span>"<span style="color: blue">*</span>"
                    <span style="color: red">location</span><span style="color: blue">=</span>"<span style="color: blue">Client</span>"
                    <span style="color: blue">/&gt;
            &lt;/</span><span style="color: #a31515">outputCacheProfiles</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">outputCacheSettings</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">caching</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span></pre>
<p>请继续阅读：《<a rel="next" href="http://wukangrui.net/2009/07/01/asp-net-mvc-best-practices-part-2.html">ASP.NET MVC 最佳实践（二）</a>》</p>
<h3  class="related_post_title">相关日志</h3><ul class="related_post"><li>2009-07-08 -- <a href="http://ofcss.com/2009/07/08/asp-net-mvc-best-practices-part-4.html" title="ASP.NET MVC 最佳实践（四）">ASP.NET MVC 最佳实践（四）</a></li><li>2009-07-07 -- <a href="http://ofcss.com/2009/07/07/asp-net-mvc-best-practices-part-3.html" title="ASP.NET MVC 最佳实践（三）">ASP.NET MVC 最佳实践（三）</a></li><li>2009-07-01 -- <a href="http://ofcss.com/2009/07/01/asp-net-mvc-best-practices-part-2.html" title="ASP.NET MVC 最佳实践（二）">ASP.NET MVC 最佳实践（二）</a></li><li>2009-04-13 -- <a href="http://ofcss.com/2009/04/13/aspnetmvc-hands-on-labs-develop-application.html" title="[翻译]ASP.NET MVC动手实验1-3：开发ASP.NET MVC应用">[翻译]ASP.NET MVC动手实验1-3：开发ASP.NET MVC应用</a></li><li>2009-04-09 -- <a href="http://ofcss.com/2009/04/09/aspnetmvc-hands-on-labs-create-application.html" title="[翻译]ASP.NET MVC动手实验1-2：创建ASP.NET MVC应用">[翻译]ASP.NET MVC动手实验1-2：创建ASP.NET MVC应用</a></li><li>2009-04-09 -- <a href="http://ofcss.com/2009/04/09/aspnetmvc-hands-on-labs-introduction.html" title="[翻译]ASP.NET MVC动手系列1-1：ASP.NET MVC概述">[翻译]ASP.NET MVC动手系列1-1：ASP.NET MVC概述</a></li><li>2011-03-14 -- <a href="http://ofcss.com/2011/03/14/browser-rendering-optimizer-translation-extra.html" title="对《优化浏览器渲染》的补充【译】">对《优化浏览器渲染》的补充【译】</a></li><li>2011-03-10 -- <a href="http://ofcss.com/2011/03/10/css-border-tricks-with-collapsed-boxes-translation.html" title="CSS边框实现&ldquo;无图化&rdquo;设计【译】">CSS边框实现&ldquo;无图化&rdquo;设计【译】</a></li><li>2010-10-31 -- <a href="http://ofcss.com/2010/10/31/prevent-a-float-drop-in-ie6-translation.html" title="CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】">CSS技巧:如何避免IE6中的&quot;浮动下坠&quot;【译】</a></li><li>2010-10-25 -- <a href="http://ofcss.com/2010/10/25/understanding-user-behavior-google-analytics-event-tracking-jquer.html" title="借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】">借助jQuery和Google分析服务的事件追踪深入了解用户行为【译】</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://ofcss.com/2009/06/28/asp-net-mvc-best-practices-part-1.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

