這篇文章主要介紹了如何從React渲染流程分析Diff算法,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
React中最神奇的部分莫過(guò)于虛擬DOM,以及其高效的Diff算法。這讓我們可以無(wú)需擔(dān)心性能問(wèn)題而”毫無(wú)顧忌”的隨時(shí)“刷新”整個(gè)頁(yè)面,由虛擬DOM來(lái)確保只對(duì)界面上真正變化的部分進(jìn)行實(shí)際的DOM操作。React在這一部分已經(jīng)做到足夠透明,在實(shí)際開(kāi)發(fā)中我們基本無(wú)需關(guān)心虛擬DOM是如何運(yùn)作的。然而,理解其運(yùn)行機(jī)制不僅有助于更好的理解React組件的生命周期,而且對(duì)于進(jìn)一步優(yōu)化React程序也會(huì)有很大幫助。
1、什么是虛擬DOM
在React中,render執(zhí)行的結(jié)果得到的并不是真正的DOM節(jié)點(diǎn),結(jié)果僅僅是輕量級(jí)的JavaScript對(duì)象,我們稱(chēng)之為virtual DOM。
簡(jiǎn)單的說(shuō),其實(shí)所謂的virtual DOM就是JavaScript對(duì)象到Html DOM節(jié)點(diǎn)的映射;即使用JavaScript對(duì)象將Html結(jié)構(gòu)表示出來(lái),而這個(gè)對(duì)象就是virtual DOM。
eg:
Html:
<ul id='list'> <li class='item'>Item 1</li> <li class='item'>Item 2</li> </ul>
JavaScript對(duì)象表示(virtual DOM)
{ tagName: 'ul', props: { id: 'list' }, children: [ {tagName: 'li', props: {class: 'item'}, children: ["Item 1"]}, {tagName: 'li', props: {class: 'item'}, children: ["Item 2"]}, ] }
2、什么時(shí)候會(huì)生成到virtual DOM
React生命周期擁有裝載、更新、卸載的三個(gè)階段;附上一張React生命周期圖
前面提到:render執(zhí)行的結(jié)果得到的并不是真正的DOM節(jié)點(diǎn),結(jié)果僅僅是輕量級(jí)的JavaScript對(duì)象,即在render函數(shù)調(diào)用時(shí)將會(huì)創(chuàng)建出虛擬DOM;
class Tab extends React.Component { render() { React.createElement( 'p', { className: 'class'}, 'Hello React' ) } }
通過(guò)React.createElemen創(chuàng)建出虛擬DOM,而該函數(shù)只在Render函數(shù)中調(diào)用,所以在React裝載和更新的過(guò)程中才會(huì)有虛擬DOM的生成;至于掛載到真實(shí)DOM自然而然是ReactDom.render函數(shù)啦。
3、virtual DOM如何實(shí)現(xiàn)
實(shí)現(xiàn)其實(shí)很簡(jiǎn)單,主要是定義一個(gè)函數(shù)并把我們傳進(jìn)去的參數(shù)組成一個(gè)React元素對(duì)象,而type就是我們傳進(jìn)去的組件類(lèi)型,可以是一個(gè)類(lèi)、函數(shù)或字符串(如'div')
React大致源碼:
function createElement(type, config, children) { let propName; const props = {}; let key = null; let ref = null; let self = null; let source = null; if (config != null) { if (hasValidRef(config)) { // 如果有ref,將它取出來(lái) ref = config.ref; } if (hasValidKey(config)) { // 如果有key,將它取出來(lái) key = '' + config.key; } self = config.__self === undefined ? null : config.__self; source = config.__source === undefined ? null : config.__source; for (propName in config) { if ( hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName) ) { // 將除ref,key等這些特殊的屬性放到新的props對(duì)象里 props[propName] = config[propName]; } } } // 獲取子元素 const childrenLength = arguments.length - 2; if (childrenLength === 1) { props.children = children; } else if (childrenLength > 1) { const childArray = Array(childrenLength); for (let i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 2]; } props.children = childArray; } // 添加默認(rèn)props if (type && type.defaultProps) { const defaultProps = type.defaultProps; for (propName in defaultProps) { if (props[propName] === undefined) { props[propName] = defaultProps[propName]; } } } return ReactElement( type, key, ref, self, source, ReactCurrentOwner.current, props, ); } const ReactElement = function(type, key, ref, self, source, owner, props) { // 最終得到的React元素 const element = { // This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, // Built-in properties that belong on the element type: type, key: key, ref: ref, props: props, // Record the component responsible for creating this element. _owner: owner, }; return element; };
打印出組件:
4、為什么需要使用virtual DOM
DOM管理歷史階段:
JS 或者 jQuery 操作 DOM: 當(dāng)應(yīng)用程序越來(lái)越復(fù)雜,需要在JS里面維護(hù)的字段也越來(lái)越多,需要監(jiān)聽(tīng)事件和在事件回調(diào)用更新頁(yè)面的DOM操作也越來(lái)越多,應(yīng)用程序會(huì)變得非常難維護(hù)。
后來(lái)產(chǎn)出 MVC、MVP 的架構(gòu)模式,期望從代碼組織方式來(lái)降低維護(hù)難度。但是 MVC 架構(gòu)并沒(méi)辦法減少維護(hù)的狀態(tài),也沒(méi)有降低狀態(tài)更新時(shí)需要對(duì)頁(yè)面的更新操作,你需要操作的DOM還是需要操作,只是換了個(gè)地方。
既然狀態(tài)改變了要操作相應(yīng)的DOM元素,為什么不做一個(gè)東西讓視圖和狀態(tài)進(jìn)行綁定,狀態(tài)變更了視圖自動(dòng)變更。這就是后來(lái)人們想出了 MVVM 模式,只要在模版中聲明視圖組件是和什么狀態(tài)進(jìn)行綁定的,雙向綁定引擎就會(huì)在狀態(tài)更新的時(shí)候自動(dòng)更新視圖;
但MVVM雙向數(shù)據(jù)綁定并不是唯一的辦法,還有一個(gè)非常直觀的方法:一旦狀態(tài)發(fā)生了變化,就用模版引擎重新渲染整個(gè)視圖,然后用新的視圖更換掉舊的視圖。
React采用的就是第四種模式;但是我們都知道對(duì)于操作DOM成本太高,而相對(duì)操作JavaScript就快速多了,而Html DOM可以很簡(jiǎn)單的用JavaScript對(duì)象表示出來(lái)(Virtual DOM就這樣誕生了)
這樣的做法會(huì)導(dǎo)致很多的問(wèn)題,大的問(wèn)題就是這樣做會(huì)很慢,因?yàn)榧词挂粋€(gè)小小的狀態(tài)變更都要重新構(gòu)造整棵 DOM,性?xún)r(jià)比太低;而React Virtual DOM在狀態(tài)更新過(guò)程加了一些特別的操作來(lái)避免整棵 DOM 樹(shù)變更(它就是接下來(lái)的Diff算法)。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“如何從React渲染流程分析Diff算法”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
分享名稱(chēng):如何從React渲染流程分析Diff算法-創(chuàng)新互聯(lián)
標(biāo)題網(wǎng)址:http://chinadenli.net/article36/ghepg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁(yè)設(shè)計(jì)公司、自適應(yīng)網(wǎng)站、標(biāo)簽優(yōu)化、關(guān)鍵詞優(yōu)化、ChatGPT、虛擬主機(jī)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容