带你看懂Virtual DOM及diff算法在vue中的应用

什么是vdom

vdom 是一种使用js对象来描述真实dom的技术,通过这种,我们能精确知道哪些真实的Dom改变了,从而尽量减少Dom操作的性能开销。

snabbdom.js

vdom是通过snabbdom.js库实现的,大概过程有以下三部

1.compile (把真实的dom编译成Vnode);

2.diff (利用diff算法,比较oldVnode和newVnode之间有什么变化);

3.patch(把这些变化通过打补丁的方式更新到真实的dom上去);

snabbdom的两个核心函数 h(),patch() 

snabbdom - h 函数

h()函数主要是根据传进来的参数,返回一个 vnode(虚拟节点)对象

 snabbdom - patch 函数

 patch()函数的两种用法

1. patch(container,vnode) //将虚拟dom渲染成真实的dom

2.patch(vnode,newVnode) // 利用diff算法比较oldVnode和newVnode的差异

 什么是diff算法

diff算法很早就存在,一开始diff算法是计算两个文本的差异。所以一定要明确的是,diff 算法并不是react或者vue原创,它们只是通过diff 算法比较两个vnode差异,并只针对该部分进行原生的dom操作,而并非重新渲染整个页面。

vdom 中是在patch(vnode,newVode)比较新旧函数时会用到diff

以下是patch()函数的核心代码分析

function patch (oldVnode, vnode) {
    ......
    if (sameVnode(oldVnode, vnode)) {
        patchVnode(oldVnode, vnode)
    } else {
        const oEl = oldVnode.el // 当前oldVnode对应的真实元素节点
        let parentEle = api.parentNode(oEl)  // 父元素
        createEle(vnode)  // 根据Vnode生成新元素
        if (parentEle !== null) {
            api.insertBefore(parentEle, vnode.el, api.nextSibling(oEl)) // 将新元素添加进父元素
            api.removeChild(parentEle, oldVnode.el)  // 移除以前的旧元素节点
            oldVnode = null
        }
    }
    .......
    return vnode
}

patchVnode (oldVnode, vnode) {
    const el = vnode.el = oldVnode.el
    let i, oldCh = oldVnode.children, ch = vnode.children
    if (oldVnode === vnode) return
    if (oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text) {
        api.setTextContent(el, vnode.text)
    }else {
        updateEle(el, vnode, oldVnode)
        if (oldCh && ch && oldCh !== ch) {
            updateChildren(el, oldCh, ch)
        }else if (ch){
            createEle(vnode) //create el's children dom
        }else if (oldCh){
            api.removeChildren(el)
        }
    }
}

 这个函数做了以下事情:

1.找到对应真实的dom,称为el

2.判断vnode和oldVode是否完全相同,如果是,那么直接返回 return

3.如果他们都有文本节点且不相等,则更新el的文本节点

4.如果oldVode有子节点,而vnode没有,则删除el的子节点

5.如果oldVode没有子节点,而vnode有,则将vnode的子节点真实化之后添加到el

6.如过两者都有子节点,则执行updateChildren函数比较子节点

updateChildren 函数比较复杂,感兴趣的同学可以去了解下源码。

vue的整体流程

1.第一步:解析模板成render函数

2.第二步:响应式开始监听

3.第三步:首次渲染,显示页面,且绑定依赖

4.第四步:data属性变化,触发render

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值