日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
虛擬DOM如何進(jìn)化為真實DOM

前言

創(chuàng)新互聯(lián)是專業(yè)的化州網(wǎng)站建設(shè)公司,化州接單;提供網(wǎng)站設(shè)計、成都網(wǎng)站設(shè)計,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行化州網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!

Vue和React的Render函數(shù)中都涉及到了Virtual DOM的概念,Virtual DOM也是性能優(yōu)化上的重要一環(huán),同時突破了直接操作真實DOM的瓶頸,本文帶著以下幾個問題來闡述Virtual DOM。

1.為什么要操作虛擬 DOM?

2.什么是虛擬 DOM?

3.手把手教你實現(xiàn)虛擬 DOM 渲染真實 DOM

希望閱讀本文之后,能夠讓你深入的了解虛擬 DOM并且在開發(fā)和面試中收益。

為什么要操作虛擬 DOM

為了幫助我們更好的理解為什么要操作虛擬 DOM,我們先從瀏覽器渲染[1]一個 HTML 文件需要做哪些事情說起:

瀏覽器渲染機制大致可以分為以下 5 步走:

1.創(chuàng)建 DOM tree

2.創(chuàng)建 Style Rules

3.構(gòu)建 Render tree

4.布局 Layout

5.繪制 Painting

我們過去使用原生JavaScript和jquery去操作真實DOM的時候,瀏覽器會從構(gòu)建 DOM 開始從頭到尾的執(zhí)行一遍渲染的流程。

在一次開發(fā)中,假如產(chǎn)品告訴你一個需求,你需要在一次操作中更新10個DOM節(jié)點,理想狀態(tài)是瀏覽器一次性構(gòu)建完DOM樹,再執(zhí)行后續(xù)操作。但瀏覽器沒這么智能,收到第一個更新 DOM 請求后,并不知道后續(xù)還有9次更新操作,因此會馬上執(zhí)行流程,最終執(zhí)行 10 次流程。

過了一會產(chǎn)品經(jīng)理把你叫過去和你說把需求改一下,此時你又需要操作一次 DOM 的更新,那么這個時候之前做的 10 次 DOM 操作就是白白浪費性能,浪費感情。

即使計算機硬件一直在更新迭代,但是操作DOM的代價仍舊是昂貴的,頻繁操作 DOM 還是會出現(xiàn)頁面卡頓,影響用戶的體驗。真實的 DOM 節(jié)點,哪怕一個最簡單的 div 也包含著很多屬性,可以打印出來直觀感受一下:

如此多的屬性,如果每次對 DOM 結(jié)構(gòu)都進(jìn)行更新,一次,兩次,三次...一百次....一千次...,可想而知,是多么龐大的數(shù)據(jù)量。

因此虛擬DOM就是為了解決這個瀏覽器性能問題而被設(shè)計出來的。例如前面的例子,假如一次操作中有 10 次更新 DOM 的動作,虛擬DOM不會立即操作DOM,而是將這 10 次更新 DOM 的動作通過Diff算法最終生成一個js對象,然后通知瀏覽器去執(zhí)行一次繪制工作,這樣可以避免大量的無謂的計算量。

什么是虛擬 DOM

虛擬 DOM[2]就是我們上面所說的js對象。

