欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

react中的虛擬dom和diff算法詳解

 更新時間:2021年04月18日 10:37:19   作者:家里有只豬  
這篇文章主要介紹了react中的虛擬dom和diff算法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

虛擬DOM的作用

首先我們要知道虛擬dom的出現(xiàn)是為了解決什么問題的,他解決我們平時頻繁的直接操作DOM效率低下的問題。那么為什么我們直接操作DOM效率會低下呢?

比如我們創(chuàng)建一個div,我們可以在控制臺查看一下這個div上自帶或者繼承了很多屬性,尤其是我們使用js操作DOM的時候,我們的DOM本身就很復(fù)雜,js的操作也會占用很多時間,但是我們控制不了DOM元素本身,因此虛擬DOM解決的是js操作DOM這一層面其實解決的是減少了操作dom的次數(shù)

簡單實現(xiàn)虛擬DOM

虛擬DOM,見名知意,就是假的DOM,我們真實的DOM掛載在頁面上的,而我們的虛擬DOM則是在內(nèi)存中的。這個就需要我們把真實的DOM抽象成一個對象放在內(nèi)存中。這個對象就可以是如下類型:

var element = {
      tagName: 'div',
      props: {
        class: 'box'
      },
      children: {
        {
          tagName: 'p',
          props: {
            class: 'p1'
          },
          children: ['我是p1']
        }, 
         {
          tagName: 'p',
          props: {
            class: 'p2'
          },
          children: ['我是p2']
        }, 
        {
          tagName: 'p',
          props: {
            class: 'p3'
          },
          children: ['我是p3']
        },
      }
    }

我們想要構(gòu)造出這樣的對象可以自己封裝一個構(gòu)造函數(shù)如下:

function Element(tagName, props, children) {
    this.tagName = tagName
    this.props = props
    this.children = children
}

有了這個對象,我們需要把這個虛擬DOM渲染到真實DOM上,可以寫出如下方法:

Element.prototype.render = function () {
    const { tagName, props, children } = this
    var el = document.createElement(tagName)
    for (key in props) {
        el.setAttribute(key, props[key])
    }
    children.forEach((item) => {
        const childEl = (item instanceof Element) ?
              item.render() :
        document.createTextNode(item)
        el.appendChild(childEl)
    })
    return el
}

最后我們可以new出這個對象調(diào)用render()方法然后appendChild到body中就好了:

let virtualDom = new Element('div', { class: 'box' }, [
    new Element('p', { class: 'p1' }, ['我是p1']),
    new Element('p', { class: 'p2' }, ['我是p2']),
    new Element('p', { class: 'p3' }, ['我是p3']),
])

let a = virtualDom.render()
document.body.appendChild(a)

diff算法

首先我們先了解一下diff算法的作用

如果我們的虛擬dom發(fā)生了變化,我們的內(nèi)存中又會產(chǎn)生新的虛擬DOM,如果我們直接用這個新的虛擬DOM結(jié)構(gòu)的話,又會導(dǎo)致很多重復(fù)的渲染,因此 這個時候diff算法的作用就體現(xiàn)了出來,diff通過比較新舊兩個虛擬DOM樹,找出差異,并且記錄下來,然后把記錄的差異應(yīng)用到真實的DOM樹上。

原理:

diff算法通過對新舊兩顆樹進(jìn)行深度優(yōu)先遍歷,每一個節(jié)點(diǎn)都加一個唯一的標(biāo)識。

這個過程分為2步

  • 找出兩個樹的差異,并記錄在一個偽數(shù)組里。
  • 把這些不同應(yīng)用到真實的DOM樹上

對于dom的操作基本可化為4種類型

  • 對節(jié)點(diǎn)的刪除,移動,添加子節(jié)點(diǎn)
  • 更換節(jié)點(diǎn)標(biāo)簽
  • 對于文本節(jié)點(diǎn),修改節(jié)點(diǎn)文本
  • 修改節(jié)點(diǎn)props

下面會用偽代碼的形式大致過一下這個流程

