国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

深度剖析:如何實(shí)現(xiàn)一個(gè) Virtual DOM 算法

vvpvvp / 995人閱讀

摘要:本文所實(shí)現(xiàn)的完整代碼存放在。這就是所謂的算法。兩個(gè)樹的完全的算法是一個(gè)時(shí)間復(fù)雜度為的問題。如果有差異的話就記錄到一個(gè)對(duì)象里面。如和的不同,會(huì)被所替代。這牽涉到兩個(gè)列表的對(duì)比算法,需要另外起一個(gè)小節(jié)來討論。

作者:戴嘉華

轉(zhuǎn)載請(qǐng)注明出處并保留原文鏈接( https://github.com/livoras/blog/issues/13 )和作者信息。

目錄:

1 前言

2 對(duì)前端應(yīng)用狀態(tài)管理思考

3 Virtual DOM 算法

4 算法實(shí)現(xiàn)

4.1 步驟一:用JS對(duì)象模擬DOM樹

4.2 步驟二:比較兩棵虛擬DOM樹的差異

4.3 步驟三:把差異應(yīng)用到真正的DOM樹上

5 結(jié)語(yǔ)

6 References

1 前言

本文會(huì)在教你怎么用 300~400 行代碼實(shí)現(xiàn)一個(gè)基本的 Virtual DOM 算法,并且嘗試盡量把 Virtual DOM 的算法思路闡述清楚。希望在閱讀本文后,能讓你深入理解 Virtual DOM 算法,給你現(xiàn)有前端的編程提供一些新的思考。

本文所實(shí)現(xiàn)的完整代碼存放在 Github。

2 對(duì)前端應(yīng)用狀態(tài)管理的思考

假如現(xiàn)在你需要寫一個(gè)像下面一樣的表格的應(yīng)用程序,這個(gè)表格可以根據(jù)不同的字段進(jìn)行升序或者降序的展示。

這個(gè)應(yīng)用程序看起來很簡(jiǎn)單,你可以想出好幾種不同的方式來寫。最容易想到的可能是,在你的 JavaScript 代碼里面存儲(chǔ)這樣的數(shù)據(jù):

var sortKey = "new" // 排序的字段,新增(new)、取消(cancel)、凈關(guān)注(gain)、累積(cumulate)人數(shù)
var sortType = 1 // 升序還是逆序
var data = [{...}, {...}, {..}, ..] // 表格數(shù)據(jù)

用三個(gè)字段分別存儲(chǔ)當(dāng)前排序的字段、排序方向、還有表格數(shù)據(jù);然后給表格頭部加點(diǎn)擊事件:當(dāng)用戶點(diǎn)擊特定的字段的時(shí)候,根據(jù)上面幾個(gè)字段存儲(chǔ)的內(nèi)容來對(duì)內(nèi)容進(jìn)行排序,然后用 JS 或者 jQuery 操作 DOM,更新頁(yè)面的排序狀態(tài)(表頭的那幾個(gè)箭頭表示當(dāng)前排序狀態(tài),也需要更新)和表格內(nèi)容。

這樣做會(huì)導(dǎo)致的后果就是,隨著應(yīng)用程序越來越復(fù)雜,需要在JS里面維護(hù)的字段也越來越多,需要監(jiān)聽事件和在事件回調(diào)用更新頁(yè)面的DOM操作也越來越多,應(yīng)用程序會(huì)變得非常難維護(hù)。后來人們使用了 MVC、MVP 的架構(gòu)模式,希望能從代碼組織方式來降低維護(hù)這種復(fù)雜應(yīng)用程序的難度。但是 MVC 架構(gòu)沒辦法減少你所維護(hù)的狀態(tài),也沒有降低狀態(tài)更新你需要對(duì)頁(yè)面的更新操作(前端來說就是DOM操作),你需要操作的DOM還是需要操作,只是換了個(gè)地方。

既然狀態(tài)改變了要操作相應(yīng)的DOM元素,為什么不做一個(gè)東西可以讓視圖和狀態(tài)進(jìn)行綁定,狀態(tài)變更了視圖自動(dòng)變更,就不用手動(dòng)更新頁(yè)面了。這就是后來人們想出了 MVVM 模式,只要在模版中聲明視圖組件是和什么狀態(tài)進(jìn)行綁定的,雙向綁定引擎就會(huì)在狀態(tài)更新的時(shí)候自動(dòng)更新視圖(關(guān)于MV*模式的內(nèi)容,可以看這篇介紹)。

MVVM 可以很好的降低我們維護(hù)狀態(tài) -> 視圖的復(fù)雜程度(大大減少代碼中的視圖更新邏輯)。但是這不是唯一的辦法,還有一個(gè)非常直觀的方法,可以大大降低視圖更新的操作:一旦狀態(tài)發(fā)生了變化,就用模版引擎重新渲染整個(gè)視圖,然后用新的視圖更換掉舊的視圖。就像上面的表格,當(dāng)用戶點(diǎn)擊的時(shí)候,還是在JS里面更新狀態(tài),但是頁(yè)面更新就不用手動(dòng)操作 DOM 了,直接把整個(gè)表格用模版引擎重新渲染一遍,然后設(shè)置一下innerHTML就完事了。

聽到這樣的做法,經(jīng)驗(yàn)豐富的你一定第一時(shí)間意識(shí)這樣的做法會(huì)導(dǎo)致很多的問題。最大的問題就是這樣做會(huì)很慢,因?yàn)榧词挂粋€(gè)小小的狀態(tài)變更都要重新構(gòu)造整棵 DOM,性價(jià)比太低;而且這樣做的話,inputtextarea的會(huì)失去原有的焦點(diǎn)。最后的結(jié)論會(huì)是:對(duì)于局部的小視圖的更新,沒有問題(Backbone就是這么干的);但是對(duì)于大型視圖,如全局應(yīng)用狀態(tài)變更的時(shí)候,需要更新頁(yè)面較多局部視圖的時(shí)候,這樣的做法不可取。

