一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務(wù)器之家 - 編程語(yǔ)言 - JavaScript - React - react中的虛擬dom和diff算法詳解

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

2022-03-05 20:49家里有只豬 React

這篇文章主要介紹了react中的虛擬dom和diff算法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

虛擬DOM的作用

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

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

簡(jiǎn)單實(shí)現(xiàn)虛擬DOM

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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)造出這樣的對(duì)象可以自己封裝一個(gè)構(gòu)造函數(shù)如下:

?
1
2
3
4
5
function Element(tagName, props, children) {
    this.tagName = tagName
    this.props = props
    this.children = children
}

有了這個(gè)對(duì)象,我們需要把這個(gè)虛擬DOM渲染到真實(shí)DOM上,可以寫(xiě)出如下方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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出這個(gè)對(duì)象調(diào)用render()方法然后appendChild到body中就好了:

?
1
2
3
4
5
6
7
8
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)存中又會(huì)產(chǎn)生新的虛擬DOM,如果我們直接用這個(gè)新的虛擬DOM結(jié)構(gòu)的話,又會(huì)導(dǎo)致很多重復(fù)的渲染,因此 這個(gè)時(shí)候diff算法的作用就體現(xiàn)了出來(lái),diff通過(guò)比較新舊兩個(gè)虛擬DOM樹(shù),找出差異,并且記錄下來(lái),然后把記錄的差異應(yīng)用到真實(shí)的DOM樹(shù)上。

原理:

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

這個(gè)過(guò)程分為2步

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

對(duì)于dom的操作基本可化為4種類(lèi)型

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

下面會(huì)用偽代碼的形式大致過(guò)一下這個(gè)流程

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// diff 函數(shù),對(duì)比兩棵樹(shù)
function diff(oldTree, newTree) {
    var patchs = {};  // 偽數(shù)組,記錄差異
    //  對(duì)4種節(jié)點(diǎn)做錯(cuò)判斷
    dfWork(oldTree, newTree, patchs, index)
 
    return patchs
 
}
function dfWork(oldTree, newTree, patchs, index) {
    let currentPatch = []
 
    if (1) { // 對(duì)節(jié)點(diǎn)的刪除
        currentPatch.push()
    } else if (3) { // 對(duì)節(jié)點(diǎn)的文本的更換
        currentPatch.push()
 
    } else { // 修改節(jié)點(diǎn)的props 對(duì)children的檢查
        // 對(duì)props作diff算法,把變化記錄到patchs中。
        currentPatch.push({ type: patch.PROPS, props: propsPatches })
        // 然后需要對(duì)子節(jié)點(diǎn)作diff算法
        diffChildren(oldNode.children, newNode.children, index, patches, currentPatch)
    }
}
function diffChildren(oldChildren, newChildren, index, patches, currentPatch) {
 
    // 對(duì)子節(jié)點(diǎn)作diff算法,遍歷子節(jié)點(diǎn),遞歸調(diào)用dfWork,做差異得到patchs
 
}
// 把變化應(yīng)用在真實(shí)的DOM樹(shù)上
function patch(node, patchs) {
    // node為老的DOM樹(shù),patchs變化。
    // 我們會(huì)遍歷這個(gè)patchs,并且把node和patch對(duì)應(yīng)上,
}
function applyPatch(node, patchs) {
    // 應(yīng)為每個(gè)節(jié)點(diǎn)可能有多個(gè)變化,所以也需要遍歷
    switch (patchs.type) {
        case REPLACE: // 節(jié)點(diǎn)替換
            // node.render()
            break;
        case REORDER:  // 節(jié)點(diǎn)的移動(dòng)刪除新增子節(jié)點(diǎn)。
 
            break;
        case PROPS:
            // setProps
            break;
        case TEXT: // 對(duì)節(jié)點(diǎn)文本的修改
            // node.nodeValue
            break;
 
        default:
            break;
    }
}

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

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

原文鏈接:https://blog.csdn.net/qq_44983621/article/details/115733067

延伸 · 閱讀

