成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

虛擬DOM內(nèi)部是如何工作的

hiYoHoo / 2717人閱讀

摘要:但是它與里大部分的概率是保持一致的。但是如何將轉(zhuǎn)換成函數(shù)的調(diào)用呢就是干這件事情的。好了,讓我們看看是如何工作的。下面的圖片在流程圖中高亮了一個組件是如何工作的最后希望這篇文章能幫助你理解是如何工作的至少在中

英文原文鏈接

Virtual DOM很神奇,同時也比較復(fù)雜,難以理解。react,preact和相似的js庫都使用了virtual dom。然而,我找不到任何好的文章或者文檔,可以詳細地又容易理解的方式來解釋它。因此我決定自己寫一篇。

注意:文章篇幅較長,文中有大量的圖片來幫助理解。文中使用的是preact的代碼,因為它體積小,容易閱讀。但是它與React里大部分的概率是保持一致的。希望閱讀完這篇文章后,你可以更好地理解React和Preact這樣的類庫,甚至為它們作出貢獻。

在這篇文章中,我將列舉一個簡單的例子來解釋以下這些是如何工作的:

Babel和JSX

創(chuàng)建VNode-一個簡單的virtual DOM元素

處理組件和子組件

初始化渲染和創(chuàng)建一個DOM元素

重新渲染

移除DOM元素

替換DOM元素

The app

這是一個簡單地可篩選的搜索應(yīng)用,它包含了兩個組件FilteredListListList組件用來渲染一組items(默認:"California"和"New York")。這個應(yīng)用有一個搜索框,可以根據(jù)字母來過濾列表項。非常地直觀:

概覽圖

我們用jsx來寫組件,它會被babel轉(zhuǎn)換成純js,然后Preact的h函數(shù)會將這段js轉(zhuǎn)換成DOM樹,最后Preact的Virtual DOM算法會將virtual DOM轉(zhuǎn)換成真實的DOM樹,來構(gòu)建我們的應(yīng)用。

在深入Virtual DOM的生命周期之前,我們先理解一下jsx,因為它為庫提供了入口。

Babel And JSX

在React,Preact這樣的類庫中,沒有HTML標簽,取而代之的是,一切都是javascript。所以我們要在js中寫HTML標簽,但是在js中寫HTML簡直就是噩夢?

對于我們的應(yīng)用來說,我們將會像下面這樣來寫HTML


這就是jsx的由來。jsx本質(zhì)上就是允許我們在javascript中書寫HTML!并且允許我們在HTML中通過使用花括號來使用js。
jsx幫助我們像下面這樣寫組件

jsx轉(zhuǎn)換成js

jsx很酷,但它不是合法的js,并且最終我們需要的是真實的DOM。JSX只是幫助編寫一個真實DOM的替代品,除此之外,它別無用處。所以我們需要一種方法將它轉(zhuǎn)換成對應(yīng)的JSON對象(也就是Virtual DOM),作為轉(zhuǎn)化成真實DOM的輸入。我們需要一個函數(shù)來實現(xiàn)這個功能。

在Preact中h函數(shù)就是干這件事情的,等同于React中的React.createElement。

但是如何將jsx轉(zhuǎn)換成h函數(shù)的調(diào)用呢?Babel就是干這件事情的。Babel遍歷每個jsx節(jié)點,并將它們轉(zhuǎn)換成h函數(shù)調(diào)用。

Babel JSX(React vs Preact)

默認情況下,Babel將jsx轉(zhuǎn)換成React.createElement調(diào)用

但是我們可以很容易地將函數(shù)名修改成任何名稱,只需要在babelrc中配置一下即可

Option 1:
//.babelrc
{   "plugins": [
      ["transform-react-jsx", { "pragma": "h" }]
     ]
}
Option 2:
//Add the below comment as the 1st line in every JSX file
/** @jsx h */

掛載到真實DOM

不僅僅是render中的代碼會被轉(zhuǎn)換成h函數(shù),最初的掛載也會!

這就是代碼執(zhí)行開始的地方

//Mount to real DOM
render(, document.getElementById(‘a(chǎn)pp’));
//Converted to "h":
render(h(FilteredList), document.getElementById(‘a(chǎn)pp’));
h函數(shù)的輸出

