談到react優化,估計說的最多的就是減少子元件渲染,減少真實dom操作等。
一 減少渲染
1. shouldcomponentupdate
通過對props和state的淺比較,如果沒有變化,return false,避免重複多餘的render方法呼叫,省去虛擬dom的生成和對比過程,提高效能。
早期類似的技術有purerender,16版本中可以直接讓class元件繼承purecomponent,它的實現其實很簡單,只是做淺比較,因為過深的比較也會消耗很多的時間,或許還比render方法帶來的消耗大,所以這其實是權衡和取捨。
注意這裡的淺比較,基礎型別比較值是否相等,不等則需要再次渲染;對於引用型別,先比較引用的位址,位址相同,不渲染,位址不同,判斷兩個物件的keys的長度,長度不等,則需要渲染,相等則對第一層屬性比較,如果有不同,則渲染,否則不渲染。下面的code則是核心主要邏輯。
注意object.is(es6推出的)和===的主要區別,是object.is(+0,-0) === false, object.is(nan,nan) === false
function is(x, y)var is$1 = typeof object.is === 'function' ?object.is : is;
var hasownproperty$2 =object.prototype.hasownproperty;
//返回值:false更新 true不更新
function
shallowequal(obja, objb) //
由於object.is 可以對基本資料型別做乙個精確的比較 如果不等只有一種情況 那就是object, obja/objb中,只要有乙個不是object或為null則返回false
if (typeof obja !== 'object' || obja === null || typeof objb !== 'object' || objb === null
)
//過濾掉基本資料型別 就是物件比較 首先比較長度 優化效能
//比較oldprops和新的props以及oldstate和newstate長度是否相同 如果長度不同則重新更新渲染 如果長度相同則不用重新渲染 如果不相等 不會往下執行 優化效能
var keysa =object.keys(obja);
var keysb =object.keys(objb);
if (keysa.length !==keysb.length)
//如果key相等
//如果obja的屬性不在objb裡,或者是obja的屬性值和objb的屬性值不等 則重新渲染 不考慮當keysa[i]為物件的多層問題 淺顯比較 提高效能
for (var i = 0; i < keysa.length; i++)
return
true; }
}
2. react.memo()
由於purecomponent是只能用於class元件的繼承,react為了支援函式元件,所以又推出了乙個高階元件react.memo(), 當props變化時做淺比較。注意如果用usestate或者usecontext等hooks導致state狀態變化時,函式元件依然會重新渲染,否則復用上一次的渲染結果(復用上一次生成的虛擬子節點dom)。
const child = memo(props =>, [json.stringify(props.schema)]);return
child
;});
//another case
const childmedo = react.memo(() =>);
3. usememo
用於函式元件,減少計算一些中間值,廢話別太多,show you code。
export defaultfunction
usememodemo() , [count]);
return
-
setcount(count + 1)}>+c1
setvalue(event.target.value)}/>
;}
4. redux中的優化
對於 redux 來說,每當 store 發生改變時,所有的 connect 都會重新計算。在乙個
大型應用中,浪費的重複計算可想而知。為了減少效能浪費, 我們想到對 connect 中的這些 selector
函式做快取。
redux 擁抱了函式式程式設計,而在函式式程式設計中,純函式的眾多好處之一就是方便做快取。那
麼,如何用純函式做快取呢?
在數學上,如果自變數不變,因變數總是不變。同樣,用相同的引數執行純函式多次,每次
返回的結果一定相同。也就是說,如果純函式的引數不變的話,可以把之前用同樣的引數計算出
來的結果直接返回。 (摘自《深入react技術棧》)
我們可以直接使用reselect庫幫我們完成。
export function defaultmemoize(func, equalitycheck =defaultequalitycheck)lastresult =func(...args)
lastargs =args
return
lastresult
}}
defaultmemoize 函式運用了閉包的原理,使純函式的引數和結果快取在記憶體中。為了讓
defaultmemoize 函式中快取的資料常駐記憶體,我們需要讓 defaultmemoize 處於全域性作用域,或者
用其他作用域鏈連線到全域性作用域。
5.高階reducer分析出哪些reducer或action耗費的時間太長,預警, 這樣之後就可以有針對性優化。
export defaultfunction logslowreducers(reducers, thresholdinms = 8) took $ ms
for$`);
}return
result;
};});
return
reducers;
}
6. 特定的action
在 redux 中,每個 action 被分發,所有的 reducer 都會被執行一次。雖然每個 reducer 僅僅只
是執行乙個 switch 判斷,但所有的 reducer 加起來的執行時間也不容小覷。
大多數情況下,應用的 action 都是和某個 reducer 對應。因此,我們可以指定特殊情況,讓
redux 在特殊情況之外只執行與 action 對應的那個 reducer 。
7. 合併多個action
比如有5個同步action,依次觸發,每乙個action都需要乙個很大的redux流程,以及dom樹的更新,我們可以通過一些辦法合併他們,只產生乙個最終的state,最後再一次性更新元件樹。
8. 提高程式設計技巧,避免屬性每次都傳入乙個新物件
比如字面量prop = ,每次都會產生要給新的物件
比如我們經常使用的合成事件的繫結。()=> {}, 或者onchange.bind(this), 最好儲存為類的成員屬性做快取。
9. 其他
使用redux標準接入元件方式,connect方法的第4個引數options=,預設也會對傳入屬性做淺比較,避免被包裝元件重複不必要的渲染。
其實還有很多。
二 刻意去迎合diff演算法
1. 同級別的元素使用唯一key,減少diff比較,增強復用,比如使用繫結元素的id。
2. 避免(元件結構)節點的跳躍變動,因為diff演算法只會同級別比較,一旦發現不同就會大刀闊斧地剪枝或增枝。
3. 同級別節點中,避免因為**問題,產生太多的移動。
比如有5個兄弟元素,只有最後乙個元素(索引為4)調到第乙個位置來,其他節點索引都變大1位,react的diff演算法是,索引變小不移動,索引變大需要移動,so,這就會增加出其餘4個元素向後移動4次真實 dom操作。
當然react的diff演算法的時間複雜度已經從o(n^3)優化到 o(n),從2/8原則的角度來看,絕大多數場景的效能已經很棒了。
SQL優化點滴記錄
1 在where和order by 涉及的列上加索引 2 引擎會放棄使用索引的情況 1 避免where子句字段進行null值判斷 2 避免where子句中使用 或 操作符 3 避免where子句中使用or。3 慎用in 和not in,in和not in也會進行全表掃瞄 4 like 子句盡量少用,...
React 效能優化
避免重複渲染 當乙個元件的props或者state改變時,react通過比較新返回的元素和之前渲染的元素來決定是否有必要更新實際的dom。當他們不相等時,react會更新dom。在一些情況下,你的元件可以通過重寫這個生命週期函式shouldcomponentupdate來提公升速度,它是在重新渲染過...
react 效能優化
在shouldcomponentupdate 方法中判斷props和state是否改變,若未改變則無需渲染。有些情況如父元件的props或state改變了,但是子元件其實未改變,若不判斷的話會導致子元件一起被渲染。shouldcomponentupdate nextprops nextstate r...