其本質(zhì)上就是在JS和DOM之間做了一個緩存??梢灶惐?CPU 和硬盤,既然硬盤這么慢,我們就在它們之間加個緩存:既然 DOM 這么慢,我們就在它們 JS 和 DOM 之間加個緩存。CPU(JS)只操作內(nèi)存(Virtual DOM),最后的時候再把變更寫入硬盤(DOM),直接操作內(nèi)存中的 JS 對象的速度顯然要更快。

 
 
 
 
  1. function vnode(tag, data, key, children, text) { 
  2.     return { 
  3.         tag, 
  4.         data, 
  5.         key, 
  6.         children, 
  7.         text 
  8.     } 

舉個栗子:

假如我們有這樣的一個 DOM 樹

 
 
 
 
  1.  
  2.   前端簡報
  3.  
  4.   
  5. vue
  6.  
  7.  

 那么,我們怎么用 js 的對象來對應(yīng)到這個樹呢?

 
 
 
 
  1.     tag: 'ul',        // 元素標(biāo)簽 
  2.     data: {           // 屬性 
  3.         class: 'list' 
  4.     }, 
  5.     key: '', 
  6.     text: '',  // 文本內(nèi)容 
  7.     children: [ 
  8.         { 
  9.             tag: "li", 
  10.             data: { 
  11.                 class: "item" 
  12.             }, 
  13.             key: '', 
  14.             text: '', 
  15.             children: [ 
  16.                 { 
  17.                     tag: undefined, 
  18.                     data: undefined, 
  19.                     key: undefined, 
  20.                     text: '前端簡報', 
  21.                     children: [] 
  22.                 } 
  23.             ] 
  24.         }, 
  25.         { 
  26.             tag: "li", 
  27.             data: "", 
  28.             key: '', 
  29.             text: '', 
  30.             children: [ 
  31.                 { 
  32.                     tag: undefined, 
  33.                     data: undefined, 
  34.                     key: undefined, 
  35.                     text: 'vue', 
  36.                     children: [] 
  37.                 } 
  38.             ] 
  39.         } 
  40.     ]       // 子元素 

由此可知:DOM tree的信息都可以用JavaScript對象來表示,反過來,我們也可以用 JavaScript對象表示的樹結(jié)構(gòu)來構(gòu)建一棵真正的DOM樹。

實現(xiàn)虛擬 DOM 渲染真實 DOM

有了JavaScript對象之后如何轉(zhuǎn)化為真實的 DOM 樹結(jié)構(gòu)呢?

ul 和 li 在 js 對象中,頁面上并沒有此結(jié)構(gòu),所以我們需要把ul和li轉(zhuǎn)化為和

標(biāo)簽

而文本標(biāo)簽我們定義 Vnode 為:

 
 
 
 
  1.    tag: undefined, 
  2.    data: undefined, 
  3.    key: undefined, 
  4.    text: 'vue', 
  5.    children: [] 

故可以判斷tag的類型來確定創(chuàng)建元素的類型.

 
 
 
 
  1. function createElm(vnode) { 
  2.     let { tag, data, children, key, text } = vnode; 
  3.  
  4.     if (typeof tag == "string") { 
  5.         vnode.el = document.createElement(tag);  //創(chuàng)建元素放到vnode.el上 
  6.         children.forEach(child => { 
  7.             vnode.el.appendChild(createElm(child)) 
  8.         }) 
  9.     } else { 
  10.         vnode.el = document.createTextNode(text);  //創(chuàng)建文本 
  11.     } 
  12.     return vnode.el 

如果子節(jié)點存在并且也是虛擬DOM的話,我們通過遞歸調(diào)用創(chuàng)建子節(jié)點。

創(chuàng)建 DOM 樹結(jié)構(gòu)之后我們需要設(shè)置節(jié)點的屬性,即處理虛擬 DOM 中的data屬性。

 
 
 
 
  1. function updateProperties(vnode) { 
  2.     let el = vnode.el; 
  3.     let newProps = vnode.data || {}; 
  4.     for (let key in newProps) { 
  5.         if (key == "style") { 
  6.             for (let styleName in newProps.style) { 
  7.                 el.style[styleName] = newProps.style[styleName]; 
  8.             } 
  9.         } else if (key == "class") { 
  10.             el.className = newProps.class; 
  11.         } else { 
  12.             el.setAttribute(key, newProps[key]); 
  13.         } 
  14.     } 

在我們創(chuàng)建元素標(biāo)簽之后調(diào)用updateProperties方法即可

把上面創(chuàng)建出來的真實 DOM 結(jié)構(gòu) vnode.el 添加到文檔當(dāng)中即可呈現(xiàn)出我們需要的真實 DOM 結(jié)構(gòu)

 
 
 
 
  1. let parentElm = document.getElementById("app").parentNode; 獲取之前app的父親body 
  2. parentElm.insertBefore(createElm(vnode), document.getElementById("app").nextSibling); //body里在老的app后面插入真實dom 
  3. parentElm.removeChild(document.getElementById("app")); //刪除老的節(jié)點 

總結(jié)

以上就是本文的全部內(nèi)容,我想我們現(xiàn)在應(yīng)該了解什么是虛擬DOM的概念了以及虛擬DOM是如何實現(xiàn)真實DOM渲染的。其中用到了主要用到了子節(jié)點的遞歸,下篇文章將講解虛擬節(jié)點的 diff 算法,敬請期待。

參考資料
[1]虛擬DOM介紹: https://www.jianshu.com/p/616999666920

[2]如何實現(xiàn)一個 Virtual DOM 算法: 'https://github.com/livoras/blog/issues/13'


本文題目:虛擬DOM如何進(jìn)化為真實DOM
標(biāo)題網(wǎng)址:http://m.5511xx.com/article/cojhcjp.html