// diff 函數(shù),對比兩棵樹
function diff(oldTree, newTree) {
    var patchs = {};  // 偽數(shù)組,記錄差異
    //  對4種節(jié)點(diǎn)做錯判斷
    dfWork(oldTree, newTree, patchs, index)

    return patchs

}
function dfWork(oldTree, newTree, patchs, index) {
    let currentPatch = []

    if (1) { // 對節(jié)點(diǎn)的刪除
        currentPatch.push()
    } else if (3) { // 對節(jié)點(diǎn)的文本的更換
        currentPatch.push()

    } else { // 修改節(jié)點(diǎn)的props 對children的檢查
        // 對props作diff算法,把變化記錄到patchs中。
        currentPatch.push({ type: patch.PROPS, props: propsPatches })
        // 然后需要對子節(jié)點(diǎn)作diff算法
        diffChildren(oldNode.children, newNode.children, index, patches, currentPatch)
    }
}
function diffChildren(oldChildren, newChildren, index, patches, currentPatch) {

    // 對子節(jié)點(diǎn)作diff算法,遍歷子節(jié)點(diǎn),遞歸調(diào)用dfWork,做差異得到patchs

}
// 把變化應(yīng)用在真實的DOM樹上
function patch(node, patchs) {
    // node為老的DOM樹,patchs變化。
    // 我們會遍歷這個patchs,并且把node和patch對應(yīng)上,
}
function applyPatch(node, patchs) {
    // 應(yīng)為每個節(jié)點(diǎn)可能有多個變化,所以也需要遍歷
    switch (patchs.type) {
        case REPLACE: // 節(jié)點(diǎn)替換
            // node.render() 
            break;
        case REORDER:  // 節(jié)點(diǎn)的移動刪除新增子節(jié)點(diǎn)。

            break;
        case PROPS:
            // setProps
            break;
        case TEXT: // 對節(jié)點(diǎn)文本的修改
            // node.nodeValue
            break;

        default:
            break;
    }
}

參考文檔:深度剖析:如何實現(xiàn)一個 Virtual DOM 算法 作者:livoras,內(nèi)置源碼。

到此這篇關(guān)于react中的虛擬dom和diff算法的文章就介紹到這了,更多相關(guān)react虛擬dom和diff算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React State狀態(tài)與生命周期的實現(xiàn)方法

    React State狀態(tài)與生命周期的實現(xiàn)方法

    這篇文章主要介紹了React State狀態(tài)與生命周期的實現(xiàn)方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • React初始化渲染過程示例詳解

    React初始化渲染過程示例詳解

    這篇文章主要為大家介紹了React初始化渲染過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • React如何利用Antd的Form組件實現(xiàn)表單功能詳解

    React如何利用Antd的Form組件實現(xiàn)表單功能詳解

    這篇文章主要給大家介紹了關(guān)于React如何利用Antd的Form組件實現(xiàn)表單功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • React函數(shù)組件和類組件的區(qū)別及說明

    React函數(shù)組件和類組件的區(qū)別及說明

    這篇文章主要介紹了React函數(shù)組件和類組件的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 淺談React + Webpack 構(gòu)建打包優(yōu)化

    淺談React + Webpack 構(gòu)建打包優(yōu)化

    本篇文章主要介紹了淺談React + Webpack 構(gòu)建打包優(yōu)化,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 可定制React自動完成搜索組件Turnstone實現(xiàn)示例

    可定制React自動完成搜索組件Turnstone實現(xiàn)示例

    這篇文章主要為大家介紹了可定制React自動完成搜索組件Turnstone實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • react中用less的問題

    react中用less的問題

    本文主要介紹了react中用less的問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • React全家桶環(huán)境搭建過程詳解

    React全家桶環(huán)境搭建過程詳解

    本篇文章主要介紹了React全家桶環(huán)境搭建過程詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • react中使用js實現(xiàn)頁面滾動監(jiān)聽(推薦)

    react中使用js實現(xiàn)頁面滾動監(jiān)聽(推薦)

    這篇文章主要介紹了react中使用js實現(xiàn)頁面滾動監(jiān)聽,本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • React Context詳解使用過程

    React Context詳解使用過程

    在Reactor中提供了Context來替代ThreadLocal,可以實現(xiàn)一個跨線程的共享變量的透明方式。本文主要為大家介紹了Context的用法的用法,感興趣的可以了解一下
    2023-03-03

最新評論