h函數(shù)將jsx轉(zhuǎn)化后的內(nèi)容轉(zhuǎn)換成Virtual DOM節(jié)點。一個Preact的Virtual DOM節(jié)點就是一個簡單的代表了單個包含屬性和子節(jié)點的DOM節(jié)點的js對象,如下所示:

{
   "nodeName": "",
   "attributes": {},
   "children": []
}

比如,應(yīng)用的input標簽對應(yīng)的Virtual DOM如下:

{
   "nodeName": "input",
   "attributes": {
    "type": "text",
    "placeholder": "Search",
    "onChange": ""
   },
   "children": []
}

注意:h函數(shù)并不是創(chuàng)建整棵樹!它只是簡單地創(chuàng)建某個節(jié)點的js對象。但是因為render方法。。。

好了,讓我們看看Virtual DOM是如何工作的。

Preact中的Virtual DOM算法

在下面的流程圖中,展示了在Preact中,組件是如何被創(chuàng)建、更新和刪除的過程。同時也展示了像componentWillMount這樣的生命周期事件是什么時候被調(diào)用的。

現(xiàn)在理解起來有些困難,所以我們一步一步來拆解流程圖中的每種情況。

情景1:初始化app 1.1 創(chuàng)建Virtual DOM

高亮的部分展示了根據(jù)給定的組件生成的Virtual DOM樹。注意一點這里并沒有為子組件創(chuàng)建Virtual DOM

下面這幅圖展示了應(yīng)用首次加載時發(fā)生的情況。這個庫最后為FilteredList組件創(chuàng)建了帶有子節(jié)點和屬性
的Virtual DOM

注意:在這個過程中還調(diào)用了componentWillMountrender生命周期方法(在上圖中的綠色區(qū)塊)

此時,我們有了一個Virtual DOM,div元素是父親節(jié)點,帶有一個input和一個list的子節(jié)點

1.2 如果不是一個組件,則創(chuàng)建真實的DOM

在這一步中,它只是為父親節(jié)點創(chuàng)建一個真實DOM,對于子節(jié)點,重復(fù)這個過程

此時,我們在下圖中只有一個div展示出來

1.3 對于子元素重復(fù)這個過程

在這一步中,循環(huán)所有的子節(jié)點。在我們的應(yīng)用中,將會循環(huán)input和list

1.4 處理孩子節(jié)點和添加到父親節(jié)點

在這一步中,我們將會處理葉子節(jié)點,由于input有個父節(jié)點div,那么我們將會將input添加到div中作為
子節(jié)點。然后流程轉(zhuǎn)向創(chuàng)建List(第二個子節(jié)點是div)

此時,我們的app長下面這樣

注意:在input被創(chuàng)建之后,由于它沒有任何子節(jié)點,并不會立馬就去循環(huán)和創(chuàng)建List組件。相反地,它會首先
input標簽添加到父節(jié)點div中去,完事之后再返回處理List標簽

1.5 處理子節(jié)點

現(xiàn)在控制流回到了步驟1.1,并且開始處理List組件。但是由于List是一個組件,所以它會遍歷執(zhí)行自身的render方法,從而獲得一組VNodes,就像下面這樣:

當(dāng)List組件的循環(huán)完成時,它會返回List的VNode,就像下面這樣:

1.6 對于所有的子節(jié)點,重復(fù)步驟1.1到1.4

對于每個節(jié)點,它將會重復(fù)以上的每一步。一旦到達葉子節(jié)點,它將會被加入到父節(jié)點中去,并且重復(fù)這個過程。

下面的圖片展示了每個節(jié)點是如何添加上去的(深度優(yōu)先遍歷)

1.7 處理完成

此時已經(jīng)完成了處理過程。然后對于所有的組件,會調(diào)用componentDidMount方法(從子組件開始,直到父組件)

注意:當(dāng)一切準備就緒,一個真實DOM的引用會被添加到每個組件的實例中。這個引用會在接下來的一些更新操作(創(chuàng)建、更新、刪除)被用來比較,避免重復(fù)創(chuàng)建相同的DOM節(jié)點

情景2:刪除葉子節(jié)點

當(dāng)輸入"cal"并按回車,這將會刪除第二個列表子元素,也就是一個葉子節(jié)點(New York),同時其他父元素都會保留。

