【Vue.js】从编译过程到渲染函数 h()

61 阅读2分钟

前言:

  • 在绝大多数情况下,Vue 推荐使用模板语法来创建应用。然而在某些使用场景下,我们真的需要用到 JavaScript 完全的编程能力。这时渲染函数就派上用场了。
  • 渲染函数 (h()), HyperScript(). 主要用于处理模板中较难处理的纯 JavaScript 逻辑视图的函数, 把虚拟 DOM 转化成真实 DOM

h 函数工作流程

  1. h 函数( createNodeDescription )
  2. 创建节点函数
  3. vNode(虚拟节点)
  4. 多个vNode组成虚拟DOM树

h 函数处理过程

  1. 模板提供: 组件(模板, 属性, 方法, 指令...)
  2. 编译优化: 编译模板和属性 (AST树 -> 优化) -> VNode (虚拟节点; 虚拟DOM节点是对真实DOM节点的描述)
  3. 更新对比 (AST对象的对比 -> 打补丁(patch) -> 通知更新)

h 函数的使用

参数:

  • 第一个参数: 元素/组件(tag)
  • 第二个参数: {} (options)
  • 第三个参数: children (如果没有options, 则children为第二个参数)

使用注意:

  • 虚拟节点的引用不能重复 (多个child, 不要使用同一个虚拟节点)
  • 使用 resolveComponent(componentName) 在h函数中使用全局组件
  • 局部注册了App, 等价于全局注册 components: { App }

h 函数的高级用法

h 函数中使用 v 自带指令

h 函数中的没有像模板一样的自带指令, 需要用户自己实现这样的逻辑

  • v-if: if (this.isOpened) { retrun h('xxx') } else { return h('xxx') }
  • v-show: style property
  • v-for: (map, filter, ...)
  • v-model: value event onUpdate:value
  • v-on:
    • on: {} (vue2.0)
    • onClick (vue3.0); Vue3中修饰符用大驼峰的方式来写 (详细参考render函数的一章)

h 函数的自定义指令 (resolveDirective & withDirectives)

// h函数的自定义指令 (resolveDirective & withDirectives)

const pin = resolveDirective('pin');

return withDirectives(h('div'), [
  [pin, 200, 'top', { animate: true }]
]);

h 函数中使用插槽 (VNode[])

  • 默认插槽: h('div', { class: 'title' }, this.$slots.default())
  • 具名插槽: h('div', { class: 'title' }, this.$slots.left())
  • 默认内容的插槽 h('div', { class: 'title' }, this.$slots.content({ content: 'xxx' }))

h 函数中使用动态组件

resolveDynamicComponent

h 函数配合 jsx 使用

  1. yarn add @vue/babel-plugin-jsx -D
  2. babel config 配置 plugins