vue 源码分析 step_2-组件更新时候,diff 的对象从何而来?

已经知道了早初始化过程中,在 update 方法里面间接调用了___patch__去更新,那么在今后的更新过程中,新老 Vnode 都存在,那么这些新老的 Vnode 是从哪里来的呢?


来看一下 update 的源码

 Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
    ...
    const prevVnode = vm._vnode
    vm._vnode = vnode
    ...
    vm.$el = vm.__patch__(prevVnode, vnode)
  }

可以看到,在更新时,把当前的的 vnode 保存了一份,放在了 preVnode 中。这个就是老的 Vnode,而新的 vnode 是代入的参数


那么新的 Vnode 从哪里来的呢?需不需要再从头开始走一个编译的过程?这样是不是有些耗费时间了?

看一下 Vue 中的解决方案

...
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
    updateComponent = () => {
      ...
      const vnode = vm._render()
     ...
      vm._update(vnode, hydrating)
    }
  }
...

可以看到即将要带入到_update中参与更新的参数,是我们调用_render 方法生成的,这个就是新的 vnode。那么这个_render 方法又是什么?


我们找到 instance/render.js

 Vue.prototype._render = function (): VNode {
...
    try {
      vnode = render.call(vm._renderProxy, vm.$createElement)
    } catch (e) {}
...
    return vnode
  }
  • 可以看到,不管是新的还是旧的 vnode,vnode 总是有代入参数的 render 方法生成,也就是由编译完成的代码字符串代入 new  Function()中生成的函数。
  • render 的前身是代码字符串,会有_c,_v 这些标识。
  • 我们常挂在嘴边的渲染函数,就是这个 creatElement。
  • 将代码字符串代入这个函数creatElement,会调用_c,_v ,_l,_f, _m 等方法去生成 vnode。

 

creatElement 方法:


export function createElement (
  context: Component,
  tag: any,
  data: any,
  children: any,
  normalizationType: any,
  alwaysNormalize: boolean
): VNode | Array<VNode> {
  return _createElement(context, tag, data, children, normalizationType)
}

这个方法最终返回了 Vnode。我们并没有经过组件的编译。说明直接书写渲染函数便可以生成 Vnode,可以节省下来组件编译所应用的时间


当有了新老 Vnode 的时候,我们就可以对这两个新老 vnode 进行 diff和path并进行更新了。接下来会分析 vnode,diff 和 patch 的源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值