浅谈什么是虚拟DOM

虚拟 DOM

为什么要写这偏博客:在阅读了多篇关于 DOM 的文章后,做一个简单的汇总,也借此提炼出一个精炼但深入的答案关于:谈谈你对虚拟 DOM 的理解 😃。由于虚拟DOM涉及到的diff算法比较复杂,之后会写一篇文章单独讨论和总结

正文

当谈及虚拟 DOM 的时候,在我的脑中有几个问题蹦出来:

  1. 什么是虚拟 DOM,它和 JSX 是强绑定的吗
  2. 为什么要用它,能带来什么好处?性能?开发便捷?它如果带来了好处,会带来副作用吗?
  3. 它和最古早的开发有什么区别

接下来,将会从这个几个问题进行一个简单的总结和整理。

什么是虚拟 DOM ,它和 JSX 强绑定吗

虚拟 DOM 可以看成一个 JS 对象,有 tag,props,children
tags:什么种类的 dom 元素
props: id,class,so on
children: 包裹的里面的 dom 元素

<div class='demo'>
    <p class='inner'>this is demo</p>
</div>

{
    tag:'div',
    props:{class:'demo'},
    children:[
        {tag:'p',
        props:{class:'inner'},
        children:[
            'this is demo'
        ]}
    ]
}

做一个不是很准确的比方:虚拟 DOM 就美猴王(这里需要给出一个前提:无论真假都是乐高玩具,意味着它们是多个部分组合而成的,而不是玻璃材质的-每次修改都需要重造);我们编写前端的代码本质上是要去操作 DOM(真的美猴王,玩具表面有金层),但是直接操作 DOM 太耗费性能了(操作需要非常小心),因此我们先写代码控制假的美猴王的姿势状态,之后再让真的美猴王根据假的美猴王改变自己的姿势和状态,使得两者一致。(这里暂时不讨论我们编写代码的难易程度,后面我会去完善这个比喻,关于 diff)

(在 React 中,其实就是通过 babel 把 JSX 语法转化为上文所描述的数据结构,然后再去创建真实的 DOM)

第二个小问题,JSX 与虚拟 DOM 并不是强绑定的,换句话说虚拟 DOM 可不仅仅是 JSX 语法才可以使用,只要能把语言转成以上描述的数据结构进行

为啥要用它

前面说了虚拟 DOM 有一个好处就是性能好,但是这句话听起来,像一句空话,性能不好它能火吗,能使用这么广吗:) 听我慢慢道来。这里我们用数据结构来描述真实的 DOM-》这种描述的结果就是上文的那种数据结构,既然有了数据结构,那肯定少不了算法,有了算法我们就能搞各种骚操作了,但这种骚操作无外乎,就是从空间和时间的复杂度进行优化。

在使用虚拟 DOM 第一次去创建真实 DOM 的时候好像比原来直接操作真实 DOM 还麻烦些,用 JSX 举例子,JSX 需要用 babel 转化为上文那样的数据结构,再去按照数据结构描述的样式去生成真实的 DOM,相比之下还不如我们最古早的方式直接操作 DOM 生成页面元素来的痛快。

但是这仅仅是第一次,当后期我们需要不停的变动页面上的元素,这时候问题就来了,如果我们仍用古早的方式,我们就不得不考虑这次这个 div 相比上次该 append 到哪个 div 上去,是不是还要 remove 那个 div 元素,这时候就要不停的操作真实 DOM,搞不好还要 N 次循环遍历。而通过虚拟 DOM 映射到真实 DOM 的方式,我们只需要拿到新旧数据的差异值就行了(那些相同或者说可以复用的我就保留着),之后再去映射到真实 DOM,起不快哉。谈到这里问题又来了,在虚拟 DOM 这一堆数据结构中,我们需要比较与上次不同的地方,我们该如何比较了,咋比较效率最高了,别做了半天,还不如古早的方法。
既然都已经是数据结构了,而且每次都需要做类似的比对,作为程序员,我们当然就需要把这种公共的算法提炼出来,还得保证性能最优,这当然难不倒 leetcode 刷爆的各位大佬:)

diff 算法

这部分就是新旧虚拟 DOM 比对,这里的算法是经常变动的,这里我只总结一个概览的情况。具体的算法实现需要查阅具体的文档(之后会模仿着 Diact 和 React 写一个更详细的 demo_React),之后也会单独写一章来进行总结。
根据上文给出的虚拟 DOM 数据结构的可以分析,这里的比对主要是三个点: tag,props,children。写到这里又有一个问题出现了,虚拟 DOM 对比完的结果是什么样的,它该如何与真实的 DOM 关联上了
第一个小问题:返回的是什么,返回的是新旧虚拟 Dom 的差异,这里只是把这个差异用数据的形式表达出来;第二个问题:在已经有的 DOM 上(之前的),依照这个表达差异的数据修改真实的 DOM 就行。

现在,在回头来看之前给出的比方,其实本质上就是一句话:操作 DOM 太耗费性能,能够复用就复用,复用不就是组件化,软件设计的思想吗。

一些想法

从最古早的直接操作 DOM,再到这里虚拟 DOM 最终映射到虚拟 DOM,其核心点还是 DOM,只是我们利用软件设计的一些思想去优化我们的实践-如这里的复用思想。而这里从虚拟 DOM 到 diff,无外乎就是以下流程,一个是 babel——用于生成虚拟 DOM 的数据结构,一个是 diff 算法,还有就是如何将虚拟 DOM 如何挂载成真实的 DOM

本文章同步到自己的github上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值