vue之diff算法

Vue通过虚拟DOM和Diff算法提高页面运行效率,减少DOM操作。当数据变化时,Vue不会立即渲染,而是经过Diff判断哪些节点需要更新。Diff过程包括patch、sameVnode和updateChildren等步骤,对比新旧节点,确定最小更新策略,实现高效更新视图。
摘要由CSDN通过智能技术生成

1.我们知道vue使用的是虚拟DOM去减少对真是DOM的操作次数,来提升页面的运行的效率。那他的内部原理是怎样的呢。首先vue和react在更新dom时,使用的算法基本相同,都是基于anabbdom。当浏览器的页面数据发生变化时,vue不会立即渲染。二十经过diff算法,判断出哪些是不需要变化的,那些是需要变化更新的,只需要更新那些需要更细的DOM就可以了,这样就减少了很多不必要的DOM操作,在很大程度上提高了性能。vue内部就是使用了这样的抽象节点VNode,它是对真实DOM的抽象,所以他不依赖任何平台,包括浏览器,weex,甚至是node平台也可以 对这样一颗抽象DOM树进行创建删除修改等操作。

Vue更新视图

在vue早期版本中1.0中,每个数据都对应一个Watcher;而在vue2.x中一个组件对应一个Watcher,这样当我们的数据变化的时候,In the set function,the notify function of Dep will be triggered to notify the watcher to execute vm._update(vm._render(), hydrating)method to update the view,Let’s take a look_Update method

Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
   
        const vm: Component = this
        const prevEl = vm.$el
        const prevVnode = vm._vnode
        const restoreActiveInstance = setActiveInstance(vm)
        vm._vnode = vnode
        //Vue.prototype.__patch__ is injected in entry points
        //based on the rendering backednd used.
        // 基于后端渲染Vue.prototype.__patch__被用来作为一个入口
        if (!prevVnode) {
   
          // initial render
          vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly*/)
        } else {
   
          //updates
          vm.$el = vm.__patch__(prevVnode, vnode)
        }

        restoreActiveInstance() 
        // update __vue__ reference
        /*更新新的实例对象的__vue__*/
        if (prevEl) {
   
          prevEl.__vue__ = null
        }
        if (vm.$el) {
   
          vm.$el.__vue__ = vm
        }
        //if parent is a HOC, upadate its $el as well
        if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
   
          vm.$parent.$el = vm.$el
        }
        //update hook is called by the scheduler to ensure that children are
        //update in a parent's updated hook.
      }

Obviusly, we can see _The update method will patch the incoming vnode and the old vnode.
Let’s take a look at what happens in the patch function.

patch

The patch function compares the new and old nodes, and then determines which nodes need to be modified. Only these nodes needs to be modifie,so that the DOM can be updated more eddifciently. Let’s take a look at the code first.

return function patch (oldVnode, vnode, hydrating, removeOnly){
    
        /*Vnode dose not exist. Call the destroy hook to delete the node*/
        if (isUndef(vnode)) {
   
          if (isDef(oldVnode) invokeDestroyHook(oldVnode))
          returns
        }

        let isInitialPath = false
        const insetedVnodeQueue = {
   }

        /*oldVnode does not exist. Create a new node directly.*/
        if (isUndef(oldVnode)) {
   
          //empty mount (likely as component),create new root element
          isInitialPath = true
          createElm(vnode, insetedVnodeQueue)
        } else {
   
          /*Mark whether the old vnode has nodeType*/
          const isRealElement = isDef(oldVnode.nodeType)
          if(!isRealElement && sameVnode(oldVnode.nodeType)) {
   
            //patch existing root node
            /*When it is the same node,modify the existing node directly*/
            patchVnode(oldVnode, vnode, insetedVnodeQueue, null, null, removeOnly)
          } else {
   
            if (isRealElement) {
   
              //mounting to a real element 
              //check if this is server-rendered content and if we can perform
              //a successful hydration
              if (oldVnode.nodeType === 1 && oldCnode.hasAttribute(SSR_ATTR)) {
   
                /*When the old vnode is the element rendered by the sever,
                the drawing is marked as true*/
                oldVnode.removeAttribute(SSR_ATTR)
                hydrating = true
              }
              if (isTrue(hydrating)){
   
                //need to merge to real DOM
                if (hydrating(oldVnode, vnode, insertedVnodeQueue)) {
   
                  //call the insert hook
                  invokeInsertHook(vnode, insertedVnodeQueue, true)
                  return oldVnode
                } else if(process.env.NODE_ENV !== 'production') {
   
                  warn(

                  )
                }
              }
              //either not server-rendered,or hydration failed.
              //create an empty node and replace it
              oldVnode = emptyNodeAt(oldVnode)
            }

            //replacing existing element
            const oldElm = oldVnode.elm
            const parentElm = nodeOps.parentNode(oldElm)

            //create new node
            createElm(
              vnode,
              insertedVnodeQueue,
              //extremely rare edge case: do not insert if old element is in a leaving
              //transition.Only happen when combining transition + 
              //keep-alive + HOCs. (#4590)
              oldElm.leaveCb ? null : parentElm,
              nodeOps.nextSibling(oldElm)
            )

            //update parent placeholder node element, recursively
            if(isDef(vnode.parent)) {
   
              let ancestor = vnode.parent
              const patchable = isPatchable(vnode)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值