虚拟dom
虚拟dom,即virtual dom(vdom),是vue和react的核心。
问题一:vdom是什么?为何会存在vdom?
虚拟dom,即用JS来模拟DOM结构。目的是,将DOM变化的对比,放在JS层来做。提高重绘性能。
怎样用JS来模拟呢,举个简单的例子:
上图这个简单的dom结构,使用JS来模拟:
如果我们要删除Item1和Item2,加上Item3,如果直接做dom操作,那么需要依次执行删除Item1,Item2,加上Item3的操作。但如果使用虚拟dom,我们可以保留之前的拥有Item1和Item2的对象,再生成一个另外一个符合要求的只有Item3的对象。通过JS算法的对比,找出差异再进行DOM修改。
为什么要这样做呢?因为在浏览器中,DOM操作是最昂贵的操作之一,为了项目的性能优化,我们最好尽可能减少Dom操作,很明显,使用虚拟dom能够有效减少dom操作以及界面重绘及回流。
接下来,我们设计要给需求场景:
按照要求,使用jQuery来实现
这样可以知道,每当我们修改表格的时候,虽然只修改了'30'和'深圳'这两个元素,但整个表格都重新渲染了,操作消耗大。
最理想的,就是只重绘改变的节点。DOM操作是昂贵的,在编程中应该尽量减少DOM操作而不是“推导重来”。
因此vdom出现了。
问题二:vdom如何应用?核心API是什么?
vdom是如何存在的?是一个怎样的存在?
首先介绍一下snabbdom,snabbdom是一个开源的vdom的库。vdom是一个统称的技术实现,能实现vdom的库很多,不限于snabbdom这一个。
为什么要介绍snabbdom呢?因为vue2.0兼容了snabbdom的代码,所以拿这个来举例。
用snabbdom重做上面的例子,我们在上面的例子中可以看到每次修改时都要清空容器再重新塞入内容,这是非常麻烦的。但用vdom使用如下:
首先snabbdom主要有两种核心API,分别是h()和patch()
举个使用的例子:
首先h函数是负责创建虚拟节点的,举一个比较简单的例子:
第一个参数是指定创建tag为ul、id为list的节点,第二个为属性,是一个对象。接下来是一个数组,里面包含了子节点。
patch有两种使用情况,第一种情况:第一个参数为真实dom节点,第二个为一个虚拟dom对象。这样可以将虚拟dom渲染为真实节点(直接替换了)。第二种情况:数据源有所改变的话,第一个参数为旧的vnode,第二个为新的vnode,此时patch会进行两种vnode的对比,将需要更新的进行更新,不更新的就不会重新渲染。使用如下:
问题三:介绍一下diff算法
linux里有diff命令,其作用是找出两个文件中的差异。git 中也有git diff命令,作用是看两种版本的异同。
因此可以看到,diff算法即是比较出两个对象的差异。
vdom中为什么要使用diff算法呢?还是之前的一个原因:DOM操作是昂贵的,因此需要尽量减少DOM操作。所以在更新DOM时,需要找出本次DOM必须更新的节点来更新,其他的不更新。而这个“找出”的过程,就需要diff算法。
简单的写一下diff的实现:
首先是第一种情况的实现:
第二种情况的实现: