網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
前言
最近看了一下 ant-design 中的 tree 組件源碼時(shí)發(fā)現(xiàn) useEffect 中根據(jù) props 來(lái)計(jì)算當(dāng)前函數(shù)組件的 state 的,感到好奇,因?yàn)檫@樣會(huì)導(dǎo)致應(yīng)用重新繪制一次,這樣才復(fù)雜場(chǎng)景下會(huì)對(duì)應(yīng)用有一定的性能影響。為了驗(yàn)證自己猜想是否正確做了一下實(shí)踐。這里的 React 是官方 16.12.0
的源碼。
優(yōu)化前
import * as React from './react-source/packages/react' import * as ReactDOM from './react-source/packages/react-dom' const root = document.getElementById('root'); function Foo({number}) { const [number2, setNumber2] = React.useState(0); React.useEffect(() => { setNumber2( number + 1) }, [number]) return <div> {number2 % 2 === 0 && <div>{number2}</div>} <button onClick={() => setNumber2(number2 + 1)}>更新 number2</button> </div> } function App() { const [number1,setNumber1] = React.useState(1); return <> {number1 % 2 === 0 && <div>{number1}</div>} <Foo number={number1}/> <button onClick={() => setNumber1(number1 + 1)}>更新 number1</button> </> } ReactDOM.render(<App/>, root)
這里有兩個(gè)組件, APP 函數(shù)組件有一個(gè) number1 的 state,并作用 Foo 函數(shù)組件的 number props傳遞給子組件。Foo 子組件在 useEffect 中 依賴 number 的變化來(lái)更新該組件的 number2 state。
為了監(jiān)聽(tīng) root 節(jié)點(diǎn)變化的情況我使用了 MutationObserver API 來(lái)看看監(jiān)聽(tīng)回調(diào)函數(shù)執(zhí)行了多少次,所以在測(cè)試代碼中增加了如下代碼
const root = document.getElementById('root'); const observer = new MutationObserver(mutations => { console.log(mutations) } ) observer.observe(root, { childList: true, subtree: true })
來(lái)看一下第一渲染時(shí)界面輸出的效果
可以看到 MutationObserver 回調(diào)被執(zhí)行了兩次, mutations 中有兩項(xiàng)新增記錄,對(duì)應(yīng) root 的新增兩個(gè)子節(jié)點(diǎn)。現(xiàn)在再看看我點(diǎn)【更新number1】按鈕之后的結(jié)果
可以看到 MutationObserver 這個(gè)回調(diào)被執(zhí)行了兩次,也就是但這個(gè)按鈕的時(shí)候頁(yè)面繪制了兩次。
優(yōu)化后
import * as React from './react-source/packages/react' import * as ReactDOM from './react-source/packages/react-dom' const root = document.getElementById('root'); const observer = new MutationObserver(mutations => { console.log(mutations) } ) observer.observe(root, { childList: true, subtree: true }) function Foo({number2,setNumber2}) { return <div> {number2 % 2 === 0 && <div>{number2}</div>} <button onClick={() => setNumber2(number2 + 1)}>更新 number2</button> </div> } function App() { const [number1,setNumber1] = React.useState(1); /** * 這里例子可能不太好,因?yàn)榈珡倪@里例子來(lái)看 number 沒(méi)必要再調(diào)用 * useState,實(shí)際項(xiàng)目應(yīng)用場(chǎng)景中有的比較復(fù)雜的邏輯,狀態(tài)之間有關(guān)聯(lián)是 * 比較常見(jiàn)的 */ const [number2, setNumber2] = React.useState(0); return <> {number1 % 2 === 0 && <div>{number1}</div>} <Foo number2={number2} setNumber2={setNumber2}/> <button onClick={() => { let newNumber1 = number1 + 1 setNumber1(newNumber1) setNumber2(newNumber1 + 1) }}>更新 number1</button> </> } ReactDOM.render(<App/>, root)
優(yōu)化有的代碼就是把 Foo 狀態(tài)提升到父組件中,然后把狀態(tài)以及更新函數(shù)傳給子組件就行。這樣我們?cè)賮?lái)看一下點(diǎn)擊【更新number1】之后的效果圖
可以看看到這次 MutationObserver 的回調(diào)只被執(zhí)行了一次。
總結(jié)
項(xiàng)目中還是盡量減少應(yīng)用的重復(fù)繪制次數(shù),不然會(huì)影響用戶的交互體驗(yàn),最差的情況可能還會(huì)看到每次繪制的中間狀態(tài),視覺(jué)上給人一種很卡的感覺(jué)。雖然性能提升上去了,但是代碼的可維護(hù)性變差了,這種的就看你怎么平衡了,如果性能如果能接受的話,個(gè)人還是感覺(jué)代碼的可維護(hù)性重要些。實(shí)踐的時(shí)候還發(fā)現(xiàn)了一個(gè) MutationObserver 的一個(gè)問(wèn)題,就是我對(duì) DOM 節(jié)點(diǎn)的文本進(jìn)行修改的時(shí)候,MutationObserver 的回調(diào)居然沒(méi)有執(zhí)行讓我有些意外。
原文鏈接:https://juejin.cn/post/7113519924479262757
相關(guān)推薦
- 2022-06-24 使用ASP.NET?Web?API構(gòu)建Restful?API_實(shí)用技巧
- 2022-06-29 C語(yǔ)言超詳細(xì)講解getchar函數(shù)的使用_C 語(yǔ)言
- 2022-03-26 jquery對(duì)元素的基本操作實(shí)例分析_jquery
- 2022-08-20 python使用tkinter模塊實(shí)現(xiàn)文件選擇功能_python
- 2022-09-15 Python利用shutil實(shí)現(xiàn)拷貝文件功能_python
- 2021-12-19 C語(yǔ)言?八大排序算法的過(guò)程圖解及實(shí)現(xiàn)代碼_C 語(yǔ)言
- 2022-12-04 WxPython界面利用pubsub如何實(shí)現(xiàn)多線程控制_python
- 2022-04-10 用python實(shí)現(xiàn)文件備份_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支