最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解react應用中的DOM DIFF算法

 更新時間:2021年04月09日 08:34:01   作者:time_w  
這篇文章主要介紹了react應用中的DOM DIFF算法,幫助大家更好的理解和學習使用react,感興趣的朋友可以了解下

前言

對我們搞前端的來說,目前最流行的兩大前端框架毫無疑問當屬React和Vue,對于這兩大框架,想必大家也是再熟悉不過了。然而,這兩大框架無一例外的全部放棄使用傳統(tǒng)的DOM技術(shù),卻采用了以JS為基礎(chǔ)的Virtual DOM技術(shù),也可稱作虛擬DOM。所以,到底什么是Virtual DOM?兩大熱門框架全部使用Virtual DOM的原因又是什么?接下來讓我這個搞前端的人來好好地為您講解一下DOM DIFF算法的牛之處。

什么是Virtual DOM?

如字面意思所說,Virtual DOM即 虛擬DOM,它的特點就是利用Javascript來模擬DOM結(jié)構(gòu),并且將DOM的變化對比放在JS層中進行比較。具體操作如下:

// 普通的HTML DOM結(jié)構(gòu)
<ul class="list">
   <li class="item">wjy</li>
   <li class="item">易烊千璽</li>
</ul>

// 映射出的虛擬DOM
{
   tag:'ul',
   props:{
       class:'list'
   },
   children: [
       {
           tag:'li',
           props:{
               class:'item'
           },
           children: ['易烊千璽']
       }
   ]
}

有朋友或許會有點迷惑,普通的HTML DOM結(jié)構(gòu)不好嗎?通俗易懂,代碼也更加簡潔,為什么還需要采用嵌套遞歸的虛擬DOM形式呢?其實這和普通DOM在重新渲染的過程中非常消耗性能有關(guān),DOM操作看似簡便,但其實效率相當?shù)?這是因為如果是在需要頻繁修改的真實DOM中,看起來更加復雜的運用JS結(jié)構(gòu)的Virtual DOM效率會更高.

使用Virtual DOM的原因

DOM 渲染頁面的操作流程

  • 當瀏覽器通過域名從服務器拿到對應的HTML文件后,瀏覽器首先會進行構(gòu)建DOM樹和CSSOM樹,關(guān)于樹的概念,學過數(shù)據(jù)結(jié)構(gòu)與算法的同學或許對樹的節(jié)點概念印象深刻。
  • 在HTML DOM中,所有的事物都是節(jié)點,而DOM是被視為節(jié)點樹的HTML,并且,各個節(jié)點之間有著相應的層級關(guān)系。DOM節(jié)點樹和HTML中的標簽一一對應,構(gòu)成了DOM樹
  • HTML文件

  • HTML DOM樹

同樣的。在CSS文檔中,所有的元素也皆是節(jié)點,與HTML中的標簽一一對應,構(gòu)成了CSSOM樹 如下圖所示

警告! 如果在構(gòu)建DOM樹的過程中,有遇到JS相關(guān)的內(nèi)容時,DOM樹的構(gòu)建會立即停止,這是由于,JS可以對DOM節(jié)點進行操作,瀏覽器為了防止JS會對以完成的DOM造成影響,會阻止DOM樹的構(gòu)建,以節(jié)約資源。

在DOM樹和CSSOM樹不斷構(gòu)建的過程中,渲染樹也在逐漸形成,瀏覽器會根據(jù)所構(gòu)建的渲染樹進行網(wǎng)頁布局和繪制流程,不斷地進行網(wǎng)頁的搭建。具體操作流程圖如下:

一般而言,對于頁面渲染的常規(guī)操作,我們通常是操作DOM,修改并重置innerHTML完成頁面的渲染,每進行一次DOM的更新操作,都會重新進行一次渲染流程,這個過程包含著頁面的重繪和重排。

Virtual DOM的優(yōu)勢

但是如果對于大型頁面項目,或者具有多標簽,多屬性的網(wǎng)頁而言,常規(guī)的DOM操作實在是太耗時了,每次的簡單修改都需要牽動大量的DOM節(jié)點的重繪與重排,極大地降低了頁面渲染效率.于是,當前端開發(fā)人員面對DOM瓶頸一籌莫展的時候,Virtual DOM顯示出了作為輕量級的JavaScript對象的極大優(yōu)越性,順利得到了了前端開發(fā)者的青睞。

