最佳实践系列:前端代码标准
@窝窝商城前端(刘轶/李晨/徐利/穆尚)翻译于2012年 版本0.55 @郑昀校对
isobar的这个前端代码标准和最佳实践文档,涵盖了Web应用开发的方方面面,我们翻译了大部分章节,并做了注解。请仔细阅读用 标记的段落。
关键词列表:
渐进增强; Combo Handler; Quirks Mode; 浏览器盒子模型; 选择器特殊性; Spacer Image; CSS Sprites; PNG8;
编写此文档的目的主要有两方面,第一,如何保持代码的一致性;第二,什么才是最佳实践。我们通过编码风格和约定保持一致,可以减轻代码维护的工作量,并降低风险,在将来代码出现问题的时候,方便我们排查错误。我们要保持最佳的编码习惯和做法,确保优化页面的加载和性能,并能更好地维护代码。
前端开发的核心
1、 结构、表现、行为应该分离 。
2、 结构良好的、语义化和 有效的HTML标记。
3、 Javascript脚本的 渐进增强 !
注: 渐进增强(Progressive Enhancement)
名词定义: 渐进增强是从一个功能可用的基本版本出发,然后逐步增加用户体验的丰富程度,并在应用增强功能之前先测试对该功能的支持性;最基本的可用性出发,在保证站点页面在低级浏览器中的可用性和可访问性的基础上,逐步增加功能及提高用户体验。辅助阅读: http://www.ryanbay.com/?p=97
一般性实践
缩进
对于所有代码语言,我们需要通过TAB缩进进行代码排版(使用空格字符),在文本编辑器击中 TAB应相当于 四个空格。
可读性 vs 压缩
我们在代码可读性和文件大小的取舍中,更倾向于良好的可读性。
在合适的地方,我们鼓励使用大量的缩进、换行来维持文件代码的可读性。开发者不需要刻意地压缩文件的体积大小,也不需要混淆使用JavaScript 。
我们将使用服务器端或发布过程中自动minify和gzip的所有静态客户端文件 ,如CSS和JavaScript。
注:一般采用服务端的 Combo Handler 来对服务器端上传的未压缩、未混淆的JS和CSS文件做统一合并、压缩和混淆。
标记定义了结构和轮廓的文档,并提供了一个结构化内容。
标记并不打算定义的外观和视觉表现,只用于感知网页的基本概念,如标题、段落、列表。HTML标记中表现样式的属性都应被弃用,样式的表现应该包含在 样式表里。
HTML5
我们将在适当的时候使用HTML5 Doctype和HTML5特性。
我们将用 W3C验证器测试我们的标记,以确保格式良好。100%有效的代码并不是我们的目标,但W3C验证确实有助于编写更易于维护的网站以及调试代码。Isobar不保证代码是100%有效,而是确保跨浏览器有统一的浏览体验。
模板
对于HTML5文档,我们将定制 H5BP。
文档类型
应该始终使用一个合适的 Doctype 来触发浏览器的标准模式 。
我们 应该始终避免 Quirks Mode (怪异模式或兼容模式)。
HTML5的一个好的方面是,它简化了所需的代码量。无意义的属性已经有所下降,而且已大大简化了 Doctype 声明。因此 建议文档类型应声明为 HTML5 的形式。
HTML5 Doctype
1.
<!DOCTYPE html>
注: 怪异模式( quirks mode)
名词定义:指在计算机领域中,一些网页浏览器为了维持对较旧的网页设计的向后兼容性,而使用的一种技术,有别于严格遵循万维网联盟(W3C)与互联网工程任务组(IETF)标准而设计的「标准模式」。
为了与可能数量众多的网页维持兼容,现代的网页浏览器一般具有多种渲染模式:在「标准模式」(standards mode) 页面按照 HTML 与 CSS 的定义渲染,而在「quirks 模式」中则尝试模拟更旧的浏览器的行为。
在 quirks 模式和标准模式之间一个突出的不同是对 CSS IE盒模型缺陷的处理。
参考资料: What happens in Quirks Mode?
DOCTYPE 声明 |
说明 |
IE8 |
FF |
Chrome |
<!DOCTYPE HTML> |
HTML5推荐的方式 |
CSS1Compat |
CSS1Compat |
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
严格模式声明并给出DTD URL |
CSS1Compat |
CSS1Compat |
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> |
严格模式声明但不给出DTD URL |
CSS1Compat |
CSS1Compat |
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
过渡模式并给出DTD URL |
CSS1Compat |
CSS1Compat |
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
过渡模式但不给出DTD URL |
BackCompat |
BackCompat |
字符编码
所有标记都应设置为utf –8 。它应该同时指定在HTTP 报头和文档头部。
1.
<
meta
http-equiv
=
"Content-Type"
content
=
"text/html; charset=UTF-8"
/>
In HTML5, just do:
1.
<
meta
charset
=
"utf-8"
>
通用标记指南
以下是一般指南,用于构建你的HTML标记。
正确的表格:
引号属性
虽然HTML5规范定义了在那些可以自动识别空格的属性周围添加引号作为可选属性,但是所有的属性都应该添加引号。
1.
<
p
class
=
"line note"
data-attribute
=
"106"
>This is my paragraph of special text.</
p
>
Web页面的第二个组件是包含在样式表(Cascading Style Sheet,CSS)里的展示信息。
一般性编码原则
div#myid
)或类选择器(如 table.results
.)。这些之所以特别重要,是因为在Web应用程序中速度是至关重要的,可能有数以千计甚至数以万计的DOM元素需要被渲染。更多细节请参考: 在MDC上编写高效的CSS。
浏览器盒子模型
深入了解CSS和浏览器盒子模型(browser-based box model)是做好CSS布局非常必要的一个条件。
CSS校验
我们不使用 w3c的css校验器。
CSS格式化
我们应该保证,至少每一个选择器应该在单独的一行。声明应该是缩进的。
Classes vs. IDs
如果一些元素是文档中独一无二的,那么你应该只给他们一个ID属性。CLASS则是应用在具备同样属性样式的多个元素上。
选择器的命名规范
无论是ID选择器还是类选择器,我们应该遵循“ 它是什么( what it is )”而不是“ 它是什么样子的( what it looks like )”的原则进行命名 。例如:一个class命名为 bigBlueText,如果它后来被改为了红色的小字体,那么该class命名就失去了意义,让人不好理解。
如果我们命名为 noteText,无论如何改变外观,它仍然是一个文本框,仍然有意义。
选择器( Selectors)
CSS Selectors Level 3规格说明书里介绍了一整套CSS选择器,非常有用。
Pseudo-classes
伪类( Pseudo-classes)能动态化样式内容。一些伪类从CSS1就存在了,如 :visited, :hover
,有些从CSS2就存在了,如:first-child, :lang
。CSS3引入了16个伪类,都非常有用,请深入学习一下 它们的用法。
特殊性(Specificity)
浏览器会计算一个选择器的权重,来决定应用哪一个CSS规则。如果两个选择器都要应用到一个元素上,那么特殊性更高的选择器胜出。
ID的特殊性比属性选择器的更高;属性选择器则比类选择器高。所以你可以尝试用id来增加特殊性。
计算特殊性
当你遇到一个又大又复杂的样式表时,你最好知道怎么计算特殊性,这样能让你的选择器更有效率。
特殊性的值可以看作是一个由四个数组成的一个组合,用 a,b,c,d 来表示它的四个位置。 依次比较 a,b,c,d 这个四个数比较其特殊性的大小。比如,a 值相同,那么 b 值大的组合特殊性会较大,以此类推。注意,W3C 中并不是把它作为一个 4 位数来看待的。
a,b,c,d 值的确定规则:
(注:原文为:
此处没有直接翻译。)
下面举一个实际例子:
使用!important将覆盖所有特殊性,无论它们值有多高。 因此尽量不要用 !important。大多数情况下它都是不必要的 。
Pixels vs. Ems
我们使用px计量单位来定义字体大小,因为它对文本提供了绝对控制。在IE6浏览器中,如果是用px为单位,那么在页面放大缩小的时候,就不会根据页面缩放的大小来调整基础文本的大小。当今所有主要浏览器(包括IE7和IE8)现在支持文本的像素单位 和/或 整版的缩放。在不考虑IE6的情况下,像素大小是首选。此外,没有单位的行高(line-height)是首选的,因为它不继承它的父元素一个百分比值,而是基于一个乘数的字体大小。
正确的写法:
错误的写法:
IE的那些BUG
不可避免的,当其他浏览器都工作正常时,IE的各个版本有可能会引入一些荒谬的BUG,搞得你措手不及。最后我们只好用CSS hooks加一些条件判断单独设置IE下的表现。更多详情请阅读 paulirish的文章。
举例:
如果你使用HTML5(以及 HTML5 Boilerplate),那推荐你使用 Modernizer Javascript 库以及下面这个模式:
简写(CSS Shorthand)
一般来说,CSS简写是首选的,因为简洁。开发人员应该意识到 TRBL ( Top Right Bottom Left )缩略词,按顺时针“上、右、下、左”进行定义。例如:
padding-left:10px;padding-right:15px;padding-top:20px;padding-bottom:10px;
可将其简写为:padding:20px 15px 10px 10px;
参考阅读:
图片
文本和字体样式
标题
链接
应确保链接的默认样式与主要文本的样式有所区分,鼠标悬停状态的样式也应该有所区分。
JavaScript是web页面中的第三个主要的组件。
JavaScript库
目前,我们主要使用 jQuery开发新的web应用程序。
一般的编码规则
合理使用空格
一般来说,使用空格应该遵循长期以来的英语阅读约定,符号左右应该存在一个空格,我们提倡代码的可读性。此外,前括号应该和总是和他的函数名处在同一行。
考虑下面这个例子,一个JavaScript循环…
变量、ID和类
所有JavaScript的变量名,都应该写成全部字母小写或者驼峰式大小写的形式。一个例外是,构造函数需要按照传统统统大写。所有CSS的ID和Class应该全部使用小写。尽可能的避免使用中划线和下划线。
事件委托
事件委托就是在一个页面上使用一个事件来管理多种类型的事件。这并不是一个新的想法,但对于把握性能来说却很重要。
事件委托对于web应用程序的性能有如下几个优点:
从传统的事件处理方法转向事件委托,提高了大型web应用的性能 。正因为它如此重要,一些类似于YUI、jQuey的javascript库也开始将事件委托应用在它们的核心接口中。实现事件委托是很轻松的,却能带来性能上很大的提高。尤其表现在你将数十个事件处理函数整合到一个函数里。试一下事件委托,你就不会再使用传统的事件处理方法了。
出于性能考虑,jQuery中的 delegate()要大大优于 live() 。
调试
即使最好的验证器,也不可避免地会导致浏览器怪异模式的问题。有几个宝贵的工具,将有助于改进代码的完整性和加载速度。我们建议开发时先以Firefox和Safari第一,然后Chrome和Opera,最后有条件地单独调整Internet Explorer 。
下面列出了有用的调试器和速度分析…
良好的Javascript编写模式
我们将继续关注网络的性能优化,它仍然同样的重要。一个网页可以做到最小的性能消耗及等待时间。以下部分说明了如何对一个网页进行优化,让更多的浏览者更加满意。
优化并交付CSS和Javascript
<script>
块,他们会阻塞页面渲染和页面加载时间 !优化Javascript执行顺序
在一个页面加载中,通常等待执行的脚本有很多。基于用户的响应,这个顺序优先级应如下:
合理利用CSS Sprites技术
CSS Sprites把一些基本的图像资源合并到一个图像文件中。通过CSS背景定位的方式来获取其中的某一个部分。这样做的目的同样是为了减少http的请求次数 。以下是一个典型的CSS Sprites:
使用CSS Sprites 能有效降低页面引用资源数,从而加快页面加载。 更多内容请阅读CSS-tricks.com的技术和概述。
许多开发人员会使用一个垂直排列内部图片元素的Sprites,这种垂直排列的Sprites应该<= 100px宽(高)。包含图标通常应该放在文件里的最边上,如列表项icon小图标。雅虎 使用了一些像这样的Sprites。
另外一个要考虑的是不要使用过大的Sprites,超过1000px的任意一个方向的Sprites会占用相当大的内存空间 。
图片格式的应用
高速缓存
对于静态内容,只要是合理的,我们都应该在本地缓存文件。应该被缓存的文件包括:
如果你的服务器是Apache,使用ExpiresDefault指令设置相对于当前日期的过期时间。这个例子ExpiresDefault指令集的要求过期时间为1年。
Expires: Thu, 15 Apr 2015 20:00:00 GMT
缓存只适用于准确的URL,所以改变文件名将开始一个新的拷贝。许多开发人员在文件发布或构建过程中添加一个版本号或时间戳 。每一次构建将开始一个全新的缓存的版本,你不用担心缓存不会过期。
有节制的使用IFRAME
创建IFRAME比创建任何其他类型的DOM元素(包括脚本和样式表)耗时多出1-2个数量级。
尽快产生 Window的onload事件是很重要的。这个事件会引发浏览器状态指示到达“完毕”状态,通知用户页面已经下载完毕。当onload事件被延迟,给用户的感受是页面变的更慢了。
Window的onload事件在所有的iframe和iframe内所有元素完全下载后才能触发。在 Safari 和 Chrome浏览器内,通过JavaScript动态设置iframe的src属性可以避免这种阻塞行为。
有人可能希望一个iframe有它自己单独的并发连接池,但是事实并不是这样。在所有主流浏览器中,连接池是被页面和iframe共享的。这意味着有可能一个iframe内的资源占据了所有可用的连接并阻塞了主页面的资源下载。如果iframe内的内容和主页面一样重要或者更重要,这是没有问题的。但如果iframe不太重要,iframe占用连接是不可取的。一个解决办法是在 更高级别的资源下载之后,动态设置iframe的src属性动态加载内容
美国10大网站中5个使用了iframe。大多数情况下,它们常用来加载广告。这是不幸的,但可以理解,因为使用iframe插入广告内容很容易实现。在许多情况下,iframe是合乎逻辑的 解决方案。但要记住他们会对你的页面产生性能影响。尽可能避免使用iframe,当必须使用时,要有节制的使用它们。
FLASH
在应用FLASH动画的地方,请备注上相应的HTML文本,以便于SEO搜索引擎的优化。SWFObject的初始化应该在文档加载完毕之后。不要使用内嵌的JavaScript输出SWFObject。
建立于客户间的成功指标。
这些指标不管从技术角度以及可测试性应该是合理的:
原文链接: http://isobar-idev.github.com/code-standards/
翻译组:@窝窝团前端(刘轶/李晨/徐利/穆尚)
校对:@郑昀
2) 55最佳实践系列:Logging最佳实践 (2012-12-15 16:43)
赠图1枚:
本文链接