Web 最佳实践
前端
选择器
- 尽量使用ID选择器
- 基于Id的选择器:先使用ID选择器定位,然后再使用find方法精确查找
// Fast:
$( "#container div.robotarm" );
// Super-fast:
$( "#container" ).find( "div.robotarm" );
- 指定选择的上下文
// 劣质的代码:因为需要遍历整个DOM来找到.class
$('.class');
// 高品代码:因为只需在指定容器范围内进行查找
$('.class', '#class-container');
这一条是否有上一条等同?
- 多级查找:右边尽量指定得详细点而左边则尽量简单点
// Unoptimized:
$( "div.data .gonzalez" );
// Optimized:
$( ".data td.gonzalez" );
- 避免冗余
$( ".data table.attendees td.gonzalez" );
// Better: Drop the middle if possible.
$( ".data td.gonzalez" );
- 不要ID与其它选择器混搭
ID已经表示唯一了,再加上其它选择符只会加重选择器的负担
$('#outer #inner'); // 脏
$('div#inner'); // 乱
$('.outer-container #inner'); // 差
$('#inner'); // 干净利落,后台只需调用document.getElementById()
- 不要使用万能选择器
$( ".buttons > *" ); // Extremely expensive.
$( ".buttons" ).children(); // Much better.
$( ".category :radio" ); // Implied universal selection.
$( ".category *:radio" ); // Same thing, explicit now.
$( ".category input:radio" ); // Much better.
Dom 操作
-
避免DOM节点频繁流化
样本代码
$.each( myArray, function( i, item ) {
var newListItem = "<li>" + item + "</li>";
$( "#ballers" ).append( newListItem );
});
-
方法一: 临时detach
var ballers = $("#ballers");
var parent = ballers.parent();
ballers.detach();
$.each(myArray, function(i, item) {
var newListItem = "<li>" + item + "</li>";
ballers.append(newListItem);
});
parent.append(ballers);
var table = $( "#myTable" );
var parent = table.parent();
table.detach();
// ... add lots and lots of rows to table
parent.append( table );
-
方法二:创建临时DOM节点
var frag = document.createDocumentFragment();
$.each( myArray, function( i, item ) {
var newListItem = document.createElement( "li" );
var itemText = document.createTextNode( item );
newListItem.appendChild( itemText );
frag.appendChild( newListItem );
});
$( "#ballers" )[ 0 ].appendChild( frag );
-
方法三:append html
var myHtml = "";
$.each( myArray, function( i, item ) {
myHtml += "<li>" + item + "</li>";
});
$( "#ballers" ).html( myHtml );
临时改变多个节点样式
// Fine for up to 20 elements, slow after that:
$( "a.swedberg" ).css( "color", "#0769ad" );
// Much faster:
$( "<style type=\"text/css\">a.swedberg { color: #0769ad }</style>")
.appendTo( "head" );
//预定义css类会更好
// .swedberg_color{color:#0769ad}
$( "a.swedberg" ).addClass("swedberg_color" );
CSS
JS 编码
-
代码组织
-
链式写法要换行
$("#myLink")
.addClass("bold")
.on("click", myClickHandler)
.on("mouseover", myMouseOverHandler)
.show();
链式写法中避免使用匿名函数,否则会严重影响代码易读性
-
使用变量保存选择器结果方便重用
//bad
$("#myLink").addClass("bold");
//stuff
$("#myLink").on("click", myClickHandler)
//better
var myLink=$("#myLink").addClass("bold");
//stuff
myLink.on("click", myClickHandler)
-
利用闭包保持代码整洁
//bad
var privateThing = "secret";
var publicThing = "not secret";
var changePrivateThing = function() {
privateThing = "super secret";
};
var sayPrivateThing = function() {
console.log( privateThing );
changePrivateThing();
};
sayPrivateThing();
//better
var feature = (function() {
// Private variables and functions
var privateThing = "secret";
var publicThing = "not secret";
var changePrivateThing = function() {
privateThing = "super secret";
};
var sayPrivateThing = function() {
console.log( privateThing );
changePrivateThing();
};
// Public API
return {
publicThing: publicThing,
sayPrivateThing: sayPrivateThing
};
})();
feature.sayPrivateThing();
-
- 利用“事件冒泡”机制进行事件绑定
//bad
$('ul>li').on('click',clientHandler);
//better
$('ul').on('click','li',clientHandler);
- 数组循环中不要每次循环都访问数组的长度,应该先缓存长度
//好的写法
var myLength = myArray.length;
for ( var i = 0; i < myLength; i++ ) {
// do stuff
}
//好的写法
for ( var i = 0,myLength=myArray.length; i < myLength; i++ ) {
// do stuff
}
//差的写法
for ( var i = 0; i < myArray.length; i++ ) {
// do stuff
}
- 其它
//bad
// 糟糕:调用了三次attr
$myLink.attr("href", "#").attr("title", "my link").attr("rel", "external");
//better
// 不错,只调用了一次attr,css函数与此类似
$myLink.attr({
href: "#",
title: "my link",
rel: "external"
});
参考
+