在頁面進行重新渲染的時候,Virtual DOM進行dom diff計算對比兩次并發(fā)現(xiàn)其中的差異,只需要修改DOM樹中不同的部分即可.也可以理解為Virtual DOM做了一個中間件,先利用JS修改Virtual DOM,在對比出差異后,將所有的更改加入頁面的真實DOM.所以說,Virtual DOM的最大優(yōu)勢就在于完全不用像原生DOM,在對比之后還要進行DOM的重建與創(chuàng)造,因為這對于大型項目的運行來說非常消耗性能,開銷極大.由此可見,不論在什么體量的網(wǎng)頁中,放棄傳統(tǒng)DOM采用Virtual DOM無疑是非常高效且絕佳的選擇.

如何將DOM用virtual DOM 來表示

首先,在vscode中新建一個dom diff 項目,項目初始化,裝好相應組件

由于是DOM樹,所以在將HTML轉(zhuǎn)換成DOM樹時,要運用遞歸的形式,首先創(chuàng)建結(jié)點,其次設置屬性,然后設置子節(jié)點

<ul class="list">
    <li class="item">wjy</li>
    <li class="item">易烊千璽</li>
</ul> 

// DOM 樹的表達轉(zhuǎn)換形式 
let virtualDOM = createElement('ul', {
  class:'list',
}, [
  createElement('li',{
    class:'item'
  },['wjy']),
  createElement('li',{
    class:'item'
  },['易烊千璽']),
])

然后,在新建一個element.js文件進行向外輸出,完成頁面渲染

// 通過構(gòu)造函數(shù)Element構(gòu)造虛擬DOM節(jié)點
class Element {
    constructor(type,props,children){
        this.type = type;
        this.props = props;
        this.children =children;
    }
}
// 
const createElement = (type,props,children) => { 
  return new Element(type,props,children);
}

// 進行頁面渲染 將Virtual Dom轉(zhuǎn)化為真實DOM
const render = (domObj) => {  
    let el = document.createElement(domObj.type);
    for(let key in domObj.props){
        setAttr(el,key,domObj.props[key]);
    }
    domObj.children.forEach(child => {
        child = (child instanceof Element)
        ? render(child)
        : document.createTextNode(child);
        el.appendChild(child);

    })
    return el;
}

function setAttr(node,key,value){
    switch(key){
        case 'value':
            if(node.tagName.toLowerCase() === 'input' || 
            node.tagName.toLowerCase() ==='textarea'
            ){
                node.value = value;
            }else{
                node.setAttribute(key,value)
            }
            break;
            case 'style':
            //   node.setAttribute('style',value)
            node.style.cssText = value;
            break;
            default:
                node.setAttribute(key,value)
            break;
    }
}

// 將真實DOM 掛載到制定根節(jié)點
const renderDOM = (el,target) => {
    target.appendChild(el);
}

// 向外輸出
export {
    createElement,
    render,
    renderDOM
}

在控制臺上得到真實DOM

頁面渲染成功!??

DOM DIFF算法

在用戶進行操作更改交互頁面操作后,虛擬DOM樹上的節(jié)點會發(fā)生變化,然而此時真實節(jié)點卻沒有改變,為了使得更改與真實頁面同步,我們會使用DOM DIFF算法找出這兩顆樹的差異,然后產(chǎn)生差異補丁對象,再將差異補丁對象應用到真實的DOM節(jié)點上去,于是完成了頁面的渲染和更新。

傳統(tǒng)的Diff算法時間復雜度達到了O(n^3),若要滿足每次都可以整體刷新頁面的目的,這種指數(shù)型的增長的性能開銷是無法滿足性能要求的,于是,F(xiàn)acebook的工程師對此進行了優(yōu)化,通過制定diff策略將Diff算法的復雜度降低到了O(n)

Diff 策略

  • DOM節(jié)點跨層級的操作特別少,所以可以忽略不計
  • 擁有相同類的兩個組件將會產(chǎn)生相似的樹形結(jié)構(gòu),擁有不同類的兩個組件將會產(chǎn)生不同的樹形結(jié)構(gòu)
  • 同一層級的一組子節(jié)點,他們可以通過uuid進行區(qū)分

Diff 粒度

由于DIFF的粒度不同,DIFF算法按照下面的順序依次執(zhí)行

  • Tree DIFF
  • Component DIFF
  • Element DIFF

