<!DOCTYPE html> <!-- HTML5 --> <html lang="en"> <head> <meta charset="UTF-8"> <title>标题</title> </head> <body>内容</body> </html>
<link rel="stylesheet" href="page.css"/> <script src="page.js"></script>
<link rel="stylesheet" href="//qq.com/page.css">
使用 protocol-relative URL 引入 CSS,在 IE7/8 下,会发两次请求。
<!-- BAD: 会block外部script请求 --> <script src="//example.com/test.js"></script><p></p>
<!-- GOOD: 外部script会异步加载 --> <script> var script = document.createElement('script'); script.src = "//example.com/test.js"; document.getElementsByTagName('head')[0].appendChild(script); </script>
<link href="http://example.com/test.css?rtt=2" rel="stylesheet"> <!-- body 内容 --> <script> var script = document.createElement('script'); script.src = "http://example.com/test.js?rtt=1&a"; document.getElementsByTagName('head')[0].appendChild(script); </script> <script> var script = document.createElement('script'); script.src = "http://example.com/test.js?rtt=1&b"; document.getElementsByTagName('head')[0].appendChild(script); </script>
Javascript 可以操作 CSSOM,所以需要等到 css 完全加载解析完毕之后才能执行 script 标签
<link href="http://example.com/test.css?rtt=2" rel="stylesheet"> <!-- body 内容 --> <script src="http://example.com/test.js?rtt=1&a"></script> <script src="http://example.com/test.js?rtt=1&b" ></script>
浏览器(包括 IE8/9 和 Android 2.3/2.2)会预解析查找可以下载的外部文件,并行下载,串行执行
<!-- 现代浏览器使用 'async',旧IE使用 'defer' --> <script src="//somehost.com/awesome-widget.js" async defer></script>
并行下载,不会 block DOM 不能确保执行顺序
No Rules! Just Tools!
.box { margin: 10px; padding: 10px; width: 100px; height: 100px; border: 1px solid #CCC; }
块级元素,新开始一行并且尽可能撑满容器
行内元素,一行之内横向的排列,宽高不起作用
行内块级元素,一行之内横向的排列,宽高起作用
<div class="demo"> <p>Lorem Ipsum is simply <span>这是一个行内块级元素 display: inline;</span> Lorem.</p> <p>Lorem Ipsum is simply <span>这是一个行内块级元素 display: inline;</span> Lorem.</p> </div>
普通文档流,一般是从左至右、从上到下
.demo-box { margin: 20px; padding: 10px; border: 5px dashed #000; } .demo-float-r, .demo-float { margin: 10px; float: left; /* 左浮动 */ width: 100px; height: 100px; background: red; } .demo-float-r { float: right; /* 右浮动 */ }
Lorem Ipsum is simply dummy text of the printing .
.demo-clear { clear: left; /* 清除左浮动 */ margin: 10px; width: 100px; height: 100px; background: blue; }
<div class="demo-box demo-clearfix"> <div class="demo-float">1</div> <div class="demo-float-r">2</div> <!-- 清除浮动 --> <div class="demo-clear"></div> </div>
/** * http://nicolasgallagher.com/micro-clearfix-hack/ * For modern browsers * 1. 处理 Opera 下 contenteditable 时候的bug * 2. 使用 table 是为了触发 BFC,解决顶部元素的 margin 折叠问题 */ .demo-clearfix:before, .demo-clearfix:after { content: ' '; /* 1 */ display: table; /* 2 */ } .demo-clearfix:after { clear: both; } /** * IE 6/7 下触发 hasLayout 实现兼容 */ .demo-clearfix { *zoom: 1; }
<!--[if IE 6]> 这段文字只在IE6浏览器显示 <![endif]-->
CSS 会忽略不支持的属性或选择器
.test1 { background-color: #FFF; /* 不支持rgba */ background-color: rgba(255, 255, 255, .8); /* 支持rgba */ } .test2 { background-image: url(top.png); /* IE9+ 不支持多背景 */ background-image: url(data:image/svg+xml;base64,....), none; }
.portal .lbf-combobox #user-id.lbf-combobox-label { /* ... */ }
解析顺序:从右到左
#user-id { /* ... */ }
CSS selector matching is now reasonably fast for the absolute majority of common selectors that used to be slow at the time of the profiler implementation. This time is also included into the Timeline "Recalculate Style" event.
As such, I believe the CSS selector profiler is not as useful as it [might have been] used to and can safely be dropped. This will also reduce the fraction of developers trying to micro-optimize already fast selectors.
/* index_header.css */ .header .current { background: #FEFEFE; } /* index_list.css */ .current { background: blue; }
/* Block */ .menu { display: block; } /* Element */ .menu__item { float: left; } /* Modifier */ .menu__item_current { background-color: #EFEFEF; }
/* components/submit-button.css */ .common { /* font-sizes, padding, border-radius */ } .normal { composes: common; /* blue color, light blue background */ } .error { composes: common; /* red color, light red background */ }
.components_submit_button__common__abc5436 { /* font-sizes, padding, border-radius */ } .components_submit_button__normal__def6547 { /* blue color, light blue background */ } .components_submit_button__error__1638bcd { /* red color, light red background */ }
/* util.less */ .clearfix() { /* 清除浮动代码 */ }
/* common.less */ /* `g-` 作为全局模块的前缀 */ .g-header { .clearfix(); }
/* page/index.less */ /* `page-` 作为页面class的前缀 */ .page-index { /* 页面模块Block名 */ .header { .clearfix(); /* 页面模块中的Element */ &-menu { /* ... */ } /* 尽可能使用标签,确保 HTML 语义化 */ &-menu li { float: left; } /* Element的状态名 */ /* 非Block命名尽量简写,`cur === current` */ &-menu .header-menu-cur { float: left; } } }
Javascript 用 ID 选择器,CSS 用 Class 选择器
尽量做到“行为和样式分离”
setTimeout(function () { console.log(1); }, 0); console.log(2);
var result = '' + '<h1>' + title + '</h1>' + '<p>' + content + '</p>';
var result = [ '<h1>' + title + '</h1>', '<p>' + content + '</p>' ].join('');
Array.join > +操作符
只是在旧浏览器下(IE7-),现代浏览器中差不多
String.replace 或者模板引擎更好
var tpl = '' + '<h1>{title}</h1>' + '<p>{content}</p>'; var template = function (tpl, data) { return tpl.replace(/{([^}]+)}/g, function (r, $0) { return data[$0] || ''; }); }; var result = template(tpl, { title: '标题', content: '内容' });
var data = { title: '标题', content: '内容' }; var result = `<h1>${data.title}</h1> <p>${data.content}</p>`;
引入了无限滚动特性
页面滚动时速度变的很慢!
jQuery 1.4.2 升级到 1.4.4
$(window).bind('scroll', function () { if (nearBottomOfPage()) { // load more tweets ... } });
$details.find('.details-pane-outer');
jQuery 1.4.3开始选择器引擎 Sizzle 会优先使用 querySelectorAll
// 1.4.2 document.getElementsByClassName('details-pane-outer'); // 1.4.4 document.querySelectorAll('details-pane-outer');
var divs = document.getElementsByTagName("div"); var i = 0; while(i < divs.length){ document.body.appendChild(document.createElement("div")); i++; }
这是一个死循环!
$('a').click(function (e) { dosomething(); });
var links = document.getElementsByTagName('a'); for (var i = 0, l = links.length; i < l; i++) { links[i].onclick = (function (link) { dosomething(); })(links[i]); }
链接多了之后很慢!
document.body.addEventListener('click', function (e) { e.preventDefault(); var target = e.target; var isLink = target.nodeName === 'A'; if (isLink) { // 记录操作 } }, false);
$('body').on('click', 'a', function () { // 记录操作 });
// 读 var height = element.clientHeight; // 写 element.style.height = (height + 2) + 'px'; // 写 element.style.height = (height + 3) + 'px';
浏览器优化之后,会把DOM操作放到一个队列里面。在将来的某个时候执行(例如屏幕刷新前)
// 读 var height1 = element1.clientHeight; // 写 element1.style.height = (height1 + 2) + 'px'; // 读 var height2 = element2.clientHeight; // 写 element2.style.height = (height2 + 2) + 'px';
此时第二次读操作执行前,会强迫浏览器 relayout 一次,这样才能计算得到新的 height
// 读 var height1 = element1.clientHeight; // 读 var height2 = element2.clientHeight; // 写 element1.style.height = (height1 + 2) + 'px'; // 写 element2.style.height = (height2 + 2) + 'px';
读写分离,减少 layout thrashing
function call1() { // 读 var height1 = element1.clientHeight; // 写 element1.style.height = (height1 + 2) + 'px'; } function call2() { // 读 var height2 = element2.clientHeight; // 写 element2.style.height = (height2 + 2) + 'px'; } call1(); call2();
不一定 DOM 操作都在一个方法体里面
function call1() { // 读 var height1 = element1.clientHeight; // 写 requestAnimationFrame(function() { element1.style.height = (height1 + 2) + 'px'; }); } function call2() { // 读 var height2 = element2.clientHeight; // 写 requestAnimationFrame(function() { element2.style.height = (height2 + 2) + 'px'; }); }
话说回来,一般调用没那么频繁。只是特殊情况下(动画)需要注意优化