但是這里要明白和記住這種做法,因?yàn)楹竺婺銜?huì)發(fā)現(xiàn),其實(shí) Virtual DOM 就是這么做的,只是加了一些特別的步驟來避免了整棵 DOM 樹變更

另外一點(diǎn)需要注意的就是,上面提供的幾種方法,其實(shí)都在解決同一個(gè)問題:維護(hù)狀態(tài),更新視圖。在一般的應(yīng)用當(dāng)中,如果能夠很好方案來應(yīng)對(duì)這個(gè)問題,那么就幾乎降低了大部分復(fù)雜性。

3 Virtual DOM算法

DOM是很慢的。如果我們把一個(gè)簡(jiǎn)單的div元素的屬性都打印出來,你會(huì)看到:

而這僅僅是第一層。真正的 DOM 元素非常龐大,這是因?yàn)闃?biāo)準(zhǔn)就是這么設(shè)計(jì)的。而且操作它們的時(shí)候你要小心翼翼,輕微的觸碰可能就會(huì)導(dǎo)致頁(yè)面重排,這可是殺死性能的罪魁禍?zhǔn)住?/p>

相對(duì)于 DOM 對(duì)象,原生的 JavaScript 對(duì)象處理起來更快,而且更簡(jiǎn)單。DOM 樹上的結(jié)構(gòu)、屬性信息我們都可以很容易地用 JavaScript 對(duì)象表示出來:

var element = {
  tagName: "ul", // 節(jié)點(diǎn)標(biāo)簽名
  props: { // DOM的屬性,用一個(gè)對(duì)象存儲(chǔ)鍵值對(duì)
    id: "list"
  },
  children: [ // 該節(jié)點(diǎn)的子節(jié)點(diǎn)
    {tagName: "li", props: {class: "item"}, children: ["Item 1"]},
    {tagName: "li", props: {class: "item"}, children: ["Item 2"]},
    {tagName: "li", props: {class: "item"}, children: ["Item 3"]},
  ]
}

上面對(duì)應(yīng)的HTML寫法是:

  • Item 1
  • Item 2
  • Item 3

