虚拟dom

是VDOM,不是VTuber

HTML文件最终都要以DOM的形式进行解析,而Virtual DOM本质上是通过JS对实际DOM进行一层抽象,因为直接操作DOM性能不够且复杂,所以把设计一种方法论,可以通过JS对象的形式描述实际DOM,进而快捷高效的操作V DOM,最后会通过特定的转换方式吧VDOM转换为实际DOM再进行更改. 比如一组实际DOM

<ul id=‘list’>
  <li class=‘item’>itemA</li>
  <li class=‘item’>itemB</li>
</ul>

以虚拟DOM的方式表达就是这样的:

{
	tag:’ul’, // 元素的标签类型 
	attrs:{// 表示指定元素身上的属性 
		id:’list’
	 }, 
	children:[ // ul元素的子节点 
		{ 
			tag: ‘li’, 
			attrs:{ 
				className:’item’ 
			}, 
			children:[‘itemA’] 
		}, { 
			tag: ‘li’, 
			attrs:{
				 className:’item’ 
			}, 
			children:[‘itemB’]
		} ] 
}
tag: 指定元素的标签类型,案例为:'ul’ (react中用type)
attrs: 表示指定元素身上的属性,如id,class, style, 自定义属性等(react中用props)
Children: 表示指定元素是否有子节点,参数以数组的形式传入,如果是文本就是数组中为字符串

VDOM的好处

  • 首先肯定是性能优化,操作DOM非常耗时的操作,频繁的变动DOM会造成浏览器的回流重绘,所以把DOM进行抽象后,可以再patch的过程中尽可能一次性的更新DOM,保证性能

  • 便捷,直接操作DOM必须通过相关的API不方便,而抽象后的DOM形制上其实是JS对象,可以更方便的操作,提高编码效率.

  • 更好的跨平台性,比如Node.js就没有DOM,如果想实现SSR(服务端渲染),那么一个方式就是借助Virtual DOM,因为Virtual DOM本身是JavaScript对象. 而且在的ReactNative,React VR、weex都是使用了虚拟dom。

缺点

  • VDOM到实际DOM的过程实际上是需要进行一层[翻译]的,所以首次渲染大量DOM时,性能不如原生DOM,一次性插入大量DOM的情况下也不如直接innerHTML

  • 如果你的场景是虚拟 DOM 大量更改,这是合适的。但是单一的,频繁的更新的话,虚拟 DOM 将会花费更多的时间处理计算的工作。比如,你有一个 DOM 节点相对较少页面,用虚拟 DOM,它实际上有可能会更慢。但对于大多数单页面应用,这应该都会更快。这也是为啥react和vue中的更新用了异步的方法,频繁更新时,只更新最后一次的。

虚拟DOM的实现案例

实现一套VDOM系统有三个核心问题,把大象装冰箱分三步,开冰箱,装大象,关冰箱(逃

  • complie:把DOM转换为VDOM

  • diff:通过算法,计算旧DOM结构和新DOM结构间的差异

  • patch:吧VDOM转换为DOM

处理属性

主要包括几类的处理

  1. class:这里我们可以理解为动态的类名,sel上的类可以理解为静态的,例如上面class:{active:true}我们可以通过控制这个变量来表示此元素是否是当前被点击

  2. style:内联样式

  3. on:绑定的事件类型

  4. dataset:data属性

  5. hook:钩子函数

vnode = h('div#divId.red', {
    'class': {
        'active': true
    },
    'style': {
        'color': 'red'
    },
    'on': {
        'click': clickFn
    }    
}, [h('p', {}, '文本内容')])
function clickFn() {
    console.log(click')
}
vnode = patch(app, vnode);

最后更新于