9.render helper
render helper
什么是 render helper
在 编译器 中我们说到,编译器最后会生成渲染函数。组件更新时,执行渲染函数,就可以得到组件的 vnode。
渲染函数之所以能生成 vnode 是通过其中的 _c、_l、_v、_s
等方法实现的,在 编译后 的代码中我们能看到很多类似函数的调用
- 普通的节点被编译成了可执行 _c 函数
- v-for 节点被编译成了可执行的 _l 函数
- …
作用总结:在 Vue 实例上挂载一些运行时的工具方法,这些方法用在编译器生成的渲染函数中,用于生成组件的 VNode。
入口
Vue 实例的入口文件(2-Vue初始化过程),包括 Vue 构造函数的定义、各个实例方法的初始化。
1 |
|
1 |
|
初始化时调用了 renderMixin,renderMixin 中调用了 Install RenderHelpers 挂载一些工具方法,也就是 _o _c 等等
installRenderHelpers
1 |
|
面试题
一个组件是如何变成 VNode?
- 组件实例初始化,最后执行 $mount 进入挂载阶段
- 如果是只包含运行时的 vue.js,则直接进入挂载阶段,因为这时候的组件已经变成了渲染函数,编译过程通过模块打包器 + vue-loader + vue-template-compiler 完成的
- 如果没有使用预编译,则必须使用全量的 vue.js
- 挂载时如果发现组件配置项上没有 render 选项,则进入编译阶段
- 将模版字符串编译成 AST 语法树,其实就是一个普通的 JS 对象
- 然后优化 AST,遍历 AST 对象,标记每一个节点是否为静态静态;然后再进一步标记出静态根节点,在组件后续更新时会跳过这些静态节点的更新,以提高性能
- 接下来从 AST 生成渲染函数,生成的渲染函数有两部分组成:
- 负责生成动态节点 VNode 的 render 函数
- 还有一个 staticRenderFns 数组,里面每一个元素都是一个生成静态节点 VNode 的函数,这些函数会作为 render 函数的组成部分,负责生成静态节点的 VNode
- 接下来将渲染函数放到组件的配置对象上,进入挂载阶段,即执行 mountComponent 方法
- 最终负责渲染组件和更新组件的是一个叫 updateComponent 方法,该方法每次执行前首先需要执行 vm._render 函数,该函数负责执行编译器生成的 render,得到组件的 VNode
- 将一个组件生成 VNode 的具体工作是由 render 函数中的
_c、_o、_l、_m
等方法完成的,这些方法都被挂载到 Vue 实例上面,负责在运行时生成组件 VNode
下面说的有点多,其实记住一句就可以了,设置组件配置信息,然后通过
new VNode(组件信息)
生成组件的 VNode
- _c,负责生成组件或 HTML 元素的 VNode,_c 是所有 render helper 方法中最复杂,也是最核心的一个方法,其它的 _xx 都是它的组成部分
- 接收标签、属性 JSON 字符串、子节点数组、节点规范化类型作为参数
- 如果标签是平台保留标签或者一个未知的元素,则直接
new VNode(标签信息)
得到 VNode - 如果标签是一个组件,则执行 createComponent 方法生成 VNode
- 函数式组件执行自己的 render 函数生成 VNode
- 普通组件则实例化一个 VNode,并且在在 data.hook 对象上设置 4 个方法,在组件的 patch 阶段会被调用,从而进入子组件的实例化、挂载阶段,然后进行编译生成渲染函数,直至完成渲染
- 当然生成 VNode 之前会进行一些配置处理比如:
- 子组件选项合并,合并全局配置项到组件配置项上
- 处理自定义组件的 v-model
- 处理组件的 props,提取组件的 props 数据,以组件的 props 配置中的属性为 key,父组件中对应的数据为 value 生成一个 propsData 对象;当组件更新时生成新的 VNode,又会进行这一步,这就是 props 响应式的原理
- 处理其它数据,比如监听器
- 安装内置的 init、prepatch、insert、destroy 钩子到 data.hooks 对象上,组件 patch 阶段会用到这些钩子方法
- _l,运行时渲染 v-for 列表的帮助函数,循环遍历 val 值,依次为每一项执行 render 方法生成 VNode,最终返回一个 VNode 数组
- _m,负责生成静态节点的 VNode,即执行 staticRenderFns 数组中指定下标的函数
参考
9.render helper
http://example.com/2022/10/26/9-render-helper/