既然原來 DOM 樹的信息都可以用 JavaScript 對(duì)象來表示,反過來,你就可以根據(jù)這個(gè)用 JavaScript 對(duì)象表示的樹結(jié)構(gòu)來構(gòu)建一棵真正的DOM樹。

之前的章節(jié)所說的,狀態(tài)變更->重新渲染整個(gè)視圖的方式可以稍微修改一下:用 JavaScript 對(duì)象表示 DOM 信息和結(jié)構(gòu),當(dāng)狀態(tài)變更的時(shí)候,重新渲染這個(gè) JavaScript 的對(duì)象結(jié)構(gòu)。當(dāng)然這樣做其實(shí)沒什么卵用,因?yàn)檎嬲捻?yè)面其實(shí)沒有改變。

但是可以用新渲染的對(duì)象樹去和舊的樹進(jìn)行對(duì)比,記錄這兩棵樹差異。記錄下來的不同就是我們需要對(duì)頁(yè)面真正的 DOM 操作,然后把它們應(yīng)用在真正的 DOM 樹上,頁(yè)面就變更了。這樣就可以做到:視圖的結(jié)構(gòu)確實(shí)是整個(gè)全新渲染了,但是最后操作DOM的時(shí)候確實(shí)只變更有不同的地方。

這就是所謂的 Virtual DOM 算法。包括幾個(gè)步驟:

用 JavaScript 對(duì)象結(jié)構(gòu)表示 DOM 樹的結(jié)構(gòu);然后用這個(gè)樹構(gòu)建一個(gè)真正的 DOM 樹,插到文檔當(dāng)中

當(dāng)狀態(tài)變更的時(shí)候,重新構(gòu)造一棵新的對(duì)象樹。然后用新的樹和舊的樹進(jìn)行比較,記錄兩棵樹差異

把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的DOM樹上,視圖就更新了

Virtual DOM 本質(zhì)上就是在 JS 和 DOM 之間做了一個(gè)緩存。可以類比 CPU 和硬盤,既然硬盤這么慢,我們就在它們之間加個(gè)緩存:既然 DOM 這么慢,我們就在它們 JS 和 DOM 之間加個(gè)緩存。CPU(JS)只操作內(nèi)存(Virtual DOM),最后的時(shí)候再把變更寫入硬盤(DOM)。

4 算法實(shí)現(xiàn) 4.1 步驟一:用JS對(duì)象模擬DOM樹

用 JavaScript 來表示一個(gè) DOM 節(jié)點(diǎn)是很簡(jiǎn)單的事情,你只需要記錄它的節(jié)點(diǎn)類型、屬性,還有子節(jié)點(diǎn):

element.js

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

module.exports = function (tagName, props, children) {
  return new Element(tagName, props, children)
}

例如上面的 DOM 結(jié)構(gòu)就可以簡(jiǎn)單的表示:

var el = require("./element")

var ul = el("ul", {id: "list"}, [
  el("li", {class: "item"}, ["Item 1"]),
  el("li", {class: "item"}, ["Item 2"]),
  el("li", {class: "item"}, ["Item 3"])
])

