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

資訊專欄INFORMATION COLUMN

虛擬DOM內部是如何工作的

hiYoHoo / 2641人閱讀

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

英文原文鏈接

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

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

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

Babel和JSX

創建VNode-一個簡單的virtual DOM元素

處理組件和子組件

初始化渲染和創建一個DOM元素

重新渲染

移除DOM元素

替換DOM元素

The app

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

概覽圖

我們用jsx來寫組件,它會被babel轉換成純js,然后Preact的h函數會將這段js轉換成DOM樹,最后Preact的Virtual DOM算法會將virtual DOM轉換成真實的DOM樹,來構建我們的應用。

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

Babel And JSX

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

對于我們的應用來說,我們將會像下面這樣來寫HTML


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

jsx轉換成js

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

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

但是如何將jsx轉換成h函數的調用呢?Babel就是干這件事情的。Babel遍歷每個jsx節點,并將它們轉換成h函數調用。

Babel JSX(React vs Preact)

默認情況下,Babel將jsx轉換成React.createElement調用

但是我們可以很容易地將函數名修改成任何名稱,只需要在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中的代碼會被轉換成h函數,最初的掛載也會!

這就是代碼執行開始的地方

//Mount to real DOM
render(, document.getElementById(‘app’));
//Converted to "h":
render(h(FilteredList), document.getElementById(‘app’));
h函數的輸出

h函數將jsx轉化后的內容轉換成Virtual DOM節點。一個Preact的Virtual DOM節點就是一個簡單的代表了單個包含屬性和子節點的DOM節點的js對象,如下所示:

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

比如,應用的input標簽對應的Virtual DOM如下:

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

注意:h函數并不是創建整棵樹!它只是簡單地創建某個節點的js對象。但是因為render方法。。。

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

Preact中的Virtual DOM算法

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

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

情景1:初始化app 1.1 創建Virtual DOM

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

下面這幅圖展示了應用首次加載時發生的情況。這個庫最后為FilteredList組件創建了帶有子節點和屬性
的Virtual DOM

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

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

1.2 如果不是一個組件,則創建真實的DOM

在這一步中,它只是為父親節點創建一個真實DOM,對于子節點,重復這個過程

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

1.3 對于子元素重復這個過程

在這一步中,循環所有的子節點。在我們的應用中,將會循環input和list

1.4 處理孩子節點和添加到父親節點

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

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

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

1.5 處理子節點

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

List組件的循環完成時,它會返回List的VNode,就像下面這樣:

1.6 對于所有的子節點,重復步驟1.1到1.4

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

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

1.7 處理完成

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

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

情景2:刪除葉子節點

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

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

2.1 創建VNodes

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

另外,更新周期并不會重新創建已經存在的DOM元素。

2.2 使用真實DOM引用,避免創建重復的節點

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


當VNodes被創建后,每個VNode的屬性都會與真實DOM的屬性相比較。如果真實DOM存在,循環將會轉移到下個節點

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

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


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

情景3-卸載整個組件

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


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

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

最后

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87098.html

相關文章

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

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

    余學文 評論0 收藏0
  • React

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

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

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

    LeviDing 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<