91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在react中實現一個虛擬dom和diff算法

發布時間:2021-04-19 16:36:15 來源:億速云 閱讀:182 作者:Leah 欄目:開發技術

這篇文章將為大家詳細講解有關怎么在react中實現一個虛擬dom和diff算法,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

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

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']
        },
      }
    }

我們想要構造出這樣的對象可以自己封裝一個構造函數如下:

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出這個對象調用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發生了變化,我們的內存中又會產生新的虛擬DOM,如果我們直接用這個新的虛擬DOM結構的話,又會導致很多重復的渲染,因此 這個時候diff算法的作用就體現了出來,diff通過比較新舊兩個虛擬DOM樹,找出差異,并且記錄下來,然后把記錄的差異應用到真實的DOM樹上。

原理:

diff算法通過對新舊兩顆樹進行深度優先遍歷,每一個節點都加一個唯一的標識。

這個過程分為2步

  • 找出兩個樹的差異,并記錄在一個偽數組里。

  • 把這些不同應用到真實的DOM樹上

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

  • 對節點的刪除,移動,添加子節點

  • 更換節點標簽

  • 對于文本節點,修改節點文本

  • 修改節點props

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

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

    return patchs

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

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

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

    // 對子節點作diff算法,遍歷子節點,遞歸調用dfWork,做差異得到patchs

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

            break;
        case PROPS:
            // setProps
            break;
        case TEXT: // 對節點文本的修改
            // node.nodeValue
            break;

        default:
            break;
    }
}

關于怎么在react中實現一個虛擬dom和diff算法就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

辽宁省| 吕梁市| 呼伦贝尔市| 保定市| 新化县| 深圳市| 遵义市| 安阳市| 怀安县| 大埔区| 婺源县| 阳城县| 安宁市| 阜南县| 大厂| 蒙城县| 大关县| 襄城县| 清原| 庆安县| 沙坪坝区| 遵化市| 彭山县| 固阳县| 丰城市| 南充市| 绵阳市| 罗定市| 沁阳市| 如皋市| 青浦区| 河北区| 新竹市| 平果县| 阳谷县| 定州市| 桂平市| 法库县| 巴东县| 马边| 普格县|