現(xiàn)在ul只是一個(gè) JavaScript 對(duì)象表示的 DOM 結(jié)構(gòu),頁(yè)面上并沒有這個(gè)結(jié)構(gòu)。我們可以根據(jù)這個(gè)ul構(gòu)建真正的

    Element.prototype.render = function () {
      var el = document.createElement(this.tagName) // 根據(jù)tagName構(gòu)建
      var props = this.props
    
      for (var propName in props) { // 設(shè)置節(jié)點(diǎn)的DOM屬性
        var propValue = props[propName]
        el.setAttribute(propName, propValue)
      }
    
      var children = this.children || []
    
      children.forEach(function (child) {
        var childEl = (child instanceof Element)
          ? child.render() // 如果子節(jié)點(diǎn)也是虛擬DOM,遞歸構(gòu)建DOM節(jié)點(diǎn)
          : document.createTextNode(child) // 如果字符串,只構(gòu)建文本節(jié)點(diǎn)
        el.appendChild(childEl)
      })
    
      return el
    }

    render方法會(huì)根據(jù)tagName構(gòu)建一個(gè)真正的DOM節(jié)點(diǎn),然后設(shè)置這個(gè)節(jié)點(diǎn)的屬性,最后遞歸地把自己的子節(jié)點(diǎn)也構(gòu)建起來。所以只需要:

    var ulRoot = ul.render()
    document.body.appendChild(ulRoot)

    上面的ulRoot是真正的DOM節(jié)點(diǎn),把它塞入文檔中,這樣body里面就有了真正的

      的DOM結(jié)構(gòu):

      • Item 1
      • Item 2
      • Item 3

      完整代碼可見 element.js。

      4.2 步驟二:比較兩棵虛擬DOM樹的差異

      正如你所預(yù)料的,比較兩棵DOM樹的差異是 Virtual DOM 算法最核心的部分,這也是所謂的 Virtual DOM 的 diff 算法。兩個(gè)樹的完全的 diff 算法是一個(gè)時(shí)間復(fù)雜度為 O(n^3) 的問題。但是在前端當(dāng)中,你很少會(huì)跨越層級(jí)地移動(dòng)DOM元素。所以 Virtual DOM 只會(huì)對(duì)同一個(gè)層級(jí)的元素進(jìn)行對(duì)比:

      上面的div只會(huì)和同一層級(jí)的div對(duì)比,第二層級(jí)的只會(huì)跟第二層級(jí)對(duì)比。這樣算法復(fù)雜度就可以達(dá)到 O(n)。

      4.2.1 深度優(yōu)先遍歷,記錄差異

      在實(shí)際的代碼中,會(huì)對(duì)新舊兩棵樹進(jìn)行一個(gè)深度優(yōu)先的遍歷,這樣每個(gè)節(jié)點(diǎn)都會(huì)有一個(gè)唯一的標(biāo)記:

      在深度優(yōu)先遍歷的時(shí)候,每遍歷到一個(gè)節(jié)點(diǎn)就把該節(jié)點(diǎn)和新的的樹進(jìn)行對(duì)比。如果有差異的話就記錄到一個(gè)對(duì)象里面。

      // diff 函數(shù),對(duì)比兩棵樹
      function diff (oldTree, newTree) {
        var index = 0 // 當(dāng)前節(jié)點(diǎn)的標(biāo)志
        var patches = {} // 用來記錄每個(gè)節(jié)點(diǎn)差異的對(duì)象
        dfsWalk(oldTree, newTree, index, patches)
        return patches
      }
      
      // 對(duì)兩棵樹進(jìn)行深度優(yōu)先遍歷
      function dfsWalk (oldNode, newNode, index, patches) {
        // 對(duì)比oldNode和newNode的不同,記錄下來
        patches[index] = [...]
        
        diffChildren(oldNode.children, newNode.children, index, patches)
      }
      
      // 遍歷子節(jié)點(diǎn)
      function diffChildren (oldChildren, newChildren, index, patches) {
        var leftNode = null
        var currentNodeIndex = index
        oldChildren.forEach(function (child, i) {
          var newChild = newChildren[i]
          currentNodeIndex = (leftNode && leftNode.count) // 計(jì)算節(jié)點(diǎn)的標(biāo)識(shí)
            ? currentNodeIndex + leftNode.count + 1
            : currentNodeIndex + 1
          dfsWalk(child, newChild, currentNodeIndex, patches) // 深度遍歷子節(jié)點(diǎn)
          leftNode = child
        })
      }
      

      例如,上面的div和新的div有差異,當(dāng)前的標(biāo)記是0,那么:

      patches[0] = [{difference}, {difference}, ...] // 用數(shù)組存儲(chǔ)新舊節(jié)點(diǎn)的不同

      同理ppatches[1]ulpatches[3],類推。

      4.2.2 差異類型

      上面說的節(jié)點(diǎn)的差異指的是什么呢?對(duì) DOM 操作可能會(huì):

      替換掉原來的節(jié)點(diǎn),例如把上面的div換成了section

      移動(dòng)、刪除、新增子節(jié)點(diǎn),例如上面div的子節(jié)點(diǎn),把pul順序互換

      修改了節(jié)點(diǎn)的屬性

      對(duì)于文本節(jié)點(diǎn),文本內(nèi)容可能會(huì)改變。例如修改上面的文本節(jié)點(diǎn)2內(nèi)容為Virtual DOM 2

      所以我們定義了幾種差異類型:

      var REPLACE = 0
      var REORDER = 1
      var PROPS = 2
      var TEXT = 3

      對(duì)于節(jié)點(diǎn)替換,很簡(jiǎn)單。判斷新舊節(jié)點(diǎn)的tagName和是不是一樣的,如果不一樣的說明需要替換掉。如div換成section,就記錄下:

      patches[0] = [{
        type: REPALCE,
        node: newNode // el("section", props, children)
      }]

      如果給div新增了屬性idcontainer,就記錄下:

      patches[0] = [{
        type: REPALCE,
        node: newNode // el("section", props, children)
      }, {
        type: PROPS,
        props: {
          id: "container"
        }
      }]

      如果是文本節(jié)點(diǎn),如上面的文本節(jié)點(diǎn)2,就記錄下:

      patches[2] = [{
        type: TEXT,
        content: "Virtual DOM2"
      }]

      那如果把我div的子節(jié)點(diǎn)重新排序呢?例如p, ul, div的順序換成了div, p, ul。這個(gè)該怎么對(duì)比?如果按照同層級(jí)進(jìn)行順序?qū)Ρ鹊脑挘鼈兌紩?huì)被替換掉。如pdivtagName不同,p會(huì)被div所替代。最終,三個(gè)節(jié)點(diǎn)都會(huì)被替換,這樣DOM開銷就非常大。而實(shí)際上是不需要替換節(jié)點(diǎn),而只需要經(jīng)過節(jié)點(diǎn)移動(dòng)就可以達(dá)到,我們只需知道怎么進(jìn)行移動(dòng)。

      這牽涉到兩個(gè)列表的對(duì)比算法,需要另外起一個(gè)小節(jié)來討論。

      4.2.3 列表對(duì)比算法

      假設(shè)現(xiàn)在可以英文字母唯一地標(biāo)識(shí)每一個(gè)子節(jié)點(diǎn):

      舊的節(jié)點(diǎn)順序:

      a b c d e f g h i

      現(xiàn)在對(duì)節(jié)點(diǎn)進(jìn)行了刪除、插入、移動(dòng)的操作。新增j節(jié)點(diǎn),刪除e節(jié)點(diǎn),移動(dòng)h節(jié)點(diǎn):

      新的節(jié)點(diǎn)順序:

      a b c h d f g h i j

      現(xiàn)在知道了新舊的順序,求最小的插入、刪除操作(移動(dòng)可以看成是刪除和插入操作的結(jié)合)。這個(gè)問題抽象出來其實(shí)是字符串的最小編輯距離問題(Edition Distance),最常見的解決算法是 Levenshtein Distance,通過動(dòng)態(tài)規(guī)劃求解,時(shí)間復(fù)雜度為 O(M * N)。但是我們并不需要真的達(dá)到最小的操作,我們只需要優(yōu)化一些比較常見的移動(dòng)情況,犧牲一定DOM操作,讓算法時(shí)間復(fù)雜度達(dá)到線性的(O(max(M, N))。具體算法細(xì)節(jié)比較多,這里不累述,有興趣可以參考代碼。

      我們能夠獲取到某個(gè)父節(jié)點(diǎn)的子節(jié)點(diǎn)的操作,就可以記錄下來:

      patches[0] = [{
        type: REORDER,
        moves: [{remove or insert}, {remove or insert}, ...]
      }]

      但是要注意的是,因?yàn)?b>tagName是可重復(fù)的,不能用這個(gè)來進(jìn)行對(duì)比。所以需要給子節(jié)點(diǎn)加上唯一標(biāo)識(shí)key,列表對(duì)比的時(shí)候,使用key進(jìn)行對(duì)比,這樣才能復(fù)用老的 DOM 樹上的節(jié)點(diǎn)。

      這樣,我們就可以通過深度優(yōu)先遍歷兩棵樹,每層的節(jié)點(diǎn)進(jìn)行對(duì)比,記錄下每個(gè)節(jié)點(diǎn)的差異了。完整 diff 算法代碼可見 diff.js。

      4.3 步驟三:把差異應(yīng)用到真正的DOM樹上

      因?yàn)椴襟E一所構(gòu)建的 JavaScript 對(duì)象樹和render出來真正的DOM樹的信息、結(jié)構(gòu)是一樣的。所以我們可以對(duì)那棵DOM樹也進(jìn)行深度優(yōu)先的遍歷,遍歷的時(shí)候從步驟二生成的patches對(duì)象中找出當(dāng)前遍歷的節(jié)點(diǎn)差異,然后進(jìn)行 DOM 操作。

      function patch (node, patches) {
        var walker = {index: 0}
        dfsWalk(node, walker, patches)
      }
      
      function dfsWalk (node, walker, patches) {
        var currentPatches = patches[walker.index] // 從patches拿出當(dāng)前節(jié)點(diǎn)的差異
      
        var len = node.childNodes
          ? node.childNodes.length
          : 0
        for (var i = 0; i < len; i++) { // 深度遍歷子節(jié)點(diǎn)
          var child = node.childNodes[i]
          walker.index++
          dfsWalk(child, walker, patches)
        }
      
        if (currentPatches) {
          applyPatches(node, currentPatches) // 對(duì)當(dāng)前節(jié)點(diǎn)進(jìn)行DOM操作
        }
      }

      applyPatches,根據(jù)不同類型的差異對(duì)當(dāng)前節(jié)點(diǎn)進(jìn)行 DOM 操作:

      function applyPatches (node, currentPatches) {
        currentPatches.forEach(function (currentPatch) {
          switch (currentPatch.type) {
            case REPLACE:
              node.parentNode.replaceChild(currentPatch.node.render(), node)
              break
            case REORDER:
              reorderChildren(node, currentPatch.moves)
              break
            case PROPS:
              setProps(node, currentPatch.props)
              break
            case TEXT:
              node.textContent = currentPatch.content
              break
            default:
              throw new Error("Unknown patch type " + currentPatch.type)
          }
        })
      }

      完整代碼可見 patch.js。

      5 結(jié)語(yǔ)

      Virtual DOM 算法主要是實(shí)現(xiàn)上面步驟的三個(gè)函數(shù):element,diff,patch。然后就可以實(shí)際的進(jìn)行使用:

      // 1. 構(gòu)建虛擬DOM
      var tree = el("div", {"id": "container"}, [
          el("h1", {style: "color: blue"}, ["simple virtal dom"]),
          el("p", ["Hello, virtual-dom"]),
          el("ul", [el("li")])
      ])
      
      // 2. 通過虛擬DOM構(gòu)建真正的DOM
      var root = tree.render()
      document.body.appendChild(root)
      
      // 3. 生成新的虛擬DOM
      var newTree = el("div", {"id": "container"}, [
          el("h1", {style: "color: red"}, ["simple virtal dom"]),
          el("p", ["Hello, virtual-dom"]),
          el("ul", [el("li"), el("li")])
      ])
      
      // 4. 比較兩棵虛擬DOM樹的不同
      var patches = diff(tree, newTree)
      
      // 5. 在真正的DOM元素上應(yīng)用變更
      patch(root, patches)

      當(dāng)然這是非常粗糙的實(shí)踐,實(shí)際中還需要處理事件監(jiān)聽等;生成虛擬 DOM 的時(shí)候也可以加入 JSX 語(yǔ)法。這些事情都做了的話,就可以構(gòu)造一個(gè)簡(jiǎn)單的ReactJS了。

      本文所實(shí)現(xiàn)的完整代碼存放在 Github,僅供學(xué)習(xí)。

      6 References

      https://github.com/Matt-Esch/virtual-dom/blob/master/vtree/diff.js

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/86258.html

