觸發render條件
1.組件mount
React組件構建并將DOM元素插入頁面的過程稱為掛載。當組件首次渲染的時候會調用render,這個過程不可避免。
2.setState方法被調用(組件或父組件中)
通常情況下執行setState會觸發 render。
執行setState的時候一定會重新渲染嗎?不一定,當setState傳入null的時候,不會觸發render;如果setState的參數不變,即判斷state并未發生改變,也不會重新渲染。
3.父組件重新渲染
原則:只要一個節點變了,那么從它開始回溯的父節點全都是變的
react父節點數據變了,但傳給子節點的沒變,子節點變不變?只要父組件重新渲染了,即使傳入子組件的props未發生變化,子組件也會重新渲染進而觸發render。
如何在數據不變的情況下阻止子節點render?shouldComponentUpdate/pure component/memo
4.調用forceUpdate
渲染詳細過程:
1.調用React.createElement()編譯成虛擬v-DOM節點
2.diff
3.調用ReactDOMComponent(vdom).mountComponent()將虛擬DOM變成真實的DOM
4.調用appendChild(domNode)插入DOM樹,顯示出來
更新視圖的過程(diff、patch)
Rendering
Batching
Whenever you call?setState?on a component, React will mark it as dirty. At the end of the event loop, React looks at all the dirty components and re-renders them.
This batching means that during an event loop, there is exactly one time when the DOM is being updated. This property is key to building a performant app and yet is extremely difficult to obtain using commonly written JavaScript. In a React application, you get it by default.
Sub-tree Rendering
When?setState?is called, the component rebuilds the virtual DOM for its children. If you call?setState?on the root element, then the entire React app is re-rendered. All the components, even if they didn’t change, will have their?render?method called. This may sound scary and inefficient but in practice, this works fine because we’re not touching the actual DOM.
First of all, we are talking about displaying the user interface. Because screen space is limited, you’re usually displaying on the orders of hundreds to thousands of elements at a time. JavaScript has gotten fast enough business logic for the whole interface is manageable.
Another important point is that when writing React code, you usually don’t call setState on the root node every time something changes. You call it on the component that received the change event or couple of components above. You very rarely go all the way to the top. This means that changes are localized to where the user interacts.
性能和渲染(Render)正相關
React的處理render的基本思維模式是每次一有變動就會去重新渲染整個應用。在Virtual DOM沒有出現之前,最簡單的方法就是直接調用innerHTML。
當DOM樹很大時,遍歷兩棵樹進行各種比對還是相當耗性能的,特別是在頂層setState一個微小的修改,默認會去遍歷整棵樹,這個過程會損耗性能。
VirtualDOM厲害的地方并不是說它比直接操作DOM快,而是說不管數據怎么變,都會盡量以最小的代價去更新DOM。React將render函數返回的虛擬DOM樹與老的進行比較,從而確定DOM要不要更新、怎么更新。
基于虛擬DOM和高效Diff算法的完美配合,實現了對DOM最小粒度的更新。在個別復雜業務場景下,性能問題依然會困擾,此時需要采取一些措施來提升運行性能,很重要的一個方向就是避免不必要的渲染。
優化Render
當子組件過多或者組件的層級嵌套過深時,反復重新渲染狀態沒有改變的組件,可能會增加渲染時間又會影響用戶體驗,此時就需要對render進行優化。不必要的render會帶來性能問題,因此主要優化思路就是減少不必要的render。
Selective Sub-tree Rendering
Finally, you have the possibility to prevent some sub-trees to re-render. If you implement the following method on a component:
boolean shouldComponentUpdate(object nextProps, object nextState)
based on the previous and next props/state of the component, you can tell React that this component did not change and it is not necessary to re-render it. When properly implemented, this can give you huge performance improvements.
In order to be able to use it, you have to have to be able to compare JavaScript objects. There are many issues that raises such as should the comparison be shallow or deep; if it’s deep should we use immutable data structures or do deep copies.
And you want to keep in mind that this function is going to be called all the time, so you want to make sure that it takes less time to compute than heuristic than the time it would have taken to render the component, even if re-rendering was not strictly needed.
第一次進入到頁面的時候,會在沒數據的情況下有一次渲染;等fetch成功后會再一次進行渲染。怎么解決第一次進入頁面沒數據的情況下,頁面渲染時不報錯?
1.給定同fetch回來的數據格式一樣的默認數據,數組使用空數組,對象則屬性都需要存在,值為默認值或者空值。
2.思路是條件渲染,設置一個判斷條件,條件值不同,渲染的組件不同。
constructor(){
? ? this.state = {
? ? ? ? isLoading = true,
? ? ? ? data: []
? ? }
}
render(){
? ? return (
? ? ? ? {
? ? ? ? ? ? this.state.isLoading
? ? ? ? ? ? ? <Loading />
? ? ? ? ? ? : <Content />
? ? ? ? }
? ? )
}
3. 使用? operator
一個模塊中props,data中存在同名的變量,會渲染哪一個,為什么?
react結合immutable.js為什么能提高渲染效率