一、通用规范
- 目录构建规范
-
src/api 模块的请求方法。应该参考 src/views 中的直接子文件夹的结构,做映射。
-
src/assets 项目的静态资源文件。虽然是静态文件(图片,字体,等),但是还是经过 webpack 处理会好一些,因为有些比较小的文件会被打包到文件,减少请求和压缩第三方包。这个模块的文件,如果还需要扩展,一个单词作为文件夹名字!保持简洁性。
-
src/common 公共的动态的脚本、样式。在实际中,样式可能是各种预处理语言写的,请自行组织目录结构。
-
src/components 公共组件。放置项目中抽象的基础和业务组件。你应该为每个组件都单独建一个文件夹,以做好组件之间的隔离,并且有一个默认的文件:index.vue 文件,以便引入组件时少写几个字母。默认组件中的文件是一个最小的单位,不应该有依赖其他组件,或操作 state 状态等行为。
-
src/http 主要是关于请求方法的封装。建议开发过程中不要修改,因为会影响到全局。
-
src/store 数据中心。这部分内容比较多,独立出来,详情参考:数据中心
-
src/router 页面路由。默认所有路由映射写在一个文件,如果需要路由模块化,请自行组织。
-
src/views 所有业务逻辑的页面。
── project-name
├── public 项目公共目录
│ ├── favicon.ico Favourite 图标
│ └── index.html 页面入口 HTML 模板
├── src 项目源码目录
│ ├── main.js 入口js文件
│ ├── App.vue 根组件
│ ├── api 把所有请求数据的接口,按照模块在单独的JS文件中
│ │ ├── home.js 首页接口
│ │ ├── detail.js 详情页接口,等等
│ │ ···
│ ├── assets 静态资源目录,公共的静态资源,图片,字体等
│ │ ├── fonts 字体资源
│ │ ├── images 图片资源
│ │ ···
│ ├── common 公共脚本,样式,配置,等动态信息
│ │ ├── js 公共脚本
│ │ │ │── utlis.js 公共 JS 工具函数
│ │ │ │── config.js 公共配置
│ │ │ ···
│ │ ├── style 公共样式,可以是各种预处理语言
│ │ │ │── index.css 样式主文件
│ │ │ │── reset.css 重置样式
│ │ │ ···
│ │ ···
│ ├── components 公共组件目录
│ │ ├── confirm 弹框组件
│ │ │ └── index.vue
│ │ ├── scroll 局部内容滚动组件
│ │ │ └── index.vue
│ │ ···
│ ├── http 封装的 HTTP 请求方法
│ │ ├── axios.js Axios 的封装
│ │ ├── jsonp.js JSONP 的封装
│ │ ···
│ ├── store 数据中心
│ │ ├── state.js state 数据源,数据定义
│ │ ├── mutations.js 同步修改 state 数据的方法定义
│ │ ├── mutation-types.js 定义 Mutations 的类型
│ │ ├── actions.js 异步修改 state 数据的方法定义
│ │ ├── getters.js 获取数据的方法定义
│ │ └── index.js 数据中心入口文件
│ ├── routes 前端路由
│ │ └── index.js
│ └── views 页面目录,所有业务逻辑的页面都应该放这里
│ ├── home 应用首页
│ │ └── index.vue
│ ···
├── .env.development Vue 开发环境的配置
├── .env.production Vue 生成环境的配置
├── .eslintrc.js Eslint 配置文件
├── .gitignore Git 忽略文件
├── package.json 包依赖文件
├── package-lock.json 依赖包版本管理文件
├── README.md 项目介绍
├── vue.config.js vue/cli 项目脚手架配置
···复制代码
- 组件/实例的选项顺序
- name
- components / directives / filters
- extends / mixins
- model / props / propsData
- data / computed
- watch / 生命周期钩子
- methods
<script>
export default {
name: 'ExampleName', // 这个名字推荐:大写字母开头驼峰法命名。
props: {}, // Props 定义。
components: {}, // 组件定义。
directives: {}, // 指令定义。
mixins: [], // 混入 Mixin 定义。
data () { // Data 定义。
return {
dataProps: '' // Data 属性的每一个变量都需要在后面写注释说明用途
}
},
computed: {}, // 计算属性定义。
created () {}, // 生命钩子函数,按照他们调用的顺序。
mounted () {}, // 挂载到元素。
activated () {}, // 使用 keep-alive 包裹的组件激活触发的钩子函数。
deactivated () {}, // 使用 keep-alive 包裹的组件离开时触发的钩子函数。
watch: {}, // 属性变化监听器。
methods: { // 组件方法定义。
publicbFunction () {} // 公共方法的定义,可以提供外面使用
_privateFunction () {} // 私有方法,下划线定义,仅供组件内使用。
}
}
</script>复制代码
- 元素特性的顺序
-
is
-
v-for / v-if / v-else-if / v-else / v-show / v-cloak
-
v-pre / v-once
-
id
-
ref / key / slot
-
v-model
-
v-on
-
v-html / v-text
4. 基本原则:结构、样式、行为分离
- 尽量确保文档和模板只包含 HTML 结构,样式都放到 css 样式表里,行为都放到 js 脚本里
- 标记应该是结构良好、语义正确。
- Javascript应该起到渐进式增强用户体验的作用 。
- 注释
写注释时请一定要注意:写明代码的作用,重要的地方一定记得写注释。 没必要每份代码都描述的很充分,它会增重HTML和CSS的代码。这取决于该项目的复杂程度。
5.1 单行注释说明:
单行注释以两个斜线开始,以行尾结束
// 调用了一个函数
setTitle();var maxCount = 10; // 设置最大量复制代码
5.2 多行注释
/*
* 代码执行到这里后会调用setTitle()函数
* setTitle():设置title的值
*/复制代码
5.3 函数注释
/**
* 以星号开头,紧跟一个空格,第一行为函数说明
* @param {类型} 参数 单独类型的参数
* @param {[类型|类型|类型]} 参数 多种类型的参数
* @param {类型} [可选参数] 参数 可选参数用[]包起来
* @return {类型} 说明
* @author 作者 创建时间 修改时间(短日期)改别人代码要留名
* @example 举例(如果需要)
*/复制代码
5.4 文件头注释
推荐:VScode 文件头部自动生成注释插件:koroFileHeader
5.5 条件注释
<!--[if IE 9]>
.... some HTML here ....
<![endif]-->复制代码
二.HTML规范
- 通用约定
标签
- 自闭合(self-closing)标签,无需闭合 ( 例如: img input br hr 等 );
- 可选的闭合标签(closing tag),需闭合 ( 例如: 或 );
- 尽量减少标签数量;
例:
Class 与 ID
- class 应以功能或内容命名,不以表现形式命名;
- class 与 id 单词字母小写,多个单词组成时,采用中划线-分隔;
- 使用唯一的 id 作为 Javascript hook, 同时避免创建无样式信息的 class;
<!-- Not recommended --><div class="item-hook left contentWrapper"></div>
<!-- Recommended --><div id="item-hook" class="sidebar content-wrapper"></div>复制代码
属性顺序 HTML 属性应该按照特定的顺序出现以保证易读性。
- id
- class
- name
- data-xxx
- src, for, type, href
- title, alt
- aria-xxx, role
<a id="..." class="..." data-modal="toggle" href="###"></a>
<input class="form-control" type="text">
<img src="..." alt="...">复制代码
嵌套
-
- 用于
- 或
-
- ,
- 用于
- 下;
- ,, , , 用于 下;
严格嵌套约束
- inline-Level 元素,仅可以包含文本或其它inline-Level元素;
- 里不可以嵌套交互式元素、、等; 里不可以嵌套块级元素、~、、//、//、等。 布尔值属性 HTML5 规范中disabled、checked、selected 等属性不用设置值。 <input type="text" disabled> <input type="checkbox" value="1" checked> <select> <option value="1" selected>1</option></select>复制代码 2. 基本文本 使用 HTML5 doctype,不区分大小写。 <!DOCTYPE html>复制代码 声明文档使用的字符编码 <meta charset="utf-8">复制代码 优先使用 IE 最新版本和 Chrome <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">复制代码 例: 4. 可选标签 为移动设备添加 viewport <meta name ="viewport" content ="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no"> <!-- `width=device-width` 会导致 iPhone 5 添加到主屏后以 WebApp 全屏模式打开页面时出现黑边 http://bigc.at/ios-webapp-viewport-meta.orz --> 复制代码 content 参数: width viewport 宽度(数值/device-width) height viewport 高度(数值/device-height) initial-scale 初始缩放比例 maximum-scale 最大缩放比例 minimum-scale 最小缩放比例 user-scalable 是否允许用户缩放(yes/no) 页面窗口自动调整到设备宽度,并禁止用户缩放页面 <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />复制代码 电话号码识别 iOS Safari ( Android 或其他浏览器不会) 会自动识别看起来像电话号码的数字,将其处理为电话号码链接,比如: 7位数字,形如:1234567 带括号及加号的数字,形如:(+86)123456789 双连接线的数字,形如:00-00-00111 11位数字,形如:13800138000 邮箱地址的识别 在 Android ( iOS 不会)上,浏览器会自动识别看起来像邮箱地址的字符串,不论有你没有加上邮箱链接,当你在这个字符串上长按,会弹出发邮件的提示。 iOS 设备 添加到主屏后的标题 - 是否启用 WebApp 全屏模式 - 设置状态栏的背景颜色 - 指定 iOS 的 safari 顶端状态条的样式 Android 设备 Android Lollipop 中增加 theme-color meta 标签,用来控制选项卡颜色。 <meta name="theme-color" content="#db5945"> 复制代码 禁止 Chrome 浏览器中自动提示翻译 <meta name="google" value="notranslate"> 复制代码 5.样式表、脚本加载 css 样式表在head标签内引用,js 脚本引用在 body 结束标签之前引用。 三.JavaScript规范 1.通用约定 注释原则 As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性、可读性。 As long as necessary(如有必要,尽量详尽):合理的注释、空行排版等,可以让代码更易阅读、更具美感。 命名 变量, 使用驼峰命名。 let loadingModules = {};复制代码 私有属性、变量和方法以下划线 _ 开头。 let _privateMethod = {};复制代码 常量, 使用全部字母大写。 let MAXCOUNT = 10;复制代码 枚举变量 使用 Pascal 命名法。 枚举的属性, 使用全部字母大写,单词间下划线分隔的命名方式。 let TargetState = { READING: 1, READED: 2, APPLIED: 3, READY: 4 };复制代码 boolean 类型的变量使用 is 或 has 开头。 let isReady = false;let hasMoreCommands = false;复制代码 二元和三元操作符 操作符始终写在前一行, 以免分号的隐式插入产生预想不到的问题。 let x = a ? b : c;let y = a ? longButSimpleOperandB : longButSimpleOperandC;let z = a ? moreComplicatedB : moreComplicatedC;复制代码 操作符也是如此: let x = foo.bar(). doSomething(). doSomethingElse();复制代码 条件(三元)操作符 ( ? : ) 三元操作符用于替代 if 条件判断语句。 // Not recommendedif (val != 0) { return foo(); } else { return bar(); }// Recommendedreturn val ? foo() : bar();复制代码 && 和 || 二元布尔操作符是可短路的, 只有在必要时才会计算到最后一项。 对于if else 过多问题可以做map配置化。 例: 声明提升 var 声明会被提升至该作用域的顶部,但它们赋值不会提升。let 和 const 被赋予了一种称为「暂时性死区(Temporal Dead Zones, TDZ)」的概念。这对于了解为什么 type of 不再安全相当重要。 匿名函数表达式的变量名会被提升,但函数内容并不会。 function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function() { console.log('anonymous function expression'); }; }复制代码 命名的函数表达式的变量名会被提升,但函数名和函数函数内容并不会。 函数声明的名称和函数体都会被提升。 function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } }复制代码 具备强类型的设计 解释: 如果一个属性被设计为 boolean 类型,则不要使用 1 或 0 作为其值。对于标识性的属性,如对代码体积有严格要求,可以从一开始就设计为 number 类型且将 0 作为否定值。 从 DOM 中取出的值通常为 string 类型,如果有对象或函数的接收类型为 number 类型,提前作好转换,而不是期望对象、函数可以处理多类型的值。 2.函数设计 函数设计基本原则:低耦合,高内聚。(假如一个程序有50个函数;一旦你修改其中一个函数,其他49个函数都需要做修改,这就是高耦合的后果。) 函数长度 [建议] 一个函数的长度控制在 50 行以内。 将过多的逻辑单元混在一个大函数中,易导致难以维护。一个清晰易懂的函数应该完成单一的逻辑单元。复杂的操作应进一步抽取,通过函数的调用来体现流程。 特定算法等不可分割的逻辑允许例外。 例: 参数设计 [建议] 一个函数的参数控制在 6 个以内。 解释: 除去不定长参数以外,函数具备不同逻辑意义的参数建议控制在 6 个以内,过多参数会导致维护难度增大。 某些情况下,如使用 AMD Loader 的 require 加载多个模块时,其 callback可能会存在较多参数,因此对函数参数的个数不做强制限制。 [建议] 通过 options 参数传递非数据输入型参数。 解释: 有些函数的参数并不是作为算法的输入,而是对算法的某些分支条件判断之用,此类参数建议通过一个 options 参数传递。 这种模式有几个显著的优势: boolean 型的配置项具备名称,从调用的代码上更易理解其表达的逻辑意义。 当配置项有增长时,无需无休止地增加参数个数,不会出现 removeElement(element, true, false, false, 3) 这样难以理解的调用代码。 当部分配置参数可选时,多个参数的形式非常难处理重载逻辑,而使用一个 options 对象只需判断属性是否存在,实现得以简化。 箭头函数 当你必须使用函数表达式(或传递一个匿名函数)时,使用箭头函数符号。 为什么?因为箭头函数创造了新的一个 this 执行环境,通常情况下都能满足你的需求,而且这样的写法更为简洁。( 参考 Arrow functions - JavaScript | MDN ) 为什么不?如果你有一个相当复杂的函数,你或许可以把逻辑部分转移到一个函数声明上。 // Not recommended [1, 2, 3].map(function (x) { const y = x + 1; return x * y; });// Recommended [1, 2, 3].map((x) => { const y = x + 1; return x * y; });复制代码 如果一个函数适合用一行写出并且只有一个参数,那就把花括号、圆括号和 return 都省略掉。如果不是,那就不要省略。 为什么?语法糖。在链式调用中可读性很高。 为什么不?当你打算回传一个对象的时候。 // Recommended [1, 2, 3].map(x => x * x);// Recommended [1, 2, 3].reduce((total, n) => { return total + n; }, 0);复制代码 函数和变量 同一个函数内部,局部变量的声明必须置于顶端 因为即使放到中间,js解析器也会提升至顶部(hosting) // Recommendedvar clear = function(el) { var id = el.id, name = el.getAttribute("data-name"); ......... return true; } // Not recommendedvar clear = function(el) { var id = el.id; ...... var name = el.getAttribute("data-name"); ......... return true; }复制代码 块内函数必须用局部变量声明 // Not recommended var call = function(name) { if (name == "hotel") { function foo() { console.log("hotel foo"); } } foo && foo(); } // Recommended var call = function(name) { var foo; if (name == "hotel") { foo = function() { console.log("hotel foo"); } } foo && foo(); }复制代码 引起的bug:第一种写法foo的声明被提前了; 调用call时:第一种写法会调用foo函数,第二种写法不会调用foo函数 空函数 [建议] 对于性能有高要求的场合,建议存在一个空函数的常量,供多处使用共享。 示例: 性能优化 避免不必要的 DOM 操作 浏览器遍历 DOM 元素的代价是昂贵的。最简单优化 DOM 树查询的方案是,当一个元素出现多次时,将它保存在一个变量中,就避免多次查询 DOM 树了。 缓存数组长度 循环无疑是和 JavaScript 性能非常相关的一部分。通过存储数组的长度,可以有效避免每次循环重新计算。 注: 虽然现代浏览器引擎会自动优化这个过程,但是不要忘记还有旧的浏览器。 var arr = new Array(1000), len, i;// Recommended - size is calculated only 1 time and then storedfor (i = 0, len = arr.length; i < len; i++) { }// Not recommended - size needs to be recalculated 1000 timesfor (i = 0; i < arr.length; i++) { }复制代码 优化 JavaScript 的特征 编写可维护的代码 单变量模式 Hoisting:把所有变量声明统一放到函数的起始位置 (在后部声明的变量也会被JS视为在头部定义,由此会产生问题) 不要扩充内置原型(虽然给Object(), Function()之类的内置原型增加属性和方法很巧妙,但是会破坏可维护性) 不要用隐含的类型转换 不要用 eval() 用 parseInt() 进行数字转换 (规范)左大括号的位置 构造器首字母大写 写注释 不要用 void 不要用 with 语句 不要用 continue 语句 尽量不要用位运算 优化 JavaScript 执行 在页面加载的时候,通常会有很多脚本等待执行,但你可以设定优先级。下面的顺序就是基于用户反馈设定的优先级: 改变页面视觉习性的脚本绝对要首先执行。这包括任何的字体调整、盒子布局、或IE6 pngfix。 页面内容初始化 页面标题、顶部导航和页脚的初始化 绑定事件处理器 网页流量分析、Doubleclick,以及其他第三方脚本 异步加载第三方内容 当你无法保证嵌入第三方内容比如 Youtube 视频或者一个 like/tweet 按钮可以正常工作的时候,你需要考虑用异步加载这些代码,避免阻塞整个页面加载。 四.CSS规范 1.通用约定 声明顺序 相关的属性声明应当归为一组,并按照下面的顺序排列: Positioning Box model Typographic Visual Misc 由于定位(positioning)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位。盒模型排在第二位,因为它决定了组件的尺寸和位置。 其他属性只是影响组件的 内部 或者是不影响前两组属性,因此排在后面。 完整的属性列表及其排列顺序请参考 Bootstrap property order for Stylelint。 .declaration-order { /* Positioning */ position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 100; /* Box-model */ display: block; float: right; width: 100px; height: 100px; /* Typography */ font: normal 13px "Helvetica Neue", sans-serif; line-height: 1.5; color: #333; text-align: center; /* Visual */ background-color: #f5f5f5; border: 1px solid #e5e5e5; border-radius: 3px; /* Misc */ opacity: 1; }复制代码 链接的样式顺序 a:link -> a:visited -> a:hover -> a:active(LoVeHAte)复制代码 命名 组成元素 命名必须由单词、中划线①或数字组成; 不允许使用拼音(约定俗成的除外,如:youku, baidu),尤其是缩写的拼音、拼音与英文的混合。 不推荐: .xiangqing { sRules; } .news_list { sRules; } .zhuti { sRules; }复制代码 推荐: .detail { sRules; } .news-list { sRules; } .topic { sRules; }复制代码 ①使用中划线 “-” 作为连接字符,而不是下划线 "_"。 2种方式都有不少支持者,但 "-" 能让你少按一次shift键,并且更符合CSS原生语法,所以只选一种目前普遍使用的方式 词汇规范 不依据表现形式来命名; 可根据内容来命名; 可根据功能来命名。 不推荐: left, right, center, red, black复制代码 推荐: nav, aside, news, type, search复制代码 缩写规范 保证缩写后还能较为清晰保持原单词所能表述的意思; 使用业界熟知的或者约定俗成的。 不推荐: navigation => navi header => head description => des复制代码 推荐: navigation => nav header => hd description => desc复制代码 前缀规范 无法复制加载中的内容 选择器必须是以某个前缀开头 不推荐: .info { sRules; } .current { sRules; } .news { sRules; }复制代码 这样将会带来不可预知的管理麻烦以及沉重的包袱。你永远也不会知道哪些样式名已经被用掉了,如果你是一个新人,你可能会遭遇,你每定义个样式名,都有同名的样式已存在,然后你只能是换样式名或者覆盖规则。 推荐: .m-detail .info { sRules; } .m-detail .current { sRules; } .m-detail .news { sRules; }复制代码 所有的选择器必须是以 g-, m-, ui- 等有前缀的选择符开头的,意思就是说所有的规则都必须在某个相对的作用域下才生效,尽可能减少全局污染。 js- 这种级别的className完全交由JSer自定义,但是命名的规则也可以保持跟重构一致,比如说不能使用拼音之类的 选择器权重等级 a = 行内样式style。 b = ID选择器的数量。 c = 类、伪类和属性选择器的数量。 d = 类型选择器和伪元素选择器的数量。 无法复制加载中的内容 简写/省略/缩写 属性值书写尽量使用缩写 CSS很多属性都支持缩写shorthand (例如 font ) 尽量使用缩写,甚至只设置一个值。 使用缩写可以提高代码的效率和方便理解。 _ |_ 省略0后面的单位 非必要的情况下 0 后面不用加单位。 padding: 0;margin: 0;复制代码 省略0开头小数点前面的0 值或长度在-1与1之间的小数,小数前的 0 可以忽略不写。 font-size: .8em;复制代码 省略URI外的引号 不要在 url() 里用 ( “” , ” ) 。 @import url(//www.google.com/css/go.css); 复制代码 十六进制尽可能使用3个字符 加颜色值时候会用到它,使用3个字符的十六进制更短与简洁。 /* Not recommended */ color: #eebbcc; /* Recommended*/color: #ebc;复制代码 2.Less 和 Sass 操作符 为了提高可读性,在圆括号中的数学计算表达式的数值、变量和操作符之间均添加一个空格。 // Not recommended .element { margin: 10px 0 @variable*2 10px; } // Recommended .element { margin: 10px 0 (@variable * 2) 10px; }复制代码 嵌套 避免不必要的嵌套。因为虽然可以使用嵌套,但是并不意味着应该使用嵌套。只有在必须将样式限制在父元素内(也就是后代选择器),并且存在多个需要嵌套的元素时才使用嵌套。 扩展阅读:Nesting in Sass and Less 代码组织 代码按一下顺序组织: @import 变量声明 样式声明 @import "mixins/size.less"; @default-text-color: #333; .page { width: 960px; margin: 0 auto; }复制代码 混入(Mixin) 在定义 mixin 时,如果 mixin 名称不是一个需要使用的 className,必须加上括号,否则即使不被调用也会输出到 CSS 中。 如果混入的是本身不输出内容的 mixin,需要在 mixin 后添加括号(即使不传参数),以区分这是否是一个 className。 模块化 每个模块必须是一个独立的样式文件,文件名与模块名一致; 模块样式的选择器必须以模块名开头以作范围约定; 任何超过3级的选择器,需要思考是否必要,是否有无歧义的,能唯一命中的更简短的写法 3.hack规范 尽可能的减少对Hack的使用和依赖,如果在项目中对Hack的使用太多太复杂,对项目的维护将是一个巨大的挑战; 使用其它的解决方案代替Hack思路; 如果非Hack不可,选择稳定且常用并易于理解的。 .test { color: #000; /* For all */ color: #111\9; /* For all IE */ color: #222\0; /* For IE8 and later, Opera without Webkit */ color: #333\9\0; /* For IE8 and later */ color: #444\0/; /* For IE8 and later */ color: #666; /* For IE7 and earlier */ color: #777; /* For IE6 and earlier */ }复制代码 注:严谨且长期的项目,针对IE可以使用条件注释作为预留Hack或者在当前使用 IE条件注释语法: <!--[if <keywords>? IE <version>?]> <link rel="stylesheet" href="*.css" /> <![endif]-->复制代码 语法说明: <keywords>if条件共包含6种选择方式:是否、大于、大于或等于、小于、小于或等于、非指定版本 是否:指定是否IE或IE某个版本。关键字:空 大于:选择大于指定版本的IE版本。关键字:gt(greater than) 大于或等于:选择大于或等于指定版本的IE版本。关键字:gte(greater than or equal) 小于:选择小于指定版本的IE版本。关键字:lt(less than) 小于或等于:选择小于或等于指定版本的IE版本。关键字:lte(less than or equal) 非指定版本:选择除指定版本外的所有IE版本。关键字:!复制代码 <version> 目前的常用IE版本为6.0及以上,推荐酌情忽略低版本,把精力花在为使用高级浏览器的用户提供更好的体验上,另从IE10开始已无此特性复制代码 4.动画与转换 使用 transition 时应指定 transition-property。 示例: /* good */.box { transition: color 1s, border-color 1s; }/* bad */.box { transition: all 1s; }复制代码 在浏览器能高效实现的属性上添加过渡和动画。 在可能的情况下应选择这样四种变换: transform: translate(npx, npx); transform: scale(n); transform: rotate(ndeg); opacity: 0..1; 典型的,可以使用 translate 来代替 left 作为动画属性。 示例:一般在 Chrome 中,3D或透视变换(perspective transform)CSS属性和对 opacity 进行 CSS 动画会创建新的图层,在硬件加速渲染通道的优化下,GPU 完成 3D 变形等操作后,将图层进行复合操作(Compesite Layers),从而避免触发浏览器大面积 重绘 和 重排。 /* good */.box { transition: transform 1s; }.box:hover { transform: translate(20px); /* move right for 20px */ }/* bad */.box { left: 0; transition: left 1s; }.box:hover { left: 20px; /* move right for 20px */ }复制代码 动画的基本概念: 帧:在动画过程中,每一幅静止画面即为一“帧”; 帧率:即每秒钟播放的静止画面的数量,单位是fps(Frame per second); 帧时长:即每一幅静止画面的停留时间,单位一般是ms(毫秒); 跳帧(掉帧/丢帧):在帧率固定的动画中,某一帧的时长远高于平均帧时长,导致其后续数帧被挤压而丢失的现象。 一般浏览器的渲染刷新频率是60 fps,所以在网页当中,帧率如果达到 50-60 fps 的动画将会相当流畅,让人感到舒适。 如果使用基于 javaScript 的动画,尽量使用 requestAnimationFrame. 避免使用 setTimeout, setInterval. 避免通过类似 jQuery animate()-style 改变每帧的样式,使用 CSS 声明动画会得到更好的浏览器优化。 使用 translate 取代 absolute 定位就会得到更好的 fps,动画会更顺滑。 5.性能优化 慎重选择高消耗的样式 高消耗属性在绘制前需要浏览器进行大量计算: box-shadows border-radius transparency transforms CSS filters(性能杀手) 正确使用 Display 的属性 Display 属性会影响页面的渲染,请合理使用。 display: inline后不应该再使用 width、height、margin、padding 以及 float; display: inline-block 后不应该再使用 float; display: block 后不应该再使用 vertical-align; display: table-* 后不应该再使用 margin 或者 float; 提升 CSS 选择器性能 CSS 选择器是从右到左进行规则匹配。只要当前选择符的左边还有其他选择符,样式系统就会继续向左移动,直到找到和规则匹配的选择符,或者因为不匹配而退出。最右边选择符称之为关键选择器。 CSS 选择器的执行效率从高到低做一个排序: 1.id选择器(#myid) 2.类选择器(.myclassname) 3.标签选择器(div,h1,p) 4.相邻选择器(h1+p) 5.子选择器(ul < li) 6.后代选择器(li a) 7.通配符选择器(*) 8.属性选择器(a[rel="external"]) 9.伪类选择器(a:hover, li:nth-child) 避免使用通用选择器 /* Not recommended */ .content * {color: red;}复制代码 浏览器匹配文档中所有的元素后分别向上逐级匹配 class 为 content 的元素,直到文档的根节点。因此其匹配开销是非常大的,所以应避免使用关键选择器是通配选择器的情况。 避免使用标签或 class 选择器限制 id 选择器 /* Not recommended */ button#backButton {…} /* Recommended */ #newMenuIcon {…}复制代码 避免使用标签限制 class 选择器 /* Not recommended */ treecell.indented {…} /* Recommended */ .treecell-indented {…} /* Much to recommended */ .hierarchy-deep {…}复制代码 避免使用多层标签选择器。 使用 class 选择器替换,减少css查找 /* Not recommended */ treeitem[mailfolder="true"] > treerow > treecell {…} /* Recommended */ .treecell-mailfolder {…}复制代码 避免使用子选择器 /* Not recommended */ treehead treerow treecell {…} /* Recommended */ treehead > treerow > treecell {…} /* Much to recommended */ .treecell-header {…}复制代码 使用继承 /* Not recommended */#bookmarkMenuItem > .menu-left { list-style-image: url(blah) }/* Recommended */#bookmarkMenuItem { list-style-image: url(blah) }复制代码
- 下;
-