摘要:不同的框架對這三個屬性的命名會有點差別,但表達的意思是一致的。它們分別是標簽名屬性和子元素對象。我們先來看下頁面的更新一般會經過幾個階段。元素有可能是數組的形式,需要將數組解構一層。
歡迎關注我的公眾號睿Talk,獲取我最新的文章:
目前最流行的兩大前端框架,React和Vue,都不約而同的借助Virtual DOM技術提高頁面的渲染效率。那么,什么是Virtual DOM?它是通過什么方式去提升頁面渲染效率的呢?本系列文章會詳細講解Virtual DOM的創建過程,并實現一個簡單的Diff算法來更新頁面。本文的內容脫離于任何的前端框架,只講最純粹的Virtual DOM。敲單詞太累了,下文Virtual DOM一律用VD表示。
這是VD系列文章的開篇,以下是本系列其它文章的傳送門:
你不知道的Virtual DOM(一):Virtual Dom介紹
你不知道的Virtual DOM(二):Virtual Dom的更新
你不知道的Virtual DOM(三):Virtual Dom更新優化
你不知道的Virtual DOM(四):key的作用
你不知道的Virtual DOM(五):自定義組件
你不知道的Virtual DOM(六):事件處理&異步更新
本質上來說,VD只是一個簡單的JS對象,并且最少包含tag、props和children三個屬性。不同的框架對這三個屬性的命名會有點差別,但表達的意思是一致的。它們分別是標簽名(tag)、屬性(props)和子元素對象(children)。下面是一個典型的VD對象例子:
{ tag: "div", props: {}, children: [ "Hello World", { tag: "ul", props: {}, children: [{ tag: "li", props: { id: 1, class: "li-1" }, children: ["第", 1] }] } ] }
VD跟dom對象有一一對應的關系,上面的VD是由以下的HTML生成的
Hello World
- 第1
一個dom對象,比如li,由tag(li), props({id: 1, class: "li-1"})和children(["第", 1])三個屬性來描述。
三、為什么需要VDVD 最大的特點是將頁面的狀態抽象為 JS 對象的形式,配合不同的渲染工具,使跨平臺渲染成為可能。如 React 就借助 VD 實現了服務端渲染、瀏覽器渲染和移動端渲染等功能。
此外,在進行頁面更新的時候,借助VD,DOM 元素的改變可以在內存中進行比較,再結合框架的事務機制將多次比較的結果合并后一次性更新到頁面,從而有效地減少頁面渲染的次數,提高渲染效率。我們先來看下頁面的更新一般會經過幾個階段。
從上面的例子中,可以看出頁面的呈現會分以下3個階段:
JS計算
生成渲染樹
繪制頁面
這個例子里面,JS計算用了691毫秒,生成渲染樹578毫秒,繪制73毫秒。如果能有效的減少生成渲染樹和繪制所花的時間,更新頁面的效率也會隨之提高。
通過VD的比較,我們可以將多個操作合并成一個批量的操作,從而減少dom重排的次數,進而縮短了生成渲染樹和繪制所花的時間。至于如何基于VD更有效率的更新dom,是一個很有趣的話題,日后有機會將另寫一篇文章介紹。
我們先從如何生成VD說起。借助JSX編譯器,可以將文件中的HTML轉化成函數的形式,然后再利用這個函數生成VD??聪旅孢@個例子:
function render() { return (Hello World); }
- 第1
這個函數經過JSX編譯后,會輸出下面的內容:
function render() { return h( "div", null, "Hello World", h( "ul", null, h( "li", { id: "1", "class": "li-1" }, "u7B2C1" ) ) ); }
這里的h是一個函數,可以起任意的名字。這個名字通過babel進行配置:
// .babelrc文件 { "plugins": [ ["transform-react-jsx", { "pragma": "h" // 這里可配置任意的名稱 }] ] }
接下來,我們只需要定義h函數,就能構造出VD
function flatten(arr) { return [].concat.apply([], arr); } function h(tag, props, ...children) { return { tag, props: props || {}, children: flatten(children) || [] }; }
h函數會傳入三個或以上的參數,前兩個參數一個是標簽名,一個是屬性對象,從第三個參數開始的其它參數都是children。children元素有可能是數組的形式,需要將數組解構一層。比如:
function render() { return (
繼續之前的例子。執行h函數后,最終會得到如下的VD對象:
{ tag: "div", props: {}, children: [ "Hello World", { tag: "ul", props: {}, children: [{ tag: "li", props: { id: 1, class: "li-1" }, children: ["第", 1] }] } ] }
下一步,通過遍歷VD對象,生成真實的dom
// 創建dom元素 function createElement(vdom) { // 如果vdom是字符串或者數字類型,則創建文本節點,比如“Hello World” if (typeof vdom === "string" || typeof vdom === "number") { return doc.createTextNode(vdom); } const {tag, props, children} = vdom; // 1. 創建元素 const element = doc.createElement(tag); // 2. 屬性賦值 setProps(element, props); // 3. 創建子元素 // appendChild在執行的時候,會檢查當前的this是不是dom對象,因此要bind一下 children.map(createElement) .forEach(element.appendChild.bind(element)); return element; } // 屬性賦值 function setProps(element, props) { for (let key in props) { element.setAttribute(key, props[key]); } }
createElement函數執行完后,dom元素就創建完并展示到頁面上了(頁面比較丑,不要介意...)。
五、總結本文介紹了VD的基本概念,并講解了如何利用JSX編譯HTML標簽,然后生成VD,進而創建真實dom的過程。下一篇文章將會實現一個簡單的VD Diff算法,找出2個VD的差異并將更新的元素映射到dom中去:你不知道的Virtual DOM(二):Virtual Dom的更新
P.S.: 想看完整代碼見這里,如果有必要建一個倉庫的話請留言給我:代碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/96981.html
摘要:變化的只有種更新和刪除。頁面的元素的數量隨著而變。四總結本文詳細介紹如何實現一個簡單的算法,再根據計算出的差異去更新真實的。 歡迎關注我的公眾號睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的兩大前端框架,React 和 Vue,都不約而同的借助 Virtual DOM 技術提高頁面的渲染...
摘要:最后里面沒有第四個元素了,才會把蘋果從移除。四總結本文基于上一個版本的代碼,加入了對唯一標識的支持,很好的提高了更新數組元素的效率。 歡迎關注我的公眾號睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的兩大前端框架,React和Vue,都不約而同的借助Virtual DOM技術提高頁面的渲染...
摘要:如果列表是空的,則存入組件后將異步刷新任務加入到事件循環當中。四總結本文基于上一個版本的代碼,加入了事件處理功能,同時通過異步刷新的方法提高了渲染效率。 歡迎關注我的公眾號睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的兩大前端框架,React和Vue,都不約而同的借助Virtual DO...
摘要:現在流行的前端框架都支持自定義組件,組件化開發已經成為提高前端開發效率的銀彈。二對自定義組件的支持要想正確的渲染組件,第一步就是要告訴某個標簽是自定義組件。下面的例子里,就是一個自定義組件。解決了識別自定義標簽的問題,下一步就是定義標簽了。 歡迎關注我的公眾號睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、...
摘要:經過這次優化,計算的時間快了那么幾毫秒?;诋斍斑@個版本的代碼還能做怎樣的優化呢,請看下一篇的內容你不知道的四的作用。 歡迎關注我的公眾號睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 目前最流行的兩大前端框架,React和Vue,都不約而同的借助Virtual DOM技術提高頁面的渲染效率。那么,什...
閱讀 819·2021-10-25 09:48
閱讀 611·2021-08-23 09:45
閱讀 2496·2019-08-30 15:53
閱讀 1759·2019-08-30 12:45
閱讀 586·2019-08-29 17:21
閱讀 3407·2019-08-27 10:56
閱讀 2547·2019-08-26 13:48
閱讀 691·2019-08-26 12:24