前端開發(fā)規(guī)范
1.HTML規(guī)范
1.1.使用正確的HTML5文檔類型
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="renderer" content="webkit"> <!-- 360使用極速模式渲染 -->
<title>Document</title>
</head>
<body>
</body>
</html>
1.2 兼容的meta屬性
<meta name="renderer" content="webkit"> <!-- 360使用極速模式渲染 -->
1.3 統(tǒng)一使用4空格的tab縮進
1.4.避免不規(guī)范的元素嵌套
錯誤示例:
<ul>
<div>導航欄標題</div>
<li>子項1</li>
<li>子項2</li>
<ul>
正確示例:
<div>導航欄標題</div>
<ul>
<li>子項1</li>
<li>子項2</li>
<ul>
ul
標簽只允許存在li
作為其直接子標簽婴谱。錯誤示例中的代碼雖然可以正常渲染火架,但是由于不同瀏覽器容錯機制不一致,錯誤的示例代碼可能會導致額外的hack铛嘱。
1.5.自定義屬性采用data-*
格式
錯誤示例:
<div ng-click="click()">
正確示例:
<div data-ng-click="click()">
data-*
是HTML5的標準規(guī)范,如不采用data-*
格式,IDE會顯示警告信息扬跋,避免警告信息影響正常的debug,建議采用data-*
格式自定義屬性凌节。
1.6.布爾類型的屬性钦听,建議不添加屬性值
錯誤示例:
<input type="checkbox" checked="true">
<input type="checkbox" checked="flase">
<input type="checkbox" checked="checked">
正確示例:
<input type="checkbox" checked>
獲取選擇選中狀態(tài),使用dom節(jié)點對象的checked屬性倍奢,或者jQuery的is方法朴上,不要使用attr('checked')進行判斷。
錯誤做法:
var $checkbox = $('input[checkbox]');
$checkbox.attr("checked"); // 不準確卒煞,甚至會取得非預期值
正確做法:
$checkbox.is(':checked');
$checkbox.check = true;
$checkbox.check;
2.CSS規(guī)范
2.1.確定全局唯一的元素痪宰,可以使用id,否則使用class
否則會導致后期維護成本過大畔裕。
2.2.選擇器應盡量避免嵌套衣撬,最多不過3級別
不好的做法:
body #container .head .title {
// code here
}
推薦做法:
.h-title {
// code here
}
嵌套過多,會導致css權重過大,子class跟父class緊耦合柴钻,后期維護成本大淮韭。
3.JavaScript規(guī)范
3.1.字符串統(tǒng)一使用單引號包含
不好的示例:
var msg = "Hello JavaScript!";
正確示例:
var msg = 'Hello JavaScript!';
使用單引號的最主要原因是垢粮,避免額外的單引號\雙引號轉義贴届。
var dom = “<div data-ng-click=\"click();\">雙引號\"\"不建議</div>”;
vs
var dom = '<div data-ng-click="click();">雙引號""不建議</div>';
兩種寫法對比,優(yōu)劣一目了然蜡吧。
3.2.避免使用JavaScript拼接HTML
使用JavaScript拼接HTML毫蚓,會有以下問題:
- 極容易產生XSS漏洞;
- 關注點不分離昔善,升級維護極其困難元潘;
- 開發(fā)效率低下,代碼不健壯君仆,非常容易產生bug翩概;
- Debug變的異常艱難牲距;
不好的示例:
var names = ['tiger','apple', '<script>alert("xss");</script>'];
var dom = '<ul>';
names.forEach(function(name,index){
dom += '<li>' + name + '</li>';
})
dom += '</ul>';
$('body').html(dom);
上面的代碼會導致一下問題:
- names[2]插入頁面后,
<script>alert("xss");<script>
會被當成腳本執(zhí)行钥庇,容易被用戶利用牍鞠,入侵系統(tǒng); - 代碼升級維護困難评姨,如果要修改樣式难述,或者渲染的對象更加復雜(多層嵌套),維護這樣的代碼不僅效率低下吐句,容易出錯胁后,簡直就是噩夢;
- 產生bug的情況下嗦枢,調試異常復雜攀芯;
正確示例:
AngularJS寫法:
<ul>
<li data-ng-repeat="name in names">{{ name }}</li>
</ul>
如果使用jQuery情況下,可以使用前端模板引擎文虏,例如doT.js敲才、jQuery Template等。
3.3 JavaScript語法技巧
使用這些小技巧择葡,可以讓代碼更加簡潔紧武、容易理解。
3.3.1 默認參數賦值
冗長寫法:
function fun(param) {
if(param == null) {
param = {name:'tiger'};
}
}
簡潔寫法:
function fun(param) {
param = param || {name:'tiger'};
}
3.3.2 判空執(zhí)行
冗長寫法:
function fun() {
if(flag) {
callback();
}
}
簡潔寫法:
function fun() {
flag && callback();
}
3.3.3 自調用函數
冗長寫法:
function fun(){
// code here
}
fun();
簡潔寫法:
(function(){
// code here
})();
3.3.4 數組迭代
冗長寫法:for
簡潔寫法:filter敏储、some阻星、every、forEach已添、map
3.3.4.2 filter:對數組進行過濾妥箕,并返回新的數組
var s = [1,2,3,4,5];
var ns = s.filter(function(item,index) {
return item > 3;
})
console.log(ns); // [4,5]
3.3.4.3 some:判斷數組中是否有符合條件的元素
var s = [1,2,3,4,5];
var b = s.some(function(item,index) {
return item > 3;
})
console.log(b); // true
3.3.4.4 every:判斷數組中所有元素是否都符合條件
var s = [1,2,3,4,5];
var b = s.every(function(item,index) {
return item > 3;
})
console.log(b); // false
3.3.4.5 map:對數組中的元素進行處理,并返回新的數組
var s = [1,2,3,4,5];
var ns = s.map(function(item,index) {
return item * 2;
})
console.log(ns); // [2,4,6,8,10]
3.3.4.6 forEach:迭代數組元素
var s = [1,2,3,4,5];
var ns = s.map(function(item,index) {
console.log(item); // 依次打印1更舞,2畦幢,3,4缆蝉,5
})
3.4. 前端開發(fā)的JavaScript技巧
3.4.1 使用Angular時宇葱,ajax請求請使用ng自帶的$http,避免使用jQuery的ajax
$http的ajax回調會自動更新DOM節(jié)點,而jQuery的回調沒有這個特征刊头,需要手動apply黍瞧。
<div>{{ user.username }}</div>
正確的jQuery寫法:
$.post('/login',{username:'tiger',passwd='123456'},function(rs){
$scope.user = rs.user;
$scope.$apply();
})
正確的AngularJS寫法:
var params = {username:'tiger',passwd='123456'}
$http({method : 'POST',url : '/login', data: $.param(params)
}).then(function(rs) {
$scope.user = rs.data.user;
});
如果是GET請求,data則改成params原杂,同時不需要$.param序列化印颤,params的參數放url上,而data是放request body中穿肄。
var params = {username:'tiger',passwd='123456'}
$http({method : 'GET',url : '/login', params: params
}).then(function(rs) {
$scope.user = rs.data.user;
});
3.4.2 HTTP請求中年局,獲取使用GET际看,提交、修改和刪除使用POST
這樣更加符合REST的語義矢否,如果POST使用GET代替仿村,在開發(fā)階段就難以調試,而且無法使用GET的特性進行一系列調優(yōu)兴喂,例如緩存等蔼囊。
HTTP中,GET/POST/DEL等的區(qū)別:http://www.cnblogs.com/zhangpengshou/archive/2012/07/09/2583096.html
3.4.3 獲取ajax的表單參數衣迷,jQuery可以將form表單序列化畏鼓,Angualr可以綁定對象
推薦的jQuery寫法:
<form id="loginFrom">
<input name="username" type="text" />
<input name="password" type="passwrod"/>
</form>
<script>
var params = $('#loginForm').serialize();
$.post('/login',params,function(rs){
// callback
});
</script>
推薦的AngularJS寫法:
<form>
<input type="text" data-ng-model="loginForm.username" />
<input type="passwrod" data-ng-model="loginForm.password"/>
</form>
<script>
$http({
method : 'POST',
url : '/login',
data: $.param($scope.loginForm)
}).then(function(rs) {
// callback說
});
</script>
3.4.4 jQuey調用AngularJS的方法
思路:取得AngularJS作用域下的節(jié)點找到scope,通過scope調用方法:
var container = $('#container'); // #containe要在data-ng-app的子節(jié)點下
angular.element(container).scope().fun(); // 調用AngularJS下面的fun方法壶谒;
強烈推薦使用Angular開發(fā)云矫,jQuery的功能基本95%以上都可以用Angular代替,代碼量更少汗菜,更容易維護让禀。
JavaScript的String添加了個encodeHTML方法,可以對HTML的特殊字符進行轉義陨界,實現(xiàn)如下:
String.prototype.encodeHTML = function () {
var div = document.createElement('div');
div.appendChild(document.createTextNode(this));
return div.innerHTML;
}
如果輸出到頁面的內容由HTML拼接完成巡揍,且內容存在用戶輸入的部分,則拼接過程中菌瘪,對應字段需要經過HTML轉義腮敌,用法如下:
function format(name){
return '<div>' + name.encodeHTML() + '</div>';
}
腳本實現(xiàn)在eompBase.js中,導入該腳本的頁面俏扩,都可以按照上面的寫法進行轉義糜工。