Reactjs 列表優化的一些心得

2022-08-17 08:06:08 字數 3277 閱讀 2819

在應用開發中,列表是我們使用頻率非常高的一種展現形式,在reactjs專案中更是如此。無處不在的使用更是需要我們小心觸發效能瓶頸的深水炸彈。

reactjs要求我們對列表中的每一項設定乙個唯一的key值,這個虛擬dom的diff演算法有很大關係。簡單的說,在同一級dom樹中,有2種情況會引起元素(這裡的元素指的是虛擬dom,而不是真正的dom元素)的增刪。

1.元素的型別改變

2.key值變化

在列表中,元素型別一般是相同的,所以我們需要根據唯一的key值來給當前元素加上標記,這樣reactjs才能感知元素是否需要增加或刪除了。

reactjs採用的非常直接粗暴的演算法來判斷元素的增刪,比如

舊的

a

b

新的

abc

d

我們來分析下這種情況下的流程:

對比第一項key都是1,內容不變,不處理

對比第二項key都是2,內容不變,不處理

第三項key為3的是新的,新增

第四項key為4的是新的,新增

這個例子中我們使用索引(+1)作為key,沒有什麼問題,完全符合我們的預期。接下我們看第二個

假設我們的的列表資料從

[,,

]

變成了

[,,

,]

仍然使用索引作為key,那麼渲染出來的應該是

舊的

b

ce

新的

abc

d

這種情況下的流程:

對比第一項key都是1,但是內容變了,替換文字

對比第二項key都是2,但是內容變了,替換文字

對比第三項key都是3,但是內容變了,替換文字

第四項key為4是新的,新增

這個和我們想的就有區別了,因為我們只是想做兩步操作,即替換第1個和新增第4個。而現在做了四步操作。

也許這個例子顯得沒有那麼糟糕,但是想象一下,如果是在乙個50項的列表中插入1個新的到頭部,那麼後面的50項將都會進行dom更新渲染,如果每一項內容是複雜的元件,那麼代價更加高昂,而我們其實只是想在第乙個元素前插入一條。

那麼如果解決上面的問題呢,其實很簡單,我們的列表資料都有唯一的id值,而實際開發中我們列表中一般都會存在這樣的唯一值,我們只需要把它複製給key即可

那麼我們的列表會變成這樣

舊的

b

ce

新的

abc

d

這種情況下的流程:

第一項key為1是新的,新增,節點變成4個

對比第二項key都是2,內容不變,不處理

對比第三項key都是3,內容不變,不處理

第四項key為4,舊的是5,替換節點

我們可能已經習慣這樣寫列表

render()
在大多數情況下,這樣寫沒有什麼問題,reactjs執行速度很快,但是有些情況下,這樣寫可能成為導致網頁卡頓的罪魁禍首。

每當我們改變元件狀態的時候,reactjs都會重建當前元件的整個虛擬dom樹,也就是說不管你的state.list是否有改變,整個樹都會重建,而這個時候列表的渲染是不必要的,當列表過長,元件狀態更新頻繁,甚至手機效能不佳的情況下,不斷的重新建立虛擬dom樹很有可能會導致頁面幀數下降。

purecomponent和component沒什麼什麼區別,除了它預設在shouldupdatecomponent裡面預設做了淺比較,如果相同,則不會觸發更新渲染。

reactjs中,資料推薦處理成不可變資料(這裡不是指immutable.js,而是說物件始終是不變的,如果資料有變了,必須是新的物件),配合redux的時候更是如此。所以如果list發生改變時,傳入的必然是新的物件,這個時候會觸發列表元件更新。

class list extends purecomponent

}/*** parent ***/

// .....

render()

// ...

當我們列表的子元素是複雜的組建時,我們也應該單獨提取成purecomponent,以避免不必要的渲染,事實上,我覺得大多數元件都可以使用purecomponent替換component

箭頭函式很方便,不僅寫法簡單還能保持this指向父級作用域。

為了維護事件處理函式的this,我們經常在元件中看到它類似這樣的使用

/>
但是這樣寫會有幾個問題

每次render都會重新建立乙個新的函式,瀏覽器建立和**物件都會有開銷,如果是列表,那麼每個列表項都會建立和銷毀。

因為每次render都是傳入新的函式,shouldupdatecomponent淺比較必然不相等,會導致purecomponent元件失去應有效果。

如果使用了transform-class-properties

handleclick = ()=>
或者

constructor()

handleclick = ()=>

列表的一些方法

1.列表的定義 列表是乙個有序的,可修改的 增刪查改 元素以逗號分隔,以中括號包圍的序列。練習 定義乙個列表 2.列表的增刪查改 排序 列表的新增 函式 用法 pop 彈出,返回並刪除指定索引位上的資料,預設刪除索引為 1 最後乙個 的資料 remove 從左往右刪除乙個指定的元素 del 刪除整個...

優化的一些例項

優化使用的工具,使用loadrunner做為壓力測試工具,使用jprobe進行 剖析。1 第乙個例項。原狀況 呼叫乙個api,發現執行的時間很高,用jprobe分析,發現消耗時間最長的是把快取中的乙個樹從第三個節點進行扁平化,就是把第二個節點的子樹構造為乙個列表,不知道為什麼構造這個資料的耗時比直接...

mysql的一些優化

前言 sql優化,是一種概率層面的優化。至於是否實際使用了我們的優化,需要通過explain進行推測。注意 服務層中有sql優化器,可能會影響我們的優化,同時註明 sql的優化前提是有索引 有索引 有索引 in和exists的使用場景 select from a where exists selec...