最近在閱讀《高效前端:Web高效程式設計與優化實踐》這本書,書中介紹了前端高效程式設計的優化實踐和前端基礎。本文將結合個人的理解介紹部分高效程式設計的例子。
能用HTML/CSS解決的問題就不要用JS
自定義radio/checkbox的樣式
表單中原生的radio/checkbox的樣式各個瀏覽器都不太一致。要想統一樣式,一種做法是自己div/span
去畫,然後去監聽單擊事件。這種做法就是邏輯控制完全要自己寫,還有原生事件change
也無法使用。
這裡可以通過CSS提供偽類checked
來實現自定義樣式。原理是把一個checkbox
和一個用來自定義樣式的span
寫在一個label
裡面,checkbox
始終隱藏。
<style>
input[type=checkbox]{
display: none;
}
/*未選中的checkbox的樣式*/
.checkbox{ /* 實現略 */ }
input[type=checkbox]:checked + .checkbox{ /* 實現略 */ }
</style>
<label for="apple">
<input type="checkbox" id="apple">
<span class="checkbox"></span>
</label>
複製程式碼
需要根據個數顯示不同樣式
有1~3個items要顯示在同一行, 但是item的個數不一定,就一個的話item佔寬100%,兩個時各佔50%,三個時各佔33%。顯然你可以用js來計算,但是這樣有點繁瑣。
我們可以通過CSS3的first-child
和nth-last-child
來實現個數的區分
<style>
li {
width: 100%
}
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li{
width: 50%
}
li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li{
width: 33%
}
</style>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
複製程式碼
用CSS畫一個三角形
這個技巧應該是比較常見,通過把寬高設定為0,同時只設定一個邊的border來畫三角形。下面提供一些其他三角形畫法:
// 斜邊在左邊的三角形
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
border-left: 50px solid #000;
// 直角三角形
border-left: 60px solid transparent;
border-right: 0 solid transparent;
border-bottom: 40px solid #000;
// 等邊三角形
border-left: 28px solid transparent;
border-right: 28px solid transparent;
border-bottom: 40px solid #000;
複製程式碼
減少前端程式碼耦合
JS/CSS/HTML的耦合
不推薦直接在JS裡面更改樣式屬性, 應該通過增刪類來控制樣式,除了scroll和mousemove
策略模式
// common
function popCallback(popType){
switch(popType){
case: "favHouse":
favHouse();
break;
case: "saveSearch":
saveSearch();
break;
}
}
// strategy
var popCallback = {
favHouse: function(){ /*do sth.*/ },
saveSearch: function(){ /*do sth.*/ }
}
if(typeof popCallback[popType] === "function"){
popCallback[popType]();
}
複製程式碼
JS書寫優化
按強型別風格寫程式碼
這邊其實也可以在專案中靜態型別檢查器(Flow、TypeScript)來優化程式碼。書中有介紹幾點還不錯建議:
- 定義變數的時候要指明型別
var num = 0,
str = ``,
obj = null;
複製程式碼
- 不要隨意改變變數的型別
// bad
var num = 5;
num = "-" + num;
// good
var num = 5;
var sign = "-" + num;
複製程式碼
- 函式的返回型別應該是確定的
// bad
function getPrice(count){
if(count < 0) return "";
else return count * 100;
}
// good
function getPrice(count){
if(count < 0) return -1;
else return count * 100;
}
複製程式碼
減少作用域查詢
全域性作用域比較複雜,所以查詢屬性比較慢。區域性作用的查詢是很快的
// bad
var url = "";
if(window.location.protocal === "https:"){
url = "wss://xxx.com" + window.location.pathname + window.location.search;
}
// good 快取成區域性變數
var url = "";
var location = window.location;
if(location.protocal === "https:"){
url = "wss://xxx.com" + location.pathname + location.search;
}
複製程式碼
避免==的使用
我們的程式碼中應該避免==
的使用,應該使用===
,這樣可以避免js型別轉換帶來的一些意外的結果。
==
建議的使用場景是判斷變數是否為空的時候,即if(obj == null)
使用ES6簡化程式碼
- 使用箭頭函式取代小函式
var nums = [4, 8, 1, 9, 0];
nums.sort((a, b) => b - a);
複製程式碼
- 字串拼接
var tpl =
` <div>
<span>1</span>
</div>
`;
var url = `/list?page=${page}&type=${type}`;
複製程式碼
- 塊級作用域變數
var tasks = [];
for(let i = 0; i <= 4; i++){
tasks.push(function(){
console.log("i is " + i);
});
}
for(var j = 0; j < tasks.length; j++){
tasks[j]();
}
複製程式碼
增強使用者的體驗
加Loding效果
常見的Loading都有圖片載入、AJAX請求、上傳檔案進度條。還有一個最近流行的骨架屏(skeleton loading)
樣式、文案
這部分可以去看下一些UI庫的基本理念和設計原則,如antd-design
用好Chrome Devtools
Chrome Devtools除錯建議可以看下F12裡面的官方文件。
列印
console.table
列印物件陣列console.dir
能遞迴列印物件的所有屬性,列印一個DOM結點
檢查沒有用的CSS/JS
devtools的Coverage標籤欄,沒有用到的用紅色表示, 用到的用綠色表示
研究重繪
devtools有一個Renders可以用來研究重繪
總結
書中的優化實踐點還是很多的,我這邊就介紹部分相對比較常用的。其實優化實踐給出了比較好的方案,但是實際還是要結合具體情況來選擇方案的。