精彩推薦
  • Reactreact中常見(jiàn)hook的使用方式

    react中常見(jiàn)hook的使用方式

    這篇文章主要介紹了react中常見(jiàn)hook的使用方式與區(qū)別,幫助大家更好的理解和學(xué)習(xí)使用react,感興趣的朋友可以了解下...

    一顆冰淇淋8902022-02-25
  • React詳解React中共享組件邏輯的三種方式

    詳解React中共享組件邏輯的三種方式

    這篇文章主要介紹了詳解React中共享組件邏輯的三種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋...

    Null20203692022-01-12
  • ReactReact中useRef的具體使用

    React中useRef的具體使用

    這篇文章主要介紹了React中useRef的具體使用,它可以用來(lái)獲取組件實(shí)例對(duì)象或者是DOM對(duì)象,除此之外還有哪些用法,就一起來(lái)了解一下...

    Meskjei6342022-02-28
  • React詳解對(duì)于React結(jié)合Antd的Form組件實(shí)現(xiàn)登錄功能

    詳解對(duì)于React結(jié)合Antd的Form組件實(shí)現(xiàn)登錄功能

    這篇文章主要介紹了詳解對(duì)于React結(jié)合Antd的Form組件實(shí)現(xiàn)登錄功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需...

    浮生離夢(mèng)6622022-02-23
  • ReactReact+Antd 實(shí)現(xiàn)可增刪改表格的示例

    React+Antd 實(shí)現(xiàn)可增刪改表格的示例

    這篇文章主要介紹了React+Antd實(shí)現(xiàn)可增刪改表格的示例,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下...

    用戶(hù)3202285797825912022-02-24
  • React從框架作者角度聊:React調(diào)度算法的迭代過(guò)程

    從框架作者角度聊:React調(diào)度算法的迭代過(guò)程

    React內(nèi)部最難理解的地方就是「調(diào)度算法」,不僅抽象、復(fù)雜,還重構(gòu)了一次。可以說(shuō),只有React團(tuán)隊(duì)自己才能完全理解這套算法。既然這樣,那本文嘗試從...

    魔術(shù)師卡頌8172022-01-10
  • React淺談React Router關(guān)于history的那些事

    淺談React Router關(guān)于history的那些事

    這篇文章主要介紹了淺談React Router關(guān)于history的那些事,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們...

    這是上帝的杰作12032022-02-23
  • ReactReact三大屬性之props的使用詳解

    React三大屬性之props的使用詳解

    這篇文章主要介紹了React三大屬性之props的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下...

    xiaoznz10002022-03-02
主站蜘蛛池模板: 日本加勒比在线精品视频 | 亚洲美女aⅴ久久久91 | 国产一级黄色网 | 第四色男人天堂 | 乳女教师欲乱动漫无修版动画3d | 视频一区二区三区欧美日韩 | 国语刺激对白勾搭视频在线观看 | 嫩草蜜桃 | 国产未成女年一区二区 | 男同桌脱我奶罩吸我奶作文 | 亚洲无总热门 | 国产成人精品高清免费 | 亚洲精品www久久久久久久软件 | 98免费视频 | 99久久香蕉国产线看观香 | 久久青青草原综合伊人 | 女教师波多野结衣高清在线 | 大肥臀风间由美 中文字幕 大东北chinesexxxx露脸 | 国产区最新 | 国产精品亚洲片在线va | 91aaa免费免费国产在线观看 | 扒开双腿疯狂进出爽爽动态图 | 激情视频图片小说qvdo | 四虎4hu永久免费国产精品 | 性欧美13处丶14处 | 青青青国产精品国产精品美女 | 欧美国产日韩综合 | 亚洲国产成人超福利久久精品 | 久久机热视频 这里只有精品首页 | 耽美肉文高h | 91亚洲精品国产自在现线 | 天天视频官网天天视频在线 | 四缺一的小说 | 厨房play黄瓜进去小说h | 日韩毛片在线影视 | 四虎黄色影视库 | 国产精品夜色视频一级区 | 亚洲欧美一区二区三区在饯 | 午夜久久久久久网站 | 国产成人免费观看在线视频 | x8x8在线永久免费观看 |