2019-11-23

vue虛擬DOM是什么?vue的虛擬DOM的用法

1、為什么需要虛擬DOM

前面我們從零開始寫了一個簡單的類Vue框架,其中的模板解析和渲染是通過Compile函數(shù)來完成的,采用了文檔碎片代替了直接對頁面中DOM元素的操作,在完成數(shù)據(jù)的更改后通過appendChild函數(shù)將真實的DOM插入到頁面。

雖然采用的是文檔碎片,但是操作的還是真實的DOM。

而我們知道操作DOM的代價是昂貴的,所以vue2.0采用了虛擬DOM來代替對真實DOM的操作,最后通過某種機制來完成對真實DOM的更新,渲染視圖。

所謂的虛擬DOM,其實就是用JS來模擬DOM結構,把DOM的變化操作放在JS層來做,盡量減少對DOM的操作(個人認為主要是因為操作JS比操作DOM快了不知道多少倍,JS運行效率高)。然后對比前后兩次的虛擬DOM的變化,只重新渲染變化了的部分,而沒有變化的部分則不會重新渲染。

比如我們有如下的DOM結構。

eg

<ul id="list">

??????<li class="item1">Item 1</li>

??????<li class="item2">Item 2</li>

</ul>

我們完全可以用JS對象模擬上面的DOM結構,模擬后就會變成下面的這種結構。

varvdom = {

????tag: 'ul',

????attr: {

????????id: 'list',

????},

????children: [

????????{

????????????tag: 'li',

????????????attrs: {

????????????????className: 'item',

????????????????children: ['Item 1']

????????????},

????????},

????????{

????????????tag: 'li',

????????????attrs: {

????????????????className: 'item',

????????????????children: ['Item 2']

????????????}

????????}

????]


}

必須要注意一點的是:JS模擬的DOM結構并沒有模擬所有DOM節(jié)點上的屬性、方法(因為DOM節(jié)點本身的屬性非常多,這也是DOM操作耗性能的一個點),而是只模擬了一部分和數(shù)據(jù)操作相關的屬性和方法。

2、vue虛擬DOM的用法

Vue在2.0版本引入了vdom。其vdom是基于snabbdom庫所做的修改。snabbdom是一個開源的vdom庫。

snabbdom的主要作用就是將傳入的JS模擬的DOM結構轉換成虛擬的DOM節(jié)點。

先通過其中的h函數(shù)將JS模擬的DOM結構轉換成虛擬DOM之后,再通過其中的patch函數(shù)將虛擬DOM轉換成真實的DOM渲染到頁面中。

為了保證頁面的最小化渲染,snabbdom引入了Diff算法,通過Diff算法找出前后兩個虛擬DOM之間的差異,只更新改變了的DOM節(jié)點,而不重新渲染為改變的DOM節(jié)點。

在這里我不打算分析snabbdom的源碼來解釋到底snabbdom是怎么干成這件事的(主要是現(xiàn)階段沒到那個水平,哈哈。再者已經(jīng)有很多同學做過類似的分析,相關鏈接附在文章末尾)。

我會從snabbdom的使用角度來看Vue中的虛擬DOM是如何完成視圖渲染的。

我們先看一下snabbdom中兩個核心API的功能。

h()函數(shù):將傳入的JS模擬的DOM結構模板轉換成vnode。(vnode是一個純JS對象)

patch()函數(shù):將虛擬的DOM節(jié)點渲染到頁面中。

我們提供一個實例來看一下snabbdom的實際作用。

<!DOCTYPE html>

<html lang="en">

<head>

????<meta charset="UTF-8">

????<meta name="viewport"content="width=device-width, initial-scale=1.0">

????<meta http-equiv="X-UA-Compatible"content="ie=edge">

????<title>Document</title></head><body>

????<p id="container"></p>

????<button id="btn-change">change</button>

????<!-- 引入snabbdom庫,先不必糾結為什么這樣引入,以及每個文件的作用。本篇文章只是介紹一下虛擬DOM的工作方式,并不涉及原理解析

????主要是因為博主目前功力尚淺,有興趣的小伙伴可以另行研究 -->

????<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom.js"></script>

????<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-class.js"></script>

????<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-props.js"></script>

????<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-style.js"></script>

????<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-eventlisteners.js"></script>

????<script src="https://cdn.bootcss.com/snabbdom/0.7.1/h.js"></script>

????<script>

????????//定義patch函數(shù)

????????varpatch = snabbdom.init([

????????????snabbdom_class,

????????????snabbdom_props,

????????????snabbdom_style,

????????????snabbdom_eventlisteners

????????])??????? //定義h函數(shù)

????????varh = snabbdom.h;??????? //生成一個vnode

????????varvnode = h('ul#list',{},[

????????????h('li.item',{},['Item 1']),

????????????h('li.item',{},['Item 2']),

????????])

     //console.log(vnode);

????????//獲取container

????????varcontainer = document.getElementById('container');

????????patch(container,vnode);//初次渲染


????????varbtn = document.getElementById('btn-change');

????????btn.onclick = function() {???????????

????????varnewVnode = h('ul#list',{},[

????????????????h('li.item',{},['Item 1']),

????????????????h('li.item',{},['Item B']),

????????????????h('li.item',{},['Item 3']),

????????????])

????????????patch(vnode,newVnode);//再次渲染

????????????vnode = newVnode;//將修改后的newVnode賦值給vnode      ???????

????????????}???

????????????</script>

????????????</body>

????????????</html>

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 前言 ??Vue2.0引入了虛擬DOM,比Vue1.0的初始渲染速度提升了2~4倍,并大大降低了內(nèi)存消耗。目前主流...
    A鄭家慶閱讀 13,925評論 0 10
  • 真實火災中的消防演習-vr消防安全體驗 烈火英雄相信有很多人都看過,看火災面前人的生命是多么的渺小,如何掌握火災救...
    奧特曼打怪獸wd閱讀 152評論 0 0
  • 回憶 首先,render函數(shù)中手寫h=>h(app),new Vue()實例初始化init()和原來一樣。$mou...
    LoveBugs_King閱讀 2,415評論 1 2
  • VR消防演練——減少火宅造成的人員傷害 隨著科學技術的不斷進步,各個方面都在變化中。世界總是在你不經(jīng)意的時候就發(fā)生...
    奧特曼打怪獸wd閱讀 149評論 0 0
  • 在 Lumen 的路由里面發(fā)現(xiàn)了這樣一個問題。真的是時間挺長的 bug 了…… 以上路由注冊在運行時會拋出類似「C...
    lalxyy閱讀 1,292評論 0 1

友情鏈接更多精彩內(nèi)容