Vue虚拟DOM是这样实现的

1.什么是虚拟DOM?

虚拟DOM就是通过一个JS对象来描述一个DOM节点,比如

<div class="a" id="b">我是内容</div>
{
tag:'div', // 元素标签
attrs:{ // 属性
class:'a',
id:'b'
},
text:'我是内容', // 文本内容
children:[] // 子元素}

通过下面对象描述的方式,将上面的div标签描述出来

2.为什么使用虚拟DOM

我们都知道Vue采用的是MVVM的框,核心思想就是通过数据控制视图,当时数据发生后变化的时候视图也要发生对应的变化,如果不采用虚拟DOM技术,每一次都去操作真实的DOM树那么在性能方面的消耗将会是非常大的。采用虚拟DOM的方式通过JS模拟出的DOM节点,在每次数据法还是能变化的时候我们只需要通过Diff算法来对比计算出需要更新的节点,这样会大大提升视图层渲染性能。

3.Vue中的虚拟DOM

Vue中的虚拟DOM主要通过VNode类实现,以下是VNode类的源码

export default class VNode {
constructor (
tag?: string,
data?: VNodeData,
children?: ?Array<VNode>,
text?: string,
elm?: Node,
context?: Component,
componentOptions?: VNodeComponentOptions,
asyncFactory?: Function
) {
this.tag = tag /*当前节点的标签名*/
this.data = data /*当前节点对应的对象,包含了具体的一些数据信息,是一个VNodeData类型,可以参考VNodeData类型中的数据信息*/
this.children = children /*当前节点的子节点,是一个数组*/
this.text = text /*当前节点的文本*/
this.elm = elm /*当前虚拟节点对应的真实dom节点*/
this.ns = undefined /*当前节点的名字空间*/
this.context = context /*当前组件节点对应的Vue实例*/
this.fnContext = undefined /*函数式组件对应的Vue实例*/
this.fnOptions = undefined
this.fnScopeId = undefined
this.key = data && data.key /*节点的key属性,被当作节点的标志,用以优化*/
this.componentOptions = componentOptions /*组件的option选项*/
this.componentInstance = undefined /*当前节点对应的组件的实例*/
this.parent = undefined /*当前节点的父节点*/
this.raw = false /*简而言之就是是否为原生HTML或只是普通文本,innerHTML的时候为true,textContent的时候为false*/
this.isStatic = false /*静态节点标志*/
this.isRootInsert = true /*是否作为跟节点插入*/
this.isComment = false /*是否为注释节点*/
this.isCloned = false /*是否为克隆节点*/
this.isOnce = false /*是否有v-once指令*/
this.asyncFactory = asyncFactory
this.asyncMeta = undefined
this.isAsyncPlaceholder = false
}
get child (): Component | void {
return this.componentInstance
}}

VNode的类型
VNode类中只有三种类型的节点可以被创建和插入到DOM中分别是元素节点,文本节点,注释节点。

  • 注释节点

描述一个注释节点,只需要传入两个属性,即:text和isComment,text代表的是传入的具体注释信息,isComment代表的则是该节点是不是注释节点,返回一个布尔值

// 创建注释节点
export const createEmptyVNode = (text: string = '') => {
const node = new VNode()
node.text = text
node.isComment = true
return node
}
  • 文本节点

只需要一个属性,那就是text属性,用来表示具体的文本信息。

// 创建文本节点
export function createTextVNode (val: string | number) {
return new VNode(undefined, undefined, undefined, String(val))}

  • 元素节点

元素节点是比较接近我们日常所接触的DOM树,元素节点的作用就是要将这样的html5标签拆分成为包含tag,data,attribute,children等属性的一个Js对象,方便进行DOM更新。

// 真实DOM节点
<div id='a'><span>元素节点</span></div>
// VNode节点
{
tag:'div',
data:{},
children:[
{
tag:'span',
text:'元素节点'
}
]}
  • 组件节点

组件其实就是一个可以服用的UI代码片段,那么本质上就是有多个html标签组成的,这样组件本质上和元素节点是相同的,但是组件和元素节点还是有区别的,组件会有自身的一些属性,比如props,以及该组件对应的Vue实例。

componentOptions :组件的option选项,如组件的props等
componentInstance :当前组件节点对应的Vue实例

  • 函数式组件节点
fnContext:函数式组件对应的Vue实例
fnOptions: 组件的option选项

4.VNode类的作用

其实VNode的作用是相当大的。我们在视图渲染之前,把写好的template模板先编译成VNode并缓存下来,等到数据发生变化页面需要重新渲染的时候,我们把数据发生变化后生成的VNode与前一次缓存下来的VNode进行对比,找出差异,然后有差异的VNode对应的真实DOM节点就是需要重新渲染的节点,最后根据有差异的VNode创建出真实的DOM节点再插入到视图中,最终完成一次视图更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值