vm._render 生成虚拟dom
我们知道在挂载过程中, $mount 会调用 vm._update和vm._render 方法,vm._updata是负责把VNode渲染成真正的DOM,vm._render方法是用来把实例渲染成VNode,这里的_render是实例的私有方法,和前面我们说的vm.render不是同一个,先来看下vm._render定义,vm._render是通过renderMixin(Vue)挂载的,定义在src/core/instance/render.js:
// 简化版本
Vue.prototype._render = function (): VNode {
const vm: Component = this
const { render, _parentVnode } = vm.$options
...
// render self
let vnode
try {
// _renderProxy生产环境下是vm
// 开发环境可能是proxy对象
vnode = render.call(vm._renderProxy, vm.$createElement) // 近似vm.render(createElement)
} catch (e) {...}
// return empty vnode in case the render function errored out
if (!(vnode instanceof VNode)) {
if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) {...}
vnode = createEmptyVNode()
}
// set parent
vnode.parent = _parentVnode
return vnode
}
先缓存vm.$options.render和vm.$options._parentVnode,vm.$options.render是在上节的$mount中通过comileToFunctions方法将template/el编译来的。
vnode = render.call(vm._renderProxy, vm.$createElement)调用了render方法,参数是vm._renderProxy,vm.$createElement
拿到vnode后,判断类型是否为VNode,如果有多个vnode,则是模板上有多个根节点,触发告警。
挂载vnode父节点,最后返回vnode
简要概括,vm._render函数最后是通过render执行了createElement方法并返回vnode;下面就来具体看下vm._renderProxy,vm.$createElement,vnode
vm._renderProxy
首先来看下vm._renderProxy,vm._renderProxy是在_init()中挂载的:
Vue.prototype._init = function (options?: Object) {
...
if (process.env.NODE_ENV !== 'production') {
// 对vm对一层拦截处理,当使用vm上没有的属性时将告警
initProxy(vm)
} else {
vm._renderProxy = vm
}
...
}
如果是生产环境,vm._renderProxy直接就是vm;开发环境下,执行initProxy(vm),找到定义:
initProxy = function initProxy (vm) {
if