相關(guān)文章

  • React Virtual DOM 理解

    摘要:二原理每個(gè)都有兩個(gè),一個(gè)是新的,一個(gè)是原來的。三實(shí)現(xiàn)過程四算法的理解與實(shí)現(xiàn)本質(zhì)上就是在和之間做了一個(gè)緩存。將差異的應(yīng)用到真正的樹上對(duì)真實(shí)上的樹進(jìn)行深度優(yōu)先遍歷,在所有的差異列表中找出當(dāng)前遍歷的節(jié)點(diǎn)差異,然后根據(jù)不同進(jìn)行操作。 React Virtual DOM 一、概念 在react中,對(duì)于每個(gè)DOM對(duì)象都有一個(gè)相應(yīng)的虛擬DOM對(duì)象,相當(dāng)于DOM對(duì)象的輕量級(jí)副本 由于是Virtual...

    smallStone 評(píng)論0 收藏0
  • React.js 小書 Lesson20 - 更新階段的組件生命周期

    摘要:所以對(duì)于組件更新階段的組件生命周期,我們簡(jiǎn)單提及并且提供一些資料給大家。這里為了知識(shí)的完整,補(bǔ)充關(guān)于更新階段的組件生命周期你可以通過這個(gè)方法控制組件是否重新渲染。大家對(duì)這更新階段的生命周期比較感興趣的話可以查看官網(wǎng)文檔。 React.js 小書 Lesson20 - 更新階段的組件生命周期 本文作者:胡子大哈本文原文:http://huziketang.com/books/react...

    Yumenokanata 評(píng)論0 收藏0
  • React系列 --- virtualdom diff算法實(shí)現(xiàn)分析(三)

    摘要:所以只針對(duì)同層級(jí)節(jié)點(diǎn)做比較,將復(fù)雜度的問題轉(zhuǎn)換成復(fù)雜度的問題。 React系列 React系列 --- 簡(jiǎn)單模擬語(yǔ)法(一)React系列 --- Jsx, 合成事件與Refs(二)React系列 --- virtualdom diff算法實(shí)現(xiàn)分析(三)React系列 --- 從Mixin到HOC再到HOOKS(四)React系列 --- createElement, ReactElem...

    sunsmell 評(píng)論0 收藏0
  • React 源碼剖析系列 - 不可思議的 react diff

    摘要:目前,前端領(lǐng)域中勢(shì)頭正盛,使用者眾多卻少有能夠深入剖析內(nèi)部實(shí)現(xiàn)機(jī)制和原理。當(dāng)發(fā)現(xiàn)節(jié)點(diǎn)已經(jīng)不存在,則該節(jié)點(diǎn)及其子節(jié)點(diǎn)會(huì)被完全刪除掉,不會(huì)用于進(jìn)一步的比較。 目前,前端領(lǐng)域中 React 勢(shì)頭正盛,使用者眾多卻少有能夠深入剖析內(nèi)部實(shí)現(xiàn)機(jī)制和原理。本系列文章希望通過剖析 React 源碼,理解其內(nèi)部的實(shí)現(xiàn)原理,知其然更要知其所以然。 React diff 作為 Virtual DOM 的加速...

    shuibo 評(píng)論0 收藏0
  • 2017-08-23 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選免費(fèi)的計(jì)算機(jī)編程類中文書籍英文技術(shù)文檔看不懂看印記中文就夠了的內(nèi)部工作原理美團(tuán)點(diǎn)評(píng)點(diǎn)餐前后端分離實(shí)踐讓你的動(dòng)畫坐上時(shí)光機(jī)中文譯有多棒簡(jiǎn)書譯別再使用圖片輪播了掘金譯如何在中使用掘金個(gè)讓增長(zhǎng)成億美元公司的獨(dú)特方法眾成翻 2017-08-23 前端日?qǐng)?bào) 精選 FPB 2.0:免費(fèi)的計(jì)算機(jī)編程類中文書籍 2.0英文技術(shù)文檔看不懂?看印記中文就夠了!Virtual DOM 的內(nèi)部工作...

    lordharrd 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<