render的方法解析——Vue源码解析
关于渲染函数的解释
render的方法解析——Vue源码解析
关于渲染函数的解释
Vue 的 _render
方法是实例的一个私有方法,它用来把实例渲染成一个虚拟 Node
。
首先_render
方法是在初始化的时候文件src/core/instance/index.js
Vue初始化的文件中定义的。
initMixin(Vue) stateMixin(Vue) eventsMixin(Vue) lifecycleMixin(Vue) renderMixin(Vue)
代码 1.1
其中代码 1.1
中的renderMixin
初始化对应的文件 src/core/instance/render.js
文件中Vue.prototype._render
方法是本次分析的重点
我们一起来看看这段代码:
Vue.prototype._render = function (): VNode { const vm: Component = this const { render, staticRenderFns, _parentVnode } = vm.$options if (vm._isMounted) { // if the parent didn't update, the slot nodes will be the ones from // last render. They need to be cloned to ensure "freshness" for this render. for (const key in vm.$slots) { const slot = vm.$slots[key] if (slot._rendered) { vm.$slots[key] = cloneVNodes(slot, true /* deep */) } } } vm.$scopedSlots = (_parentVnode && _parentVnode.data.scopedSlots) || emptyObject if (staticRenderFns && !vm._staticTrees) { vm._staticTrees = [] } // set parent vnode. this allows render functions to have access // to the data on the placeholder node. vm.$vnode = _parentVnode // render self let vnode try { vnode = render.call(vm._renderProxy, vm.$createElement) } catch (e) { handleError(e, vm, `render function`) // return error render result, // or previous vnode to prevent render error causing blank component /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { vnode = vm.$options.renderError ? vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e) : vm._vnode } else { vnode = vm._vnode } } // return empty vnode in case the render function errored out if (!(vnode instanceof VNode)) { if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) { warn( 'Multiple root nodes returned from render function. Render function ' + 'should return a single root node.', vm ) } vnode = createEmptyVNode() } // set parent vnode.parent = _parentVnode return vnode }
代码 1.2
我们可以看到很多关于$scopedSlots
、$slots
、$options
等,后续会分析各自的意义。本次主要看代码片段1.3中
const { render, staticRenderFns, _parentVnode } = vm.$options
代码 1.3
其中render
是从vm.$options
中获取。具体vm.$options
中如何定义,可以自行查看初始化的而过程。
之后代码会执行到vnode = render.call(vm._renderProxy, vm.$createElement)
的片段
vm._renderProxy 是什么?
这是最为关键的两个参数,前面已经分析过了vm._renderProxy
分为2个方式,生产环境下就是vm
的意思,如果是开发环境则是 如下代码片段src/core/instance/init.js
中
/* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { initProxy(vm) } else { vm._renderProxy = vm }
代码 1.4
可以看到initProxy
就是在开发环境才会进入使用。然后可以进入代码片段分析src/core/instance/proxy.js
中。最终主要就是在开发环境中,提前报出一些常见错误,基本都是 在这里报出的,比如模版参数不正确等。
vm.$createElement 是什么
我们可以看到render.js
文件中的最开始的定义 方法initRender
这个是在初始化的时候调用的。
可以看到预定义的几个静态变量
const parentVnode = vm.$vnode = vm.$options._parentVnode // the placeholder node in parent tree const renderContext = parentVnode && parentVnode.context
代码 1.5
其实就是获取父节点和文本的对象,再往下查看代码
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)
代码 1.6
上面的两行代码都是使用了createElement
的方法。
区别就在于,前者是给有编译环境下使用的render方法,后者是给手写render方法使用的
这篇主要介绍到这里。关于createElement参数可以查看官网createElemnt
vm._render
最终是通过执行 createElement
方法并返回的是 vnode
,它是一个虚拟 Node
。Vue 2.0 相比 Vue 1.0 最大的升级就是利用了 Virtual DOM
。因此在分析 createElement
的实现前,我们先了解一下 Virtual DOM
的概念
您的鼓励是我前进的动力---
使用微信扫描二维码完成支付