美文网首页
Vue源码实现--VNode与挂载

Vue源码实现--VNode与挂载

作者: 勤奋的大鱼 | 来源:发表于2018-05-27 16:31 被阅读0次

 上一篇讲到当与页面渲染相关的依赖发生变化时,就会触发render watcher的run方法执行,重新收集依赖,而render watcher是把updateComponent方法作为watcher的getter,因此每次页面渲染所需的数据发生改变时,都会执行updateComponent方法。
updateComponent方法很简单

updateComponent = function () {
   vm._update(vm._render())
}

vm._render方法上一篇已经说过了,返回的是一个根据render函数生成的vnode对象,这里主要看一下vm._update以及相关的方法。

Vue.prototype._update = function (vnode) {
  var vm = this
  var prevVnode = vm._vnode
  vm._vnode = vnode
  if (!prevVnode) { // 首次渲染
    vm.$el = this.__patch__(vm.$el, vnode)
  } else {
    vm.$el = this.__patch__(prevVnode, vnode)
  }
}
// 挂载、更新vnode到页面上
Vue.prototype.__patch__ = function (oldVnode, vnode, parentElm, refElm) {
  var isRealElement = oldVnode.nodeType
  if (!isRealElement && sameVnode(oldVnode, vnode)) {
    patchVnode(oldVnode, vnode)
  } else {
    // 若isRealElement为true,说明传入的oldVnode为真实的dom节点,则生成一个空vnode实例,其中vnode.elm为传入的dom
    if (isRealElement) {
      oldVnode = emptyNodeAt(oldVnode)
    }
    var oldElm = oldVnode.elm
    var parentElm = nodeOps.parentNode(oldElm)
    createElm(vnode, parentElm, nodeOps.nextSibling(oldElm))
    // 移除老的dom元素
    removeVnodes(parentElm, [oldVnode], 0, 0)
  }
}
// 创建真实dom,refElm为插入在哪个元素之前
function createElm (vnode, parentElm, refElm) {
  var data = vnode.data
  // 创建节点
  if (vnode.tag) {
    vnode.elm = nodeOps.createElement(vnode.tag)
    // 创建子节点
    createChildren(vnode, vnode.children)
    // 添加attr
    if (data) {
      updateAttrs(emptyNode, vnode)
    }
    // 插入到文档中
    insert(parentElm, vnode.elm, refElm)
  } else {
    vnode.elm = nodeOps.createTextNode(vnode.text)
    insert(parentElm, vnode.elm, refElm)
  }
}

大概逻辑是这样的:
1.根据vm实例上是否有_vnode属性判断是否是首次渲染,若是首次渲染,则传给patch方法的是要被挂载到的dom元素,以及当前的vnode。
2.在patch方法中,若传入的oldVnode是一个真实的dom,则为这个dom元素生成一个vnode对象(vnode.elm传入的dom节点),接下来的处理和新旧两个vnode不是同一个vnode的情况相同,插入新的vnode到文档中,并且删除旧的vnode。
附上本文详细的代码注释与demo(相关代码

相关文章

  • Vue源码实现--VNode与挂载

     上一篇讲到当与页面渲染相关的依赖发生变化时,就会触发render watcher的run方法执行,重新收集依赖,...

  • vue源码2

    之前说了vue是数据驱动的,挂载($mount)之后,vue将要通过render将实例渲染为vnode,即虚拟do...

  • Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载author: @TiffanysBear 实例挂载主要是 $mount ...

  • Vue源码实现--VNode的diff与更新

     上一篇说的是vnode怎样挂载到页面上,但是不可能一个数据的改变就把整个页面的dom都替换掉,这样的话效率也太低...

  • Vue2源码解析系列

    目录 Vue整体流程一(带你了解一下Vue源码) 变化侦测篇(Observer) 虚拟DOM篇(VNode) 模板...

  • vue虚拟DOM初探

    vue源码版本:2.6.11虚拟DOMsrc/core/vdom/vnode.js 虚拟DOM(Virtual D...

  • Vue源码探究-虚拟DOM的渲染

    Vue源码探究-虚拟DOM的渲染 在虚拟节点的实现一篇中,除了知道了 VNode 类的实现之外,还简要地整理了一下...

  • vue响应式和依赖收集

    看了vue源码后实现的一个很简单很简单的vue? 目的主要是串一下new Vue()之后到组件挂载的流程,及数据更...

  • 认识vue虚拟DOM(二)

    什么是vnode 在vue中,存在一个VNode类,使用它可以实例化不同类型的vnode实例,不同类型的vnode...

  • 一、挂载点、模板与实例的关系

    一、挂载点、模板与实例的关系挂载点:Vue中的el属性所绑定的DOM节点Vue只会处理挂载点内的内容 模板:挂载点...

网友评论

      本文标题:Vue源码实现--VNode与挂载

      本文链接:https://www.haomeiwen.com/subject/ghrzhftx.html