讓我們看下這種情景下,流程是怎么樣的

2.1 創(chuàng)建VNodes

在初始化渲染之后,后面的每次改變都是一次"更新"。當(dāng)創(chuàng)建VNodes時,更新周期與創(chuàng)建周期非常相似,并且再一次創(chuàng)建所有的VNodes。不過既然是更新(不是創(chuàng)建)組件,將會調(diào)用每個組件和子組件相應(yīng)的componentWillReceiveProps,shouldComponentUpdatecomponentWillUpdate方法。

另外,更新周期并不會重新創(chuàng)建已經(jīng)存在的DOM元素。

2.2 使用真實DOM引用,避免創(chuàng)建重復(fù)的節(jié)點

之前提到過,在初始化加載期間,每個組件都有一個指向真實DOM樹的引用。下面的圖展示了引用是如何尋找我們的應(yīng)用的。


當(dāng)VNodes被創(chuàng)建后,每個VNode的屬性都會與真實DOM的屬性相比較。如果真實DOM存在,循環(huán)將會轉(zhuǎn)移到下個節(jié)點

2.3 如果在真實DOM中有其它的節(jié)點,則刪除

下面的圖展示了真實DOM和VNode之間的不同


由于存在不同,真實DOM中的"New York"節(jié)點會被算法刪除掉,正如下面圖展示的那樣。這個算法也稱為"componentDidUpdate"生命周期。

情景3-卸載整個組件

舉例:當(dāng)輸入blabla時,由于不匹配"California"和"New York",我們將不會渲染子組件List。這意味著,我們需要卸載整個組件


刪除一個組件類似于刪除一個多帶帶的節(jié)點。除此之外,當(dāng)我們刪除一個包含組件引用的節(jié)點,將會調(diào)用"componentWillUnmount",然后遞歸刪除所有的DOM元素。在刪除了所有的真實DOM元素之后,"componentDidUnmount"將會被調(diào)用。
下面的圖片展示了真實DOM元素"ul"包含了指向"List"組件的引用。

下面的圖片在流程圖中高亮了deleting/unmounting一個組件是如何工作的

最后

希望這篇文章能幫助你理解Virtual DOM是如何工作的(至少在Preact中)

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/87098.html

相關(guān)文章

  • JavaScript 如何工作:編寫自己 Web 開發(fā)框架 + React 及其虛擬 DOM

    摘要:與大多數(shù)全局對象不同,沒有構(gòu)造函數(shù)。為什么要設(shè)計更加有用的返回值早期寫法寫法函數(shù)式操作早期寫法寫法可變參數(shù)形式的構(gòu)造函數(shù)一般寫法寫法當(dāng)然還有很多,大家可以自行到上查看什么是代理設(shè)計模式代理模式,為其他對象提供一種代理以控制對這個對象的訪問。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第 19 篇。 如果你錯過了前面的章節(jié),可以在這里找到它們: 想閱讀更多優(yōu)質(zhì)文章請...

    余學(xué)文 評論0 收藏0
  • React

    摘要:基礎(chǔ)創(chuàng)建虛擬參數(shù)元素名稱,例如參數(shù)屬性集合,例如,,,從參數(shù)開始,表示該元素的子元素,通常這些元素通過創(chuàng)建,文本文件可以直接插入嘻嘻哈哈這是渲染器,將元素渲染到頁面中。 React簡介 FeceBook開源的一套框架,專注于MVC的視圖V模塊。實質(zhì)是對V視圖的一種實現(xiàn)。 React框架的設(shè)計沒有過分依賴于某個環(huán)境,它自建一套環(huán)境,就是virtual DOM(虛擬DOM)。 提供基礎(chǔ)AP...

    hlcc 評論0 收藏0
  • React 深入系列1:React 中元素、組件、實例和節(jié)點

    摘要:中的元素組件實例和節(jié)點,是中關(guān)系密切的個概念,也是很容易讓初學(xué)者迷惑的個概念。組件和元素關(guān)系密切,組件最核心的作用是返回元素。只有組件實例化后,每一個組件實例才有了自己的和,才持有對它的節(jié)點和子組件實例的引用。 React 深入系列,深入講解了React中的重點概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項目中更加靈活地使用React。 React 中的元素、組件、實...

    LeviDing 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<