打補丁

我們根據(jù)diff策略以及react diff中的比對算法將兩個虛擬DOM通過深度優(yōu)先遍歷進行比較,如果有差異,就把所遍歷到節(jié)點的索引值所對應的操作存儲起來,也稱為補丁對象(patches)

然后對真實的DOM再次經(jīng)過深度優(yōu)先遍歷,補丁對象中的索引就會和DOM相對應,我們就完成了DOM的更新操作。

結(jié)語
在互聯(lián)網(wǎng)環(huán)境下,隨時刷新交互頁面是我們上網(wǎng)的常規(guī)操作,然而這一簡單的操作卻是多次算法優(yōu)化的結(jié)果。DOM DIFF的底層原理挺復雜,如果有感興趣的朋友,可以自行搜索相關(guān)文獻,因為本文只是淺析,所以太多方面就不贅述了,如果本文有知識錯漏的地方,也歡迎指正!虛心接收一切合理批評!??

如果這篇文章有幫助到你對dom diff算法的理解,也希望您能為我點一個贊??,答主是剛?cè)腴T的前端小白,每一個贊都是我前進的動力,我會持續(xù)更新掘金的博客的??

以上就是詳解react應用中的DOM DIFF算法的詳細內(nèi)容,更多關(guān)于react應用的DOM DIFF算法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 深入理解React虛擬Dom

    深入理解React虛擬Dom

    虛擬DOM是一種輕量級的JavaScript對象,用于描述真實網(wǎng)頁的DOM結(jié)構(gòu)和屬性,存在于內(nèi)存中,本文就來詳細的介紹React虛擬Dom的實現(xiàn),感興趣的可以了解一下
    2026-01-01
  • 基于React路由跳轉(zhuǎn)的幾種方式

    基于React路由跳轉(zhuǎn)的幾種方式

    這篇文章主要介紹了React路由跳轉(zhuǎn)的幾種方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • react分頁顯示數(shù)據(jù)的方法

    react分頁顯示數(shù)據(jù)的方法

    分頁在很多地方都可以用到,本文主要實現(xiàn)了react分頁顯示,主要使用三個組件,父組件listBox、列表組件List、按鈕組件PageButton,感興趣的可以了解一下
    2021-08-08
  • 原生實現(xiàn)一個react-redux的代碼示例

    原生實現(xiàn)一個react-redux的代碼示例

    這篇文章主要介紹了原生實現(xiàn)一個react-redux的代碼示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • 關(guān)于useEffect執(zhí)行兩次的問題及解決

    關(guān)于useEffect執(zhí)行兩次的問題及解決

    這篇文章主要介紹了關(guān)于useEffect執(zhí)行兩次的問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • react中useRef的使用和渲染機制

    react中useRef的使用和渲染機制

    本文主要介紹了react中useRef的使用和渲染機制,react useRef
    2025-11-11
  • 淺談react性能優(yōu)化的方法

    淺談react性能優(yōu)化的方法

    這篇文章主要介紹了淺談react性能優(yōu)化的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • react框架next.js學習之API?路由篇詳解

    react框架next.js學習之API?路由篇詳解

    這篇文章主要為大家介紹了react框架next.js學習之API?路由篇詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 深入React?18源碼useMemo?useCallback?memo用法及區(qū)別分析

    深入React?18源碼useMemo?useCallback?memo用法及區(qū)別分析

    這篇文章主要為大家介紹了React?18源碼深入分析useMemo?useCallback?memo用法及區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • React手稿之 React-Saga的詳解

    React手稿之 React-Saga的詳解

    這篇文章主要介紹了React手稿之 React-Saga的詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11

最新評論

霍林郭勒市| 临西县| 荃湾区| 吴江市| 永和县| 北京市| 伊吾县| 邓州市| 桦甸市| 四子王旗| 开原市| 嘉兴市| 金山区| 五家渠市| 铜梁县| 缙云县| 西和县| 德昌县| 阿城市| 台湾省| 庆云县| 永靖县| 霍山县| 龙里县| 巴林右旗| 社会| 获嘉县| 敖汉旗| 沂水县| 凤翔县| 海林市| 宁明县| 湟中县| 海伦市| 通许县| 攀枝花市| 陈巴尔虎旗| 九寨沟县| 台南市| 鸡泽县| 友谊县|