【vue2源码学习】— vm._render

上一篇

我们在分析vue的挂载时
出现了一个vm._render()
接下来我们来看看这个_render函数做了什么
前置知识
在 Vue 的官方文档中介绍了 render 函数的第一个参数是 createElement
https://vuejs.bootcss.com/guide/render-function.html

平时我们更多的是使用template而不是手写render,vue会把template编译成render方法
比如
<div id="app">
  {{ msg }}
</div>
相当于我们编写如下 render 函数:
render: function (createElement) {
  return createElement('div', {
     attrs: {
        id: 'app'
      },
  }, this.msg)
}
// 它用来把实例渲染成一个虚拟 Node。它的定义在 src/core/instance/render.js
  Vue.prototype._render = function (): VNode {
    const vm: Component = this
    const { render, _parentVnode } = vm.$options
    //...
    vm.$vnode = _parentVnode
    // render self
    let vnode
    try {
      // There's no need to maintain a stack because all render fns are called
      // separately from one another. Nested component's render fns are called
      // when parent component is patched.
      currentRenderingInstance = vm
      // option中的 render 函数中的 createElement 方法实际上就是 vm.$createElement 方法
      // vm.$createElement最终是通过执行 createElement 方法
      // 并返回的是 vnode,它是一个虚拟 Node
      vnode = render.call(vm._renderProxy, vm.$createElement)
    } catch (e) {
      handleError(e, vm, `render`)
      // return error render result,
      // or previous vnode to prevent render error causing blank component
      /* istanbul ignore else */
      if (process.env.NODE_ENV !== 'production' && vm.$options.renderError) {
       	// 省略
      } else {
        vnode = vm._vnode
      }
    } finally {
      currentRenderingInstance = null
    }
    // if the returned array contains only a single node, allow it
    if (Array.isArray(vnode) && vnode.length === 1) {
      vnode = vnode[0]
    }
    // return empty vnode in case the render function errored out
    if (!(vnode instanceof VNode)) {
      vnode = createEmptyVNode()
    }
    // set parent
    vnode.parent = _parentVnode
    return vnode
  }
vm.$createElement 方法定义是在执行 initRender 方法的时候,
可以看到除了 vm.$createElement 方法,还有一个 vm._c 方法,
它是被模板编译成的 render 函数使用,
而 vm.$createElement 是用户手写 render 方法使用的,
这俩个方法支持的参数相同,并且内部都调用了 createElement 方法。

//src\core\instance\render.js
export function initRender (vm: Component) {
  // ...
  // bind the createElement fn to this instance
  // so that we get proper render context inside it.
  // args order: tag, data, children, normalizationType, alwaysNormalize
  // internal version is used by render functions compiled from templates
  vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
  // normalization is always applied for the public version, used in
  // user-written render functions.
  vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
  //...
}
总结
vm._render 方法最终是通过调用 createElement 返回的是 vnode(虚拟 Node)

下一篇

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值