vue考点 —— virtual dom

vdom是vue和React的核心。

  • vdom是什么?为何会存在vdom?
  • vdom如何应用,核心API是什么

一、vdom是什么?

虚拟DOM,用JS模拟DOM结构。DOM变化的对比,放在JS层来做(图灵完备语言)。提高重绘性能。

1、什么是图灵完备语言?

就是可以实现逻辑、判断、算法的语言。

2、什么是vdom?

这是一个真实的DOM

<ul id="list">
    <li class="item">Item 1</li>
    <li class="item">Item 2</li>
</ul>

用JS来模拟上面的DOM,就是如下:

{
    tag: 'ul',
    attrs: {
        id: 'list'
    },
    children: [
        {
            tag: 'li',
            attrs: {className: 'item'},      //class是JS保留字,所以这里使用className
            children: ['Item 1']
        },{
            tag: 'li',
            attrs: {className: 'item'},
            children: ['Item 2']
        }
    ]
}

假设DOM发生了变化,我们在真实的DOM结构中,我们要进行DOM操作。而在虚拟的DOM结构中,我们只需要修改不一样的地方即可。为什么这样做,因为浏览器在进行DOM操作的时候消耗很大,而进行JS操作,操作很多次也没什么关系。DOM操作是最昂贵的,现在浏览器执行JS速度非常快。所以说用虚拟DOM。

二、设计场景(为什么会存在vdom)

将数据展示成一个表格。随便修改一个信息,表格也跟着修改。数据如下:

[
    {
        name: '张三',
        age: '20',
        address: '北京'
    },
    {
        name: '李四',
        age: '21',
        address: '上海'
    },
    {
        name: '王五',
        age: '22',
        address: '广州'
    }
]

1、用jQuery实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="./jquery-1.12.4.min.js"></script>
</head>
<body>
    <div id="container"></div>
    <button id="btn-change">change</button>
    <script>
        var data = [
            {
                name: '张三',
                age: '20',
                address: '北京'
            },
            {
                name: '李四',
                age: '21',
                address: '上海'
            },
            {
                name: '王五',
                age: '22',
                address: '广州'
            }
        ]

        function render(data) {
            var $container = $('#container')
            $container.html('')
            var $table = $('<table>')
            $table.append($('<tr><td>name</td><td>age</td><td>address</td></tr>'))
            data.forEach(function(item){
                $table.append($('<tr><td>'+ item.name +'</td><td>' + item.age + '</td><td>' + item.address + '</td></tr>'))
            })
            //渲染到页面
            $container.append($table)
        }

        $('#btn-change').click(function(){
            data[1].age = 30
            data[2].address = '深圳'
            render(data)
        })

        render(data)
    </script>
</body>
</html>

这样做的时候,每次点击click,table里面的所有内容都会重新渲染一次。DOM操作是非常昂贵的。这就是用jQuery实现的时候出现的问题。于是我们引出了vdom。

三、vdom如何应用?核心API是什么?

1、snabbdom?

h函数和pathch函数就是snabbdom的核心API,也就是vdom的核心API。

h函数就是定义一个虚拟DOM节点。

var vnode = h('ul#list', {}, [
    h('li.item', {}, 'Item1'),
    h('li.item', {}, 'Item2')
])


//对应的内容:
{
    tag: 'ul',
    attrs: {
        id: 'list'
    },
    children: [
        {
            tag: 'li',
            attrs: {className: 'item'},
            children: ['Item 1']
        },{
            tag: 'li',
            attrs: {className: 'item'},
            children: ['Item 2']
        }
    ]
}

patch函数

patch(container, vnode) //第一次渲染,container是一个真实的DOM节点,vnode是虚拟的DOM,将vnode放入到container中。
patch(vnode, newVnode)  //DOM有所改变时,将新的newVnode渲染到vnode中,这个过程中将进行复杂的对比,只修改不同的地方

如下是用vdom实现的一个例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="container"></div>
    <button id="btn-change">change</button>
    <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>
        var snabbdom = window.snabbdom
        var patch = snabbdom.init([
            snabbdom_class,
            snabbdom_props,
            snabbdom_style,
            snabbdom_eventlisteners
        ])
        var h = snabbdom.h

        var container = document.getElementById('container')

        //生成vnode
        var vnode = h('ul#list', {}, [
            h('li.item', {}, 'Item 1'),
            h('li.item', {}, 'Item 2')
        ])
        patch(container, vnode)


        //点击click,只修改了第二个li,新增了第三个li,第一个li并没有重新渲染。
        document.getElementById('btn-change').addEventListener('click', function(){
            var newVnode = h('ul#list', {}, [
                h('li.item', {}, 'Item 1'),
                h('li.item', {}, 'Item B'),
                h('li.item', {}, 'Item 3')
            ])
            patch(vnode, newVnode)
        })
    </script>
</body>
</html>

三、用vnode实现前面的设计场景如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="container"></div>
<button id="btn-change">change</button>
<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>
    var snabbdom = window.snabbdom
    var patch = snabbdom.init([
            snabbdom_class,
            snabbdom_props,
            snabbdom_style,
            snabbdom_eventlisteners
        ])
    var h = snabbdom.h
    var data = [
            {
                name: '张三',
                age: '20',
                address: '北京'
            },
            {
                name: '李四',
                age: '21',
                address: '上海'
            },
            {
                name: '王五',
                age: '22',
                address: '广州'
            }
        ]
        //把表头也放在data中
         data.unshift({
             name:'姓名',
             age: '年龄',
             address: '地址'
         })
         var container = document.getElementById('container')
         //渲染函数
         var vnode
         function render(data){
            var newVnode = h('table',{}, data.map(function(item){
                var tds = []
                var i
                for(i in item){
                    if(item.hasOwnProperty(i)){
                        tds.push(h('td', {}, item[i] + ''))
                    }
                }
                return h('tr',{},tds)
            }))
             if(vnode) {
                patch(vnode, newVnode)
             } else {
                patch(container, newVnode)
             }
             vnode = newVnode
         }
         render(data)

         var btnChange = document.getElementById('btn-change')
         btnChange.addEventListener('click', function() {
             data[1].age = 30
             data[2].address = '深圳'
             render(data)
         })
 </script>
</body>
</html>

四、vdom的核心API

  • h('<标签名>',{...属性...},[...子元素...])
  • h('<标签名>',{...属性...},'...')
  • patch(container,vnode)
  • patch(vnode,newVnode)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值