什么是虛擬DOM
react數(shù)據(jù)變化頁面同步渲染的邏輯屁使,這里分析三種邏輯在岂。
- 先有數(shù)據(jù) (state)
- 模版(render中的jsx)
- 數(shù)據(jù) + 模版 = 生成真實(shí)Dom,來顯示
- state 發(fā)生改變
- 數(shù)據(jù) + 模版 = 生成真實(shí)Dom蛮寂,替換原有的DOM
- 缺陷: 第一次生成真實(shí)dom蔽午,第二次又生成一個。最后替換酬蹋。非常耗性能及老。
- 原因: 生成一個完整的dom,和替換一個完整的dom范抓,非常耗性能骄恶。并不是每次數(shù)據(jù)變化dom的所有內(nèi)容都要變。
- 先有數(shù)據(jù) (state)
- 模版(render中的jsx)
- 數(shù)據(jù) + 模版 = 生成真實(shí)Dom匕垫,來顯示
- state 發(fā)生改變
- 數(shù)據(jù) + 模版 = 生成真實(shí)Dom僧鲁,并不直接替換原始的DOM
- 新舊DOM做對比,找差異。注意新的DOM其實(shí)是DoucumentFragment: 文檔碎片并沒有真實(shí)的掛載到頁面上寞秃。
- 找出input框發(fā)生變換
- 只用新DOM中的input元素斟叼,替換掉老的DOM中的input元素。
- 缺陷: 節(jié)約了完整dom替換的性能春寿,但是消耗了對比的性能朗涩。效果不明顯。
- 先有數(shù)據(jù) (state)
- 模版(render中的jsx)
- 數(shù)據(jù) + 模版 = 生成虛擬DOM(生成虛擬DOM是一個js對象绑改,用它來描述真是DOM)(損耗性能非常行淮病)
- ['div', {id: 'abc'}, ['span', {}, 'hello,world']]
- 用虛擬DOM的結(jié)構(gòu)生成真實(shí)Dom,來顯示
- <div id='abc'><span>hello,world</span></div>
- state 發(fā)生改變
- 數(shù)據(jù) + 模版 = 生成新的虛擬DOM(極大提升了性能)
- ['div', {id: 'abc'}, ['span', {}, 'bye绢淀,bye']]
- 比較原始虛擬DOM和新的虛擬DOM的區(qū)別萤悴,找到區(qū)別是span中的內(nèi)容
- 直接操作DOM改變span中的DOM
- 優(yōu)勢:
- 減少了對真實(shí)DOM的創(chuàng)建,性能提高很大
- js對象的比對非常不消耗性能的皆的。
- 原因:
- js去生產(chǎn)一個虛擬DOM其實(shí)就是一個js對象覆履,而使用js去生成一個js對象是不怎么消耗性能的。
- 對比上面兩種方法费薄,不僅減少了真實(shí)DOM的生產(chǎn)硝全,同時也沒有了真實(shí)DOM的對比,虛擬DOM對比也是非常節(jié)約新能的楞抡。
深入了解虛擬DOM
- jsx --> createElement --> js對象(虛擬dom) --> 真實(shí)DOM
- jsx實(shí)際上就是一個模版伟众。
- react將數(shù)據(jù)和jsx模版結(jié)合通過createElement方法生成js對象,也就是虛擬dom召廷。
- React.createElement('div', {}, 'item') // {}為div屬性
- return <div>item</div>
- 以上兩行代碼效果是一樣的凳厢,都是創(chuàng)建了虛擬dom
- 最后react再將虛擬dom生成真實(shí)dom
- 虛擬dom帶來的好處
- 性能提升:真實(shí)dom的比對變成了js對象比對
- 它使得跨端應(yīng)用得以實(shí)現(xiàn),React Native
- 虛擬dom是js對象竞慢,他可以同時在原生應(yīng)用里面和瀏覽器中都能識別先紫。真實(shí)dom是不能在原生應(yīng)用識別的。
- 在原生應(yīng)用中筹煮,我們可以使用虛擬dom轉(zhuǎn)化成原生組件遮精。這讓我們能夠開發(fā)原生應(yīng)用。
虛擬dom中的diff算法
- 算法運(yùn)用在比較原始虛擬DOM和新的虛擬DOM的比對中
- 兩個虛擬dom的比對就叫diffrence算法(react底層會用到)败潦,大大提高了比對效率
- 什么時候會發(fā)生比對本冲。
- 當(dāng)你調(diào)用setState()的時候,就會發(fā)生比對劫扒。
- setState()是一個異步方法檬洞。
- 為什么是一個異步呢。
- 假設(shè)你調(diào)用了3次setState()方法沟饥。如果不是異步函數(shù)添怔,是不是要進(jìn)行3次虛擬dom比對呢环戈?所以react將它設(shè)計(jì)成異步函數(shù)。
- diff算法
- 同級比較
- 從第一層虛擬DOM開始比較澎灸,如果差異院塞,他就不再對比,他會將第一層以及該層對應(yīng)的子節(jié)點(diǎn)都替換掉性昭。
- 這樣比較確實(shí)會造成渲染的浪費(fèi)拦止,因?yàn)榭赡茏庸?jié)點(diǎn)會有相同的地方。
- 優(yōu)勢在于比對算法簡單糜颠,他可以大大減少比對的時間汹族。
- 為什么在我們給dom的key值賦值時候,不要使用index其兴?
- 首先我們要知道顶瞒,為什么我們在循環(huán)遍歷DOM的時候要給DOM設(shè)置一個key值。
- 每個DOM設(shè)置一個key元旬,相當(dāng)于給每個dom起了一個名字榴徐。在做虛擬dom對比的時候,我們只需要按名字對比匀归,不需要通過dom內(nèi)容現(xiàn)找到對應(yīng)的dom再進(jìn)行對比坑资,這樣就節(jié)省了新能。
- 為什么不能用index呢穆端?因?yàn)閕ndex不具備穩(wěn)定性袱贮,當(dāng)你刪除某一個dom后,可能你整個dom樹的key值都會發(fā)生變化体啰。
- 我們可以使用dom的內(nèi)容去做key攒巍,因?yàn)閮?nèi)容改變本身dom就需要重新渲染。就拿todolist來說key可以綁定value值荒勇。
- 同級比較