React 重溫之 虛擬DOM

2021-09-13 19:39:48 字數 1906 閱讀 2959

虛擬dom可以說是現代前端庫的標配了,好像你乙個前端框架不實現乙個虛擬dom出門都不好意思跟人打招呼,那麼到底什麼是虛擬dom呢?

那麼與之相對應的,我們可以簡單理解成虛擬dom就是用其他語言模擬出乙個dom的樹形結構

那麼問題來了,為什麼要用其它語言模擬dom,人家本來就已經是乙個很完整的樹形結構物件了啊?

這就涉及到前端乙個效能問題,那就是dom操作非常非常耗費效能,我們在很多前端優化的文章中都被告知要儘量減少、合併dom操作,就是因為dom非常非常耗費效能,因為太慢了。。。

為什麼慢? 因為幹的事兒多啊,建立乙個dom的時候要繼承一堆屬性、方法,涉及到多個dom節點的話還會有節點的巢狀啊,父子關係的維護之類的;同時,我們使用原生js api去操作dom的時候,效率也是很低的,這也是為啥jquery當年可以流行的原因(因為它做了許多優化。。。)

因為直接去操作真實的dom效率很低,聰明的人決定用比較快的js去模擬實現乙個dom樹,所有需要對dom節點進行的操作,都可以現在虛擬dom上進行建立、更新、銷毀等一系列計算操作,最後得出乙個更新後的虛擬dom,然後再一次性的更新到真實dom上,從而提高頁面效率。

上面已經大概說了虛擬dom是怎麼回事,那麼虛擬dom最核心的就是diff演算法,簡單的說就是比對新舊dom樹來確定如何去更新真實dom。

學術上有一些解決將一棵樹轉換為另一棵樹的最小運算元演算法問題的通用方案。然而,樹中元素個數為n,最先進的演算法 的時間複雜度為o(n3)演算法鏈結 。

這是通用的演算法,考慮的是所有情況,但react並不需要乙個通用的演算法,基於以下兩個假設,react 實現了乙個 o(n)演算法:

基於以上兩點,我們來詳細說說react中的對比策略:

如果更新前後是兩種不同型別的dom元素,那就沒什麼說的,直接銷毀原來的節點,建立新的節點.(比如原來是div,更新為span)在這個過程中,原來節點的componentwillunmount函式被觸犯, 新節點的componentwillmount和componentdidmount依次被觸發.

需要特別指出的是,當前更新節點的所有子節點都會被銷毀重建,而不管子節點是否有更新. 簡單的來說,就是根變了,那麼這個根上的所有葉子都要更新了.

當節點型別沒有發生變化,而只是熟悉變化的話,react就智慧型多了,只會更新變化的部分. 好比是乙個元素有多個css樣式,如果只變化了乙個樣式,那麼react也只更新乙個.

當元素不是葉子節點的時候,也就是乙個元件元素的時候,會繼續深入的去比較子元素來更新子元素.

當子元素有變動的時候,react會更新子元素.

子元素的變動指的是節點的型別/屬性/位置等的變動. 型別和屬性的變動會觸發更新,這個比較好理解.子元素的位置變動,指的是如果乙個資源原來在第一位,更新後到第二位了,react會認為這是一種變動,從而觸發更新.

這樣看起來react也沒有那麼智慧型.那麼這個時候就要引入乙個很重要的key屬性.react通過給子元件乙個key屬性.來唯一標識乙個子元件,如果更新前後的元件key值一樣,並且除了位置之外其他屬性沒有變化,那麼就不會觸發更新.

我們知道另乙個經常被提起的前端框架vue也實現了虛擬dom,vue是乙個傳統意義上的mvc模型.通過例項化乙個vue物件來繫結dom和data的關係,也就是繫結view和model.通過對model中每個屬性新增[反射]來完成監視器的註冊. 當model中的資料模型變化時,watcher會重新計算,從而引發view層的更新.

上面提到,vue的更新是model中資料的變化引發在初始化時注入的watcher的變化,從而引起view層的更新.只要觀察到資料變化,vue 將開啟乙個佇列,並緩衝在同一事件迴圈中發生的所有資料改變。如果同乙個 watcher 被多次觸發,只會一次推入到佇列中。

根據以上特點,我們知道vue中的元件更新是由model資料的更新引起的,因為view和model在初始化時已經完成繫結,所以當model發生變化時,哪些view需要變化已經很明確了,所以就不需要像react那般去判斷比對了.

React虛擬DOM轉換為真實DOM

按照上面的猜想,那麼render方法的作用就是 render方法接收兩個引數,第二個引數沒什麼好說的,固定寫法,第乙個引數有以下幾種情況 類元件函式元件 文字 數字 class extends component 然後再來處理函式元件,函式元件的寫法是,直接就返回了dom 對於文字 數字,直接新增到...

React 中的虛擬DOM

react 的重新渲染,效能是很高的。因為它引入了虛擬dom的概念。呃,來看一下,render 函式渲染頁面的幾種做法。前兩步都是拿到state 資料 與 jsx模版。第一種就是比較樸素的方式。第二種方式雖然不用完全替換,但是也需要比對兩個dom。第三種是虛擬dom方式。虛擬dom 本質上就是 js...

React學習筆記 虛擬DOM

react對底層的 作了封裝,在大多數情況下,我們不需要直接去操作dom。但是有時候我們還是需要使用到底層的 的,比如輸入框獲取焦點,這個時候可以通過第三方的類庫或者react提供的api實現。react之所以快,是因為它不直接操作dom。react將dom結構儲存在記憶體中,然後同render 的...