# Render
打开mysrc/core/instance/render.js
Vue.prototype._render = function () {
const vm = this
const { render, _parentVnode } = vm.$options
// set parent vnode. this allows render functions to have access
// to the data on the placeholder node.
vm.$vnode = _parentVnode
// render self
let vnode
// 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
vnode = render.call(vm._renderProxy, vm.$createElement)
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
}
在_render方法内部调用了options.render方法。回想一下render的使用方式:
render: function (h) {
return h('div', {
attrs: {
id: 'mydiv'
},
})
}
所以h就是执行的vm.$createElement方法。即便没有使用render,而是写成模板形式,最终也会编译成render函数的形式:
<div id="myapp">{{...}}</div>
// 编译之后
var render = function() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c("div", { attrs: { id: "mydiv" } })
}
var staticRenderFns = []
render._withStripped = true
export { render, staticRenderFns }
继续再mysrc/core/instance/render.js文件中找到vm.$createElement的定义
export function initRender (vm) {
vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
}
可以看到在initRender方法里对实例扩展了_c和$createElement两个方法,_c是被模板编译成的 render 函数使用的,$createElement是用户手写 render 方法使用的。这两个方法内部都是调用了createElement方法。