前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >白话虚拟dom

白话虚拟dom

作者头像
挥刀北上
发布2019-07-19 15:43:29
7890
发布2019-07-19 15:43:29
举报
文章被收录于专栏:Node.js开发

又到了发文章的时候了,今天和大家一起来讨论下虚拟dom,为什么要讨论这个玩意呢,因为现在最流行的两个前端框架都用到了虚拟dom。

首先咱们从起源说起,做web开发的时候,当数据发生变化的时候,我们要去更新dom,从而给前端用户呈现最新的数据,流程图如下:

数据更改后直接操作dom,我们举例来看一下需求,比方说一个列表,列表下面有一个点击加载更多的按钮:

点击加载更多,会发送一个ajax请求,请求更多的数据,然后将数据渲染到页面,我们一般会如何做呢,代码片段如下:

我们看到,每次数据更新后,我们借助模板生成html片段,获取列表的新旧内容拼接,这里我们思考一下,就会发现已经存在的列表信息是不应该重新渲染的。

上面的案例先放一边,先了解一下什么是虚拟dom,简单来说就是一句话,用js对象来描述dom结构,示例如下:

有如下dom结构:

代码语言:javascript
复制
<ul id='list'>
  <li class='item'>item1</li>
  <li class='item'>item2</li>
</ul>

用js对象表示如下:

代码语言:javascript
复制
   {

        tag: 'ul',
            attrs: {
            id:'list'
        },
        children: [
            {
                tag: 'li',
                attrs: {
                    className: 'item'
                },
                children: ['item1']
            }, {
                tag: 'li',
                attrs: {
                    className: 'item'
                },
                children: ['item2']
            }
        ]
    }

既然dom结构可以表示为js对象,那么根据js对象也可以生成dom结构。

再来看一张图,这张图我们将数据和ui生成一个js对象来表示dom结构也就是Virtual Dom,然后根据这个js对象(Virtual Dom),来生成真实的Dom;

虚拟dom就是上面说的js对象,我们在数据和真实dom之间,加了一个中间层,类似夹心饼干。

这样做有什么好处呢?我们观察上面的流程,好像比直接操作dom还复杂,不要急,这里我们还有引入另外一个概念,diff算法,为什么要引入这个diff算法呢?

这是因为虚拟dom的渲染机制,那什么是虚拟dom的渲染机制呢?

当我们更改了数据后,并不是我们想的那样:立即成新的虚拟dom,然后根据新的虚拟dom渲染成真实Dom。而是数据更改后,在生成新的虚拟dom后,通过diff算法比较新旧虚拟dom,得出需要重新渲染的部分,然后最小化的更新真实dom。

流程如下图:

然后,我们在看上面的点击加载更多案例,如果借助了虚拟dom,那么伪代码可坑就是这样操作了:

虚拟dom渲染流程用代码表示如下:

代码语言:javascript
复制
// 1. 构建虚拟DOM
var tree = el('div', {'id': 'container'}, [
    el('h1', {style: 'color: blue'}, ['simple virtal dom']),
    el('p', ['Hello, virtual-dom']),
    el('ul', [el('li')])
])

// 2. 通过虚拟DOM构建真正的DOM
var root = tree.render()
document.body.appendChild(root)

// 3. 更改数据后生成新的虚拟DOM
var newTree = el('div', {'id': 'container'}, [
    el('h1', {style: 'color: red'}, ['simple virtal dom']),
    el('p', ['Hello, virtual-dom']),
    el('ul', [el('li'), el('li')])
])

// 4. 比较两棵虚拟DOM树的不同
var patches = diff(tree, newTree)

// 5. 在真正的DOM元素上应用变更
patch(root, patches)

说完虚拟dom,再次提到两个最火的前端框架,Vue和react,这两个框架都使用了虚拟dom,这两个框架所使用的虚拟dom有什么不同呢?

主要是更新虚拟dom的策略不同:

vue中将数据维护成了可观察的数据,数据的每一项都通过getter来收集依赖,然后将依赖转化成watcher保存在闭包中,数据修改后,触发数据的setter方法,然后调用所有的watcher修改旧的虚拟dom,从而生成新的虚拟dom,然后就是运用diff算法 ,得出新旧dom不同,根据不同更新真实dom。

而react的更新策略比较粗暴,可以用一个公式来表述,virtualDom = h(data),数据发生变化,通过调用setState生成新的虚拟dom,(而不是像vue一样为每个数据社会setter、getter、watcher),然后对比新旧dom,得出新旧dom不同,更新真实dom。但是,react给开发者暴露一个生命周期函数:shouldcomponentupdate,这个函数可以根据开发者的需求决定数据发生变化决定是否重新渲染。

react是 函数式组件思想,当你 setstate 就会遍历,diff 当前组件所有的子节点子组件, 这种方式开销是很大的,要合理使用shouldcomponentupdate。

vue为每个数据设置setter、getter、watcher,当数据足够多时,运行效率反倒不如react。

所以在选择框架时,要衡量一下,如果页面数据量大,变化多,选react,而如果项目中型,并且想快速开发,选vue。

以上便是笔者在当前阶段对虚拟dom的认识,其中不乏一些不足之处,如果你有什么建议或者想法欢迎留言。

https://www.jianshu.com/p/bef1c1ee5a0e

https://www.cnblogs.com/wubaiqing/p/6726429.html

https://blog.csdn.net/sinat_17775997/article/details/88287074

https://segmentfault.com/a/1190000015749345

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nodejs全栈开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档