关于vue渲染函数的一些不得不说的API

53 阅读3分钟

前言:关于什么是渲染函数,什么是h()这些东西我就不说了,以及h函数里面的各种参数,在Vue官网中都有详细解释,这篇文章主要针对Vue3渲染函数中的一些api结合自己的开发经验进行叙述

mergeProps()

主要合并classstyle事件监听多个同名的事件监听器将被合并到一个数组) 顾名思义,合并props,为什么要合并props?当然是因为小孩子才做选择,成年人都要!

import { mergeProps } from 'vue'

const one = {
  class: 'foo',
  onClick: handlerA
}

const two = {
  class: { bar: true },
  onClick: handlerB
}

const merged = mergeProps(one, two)
// 合并后 ↓
// 拥有了两个class的样式,一个onClick可以做两件事
/**
 {
   class: 'foo bar',
   onClick: [handlerA, handlerB]
 }
 */

cloneVNode()

顾名思义,克隆虚拟节点返回一个克隆的 vnode,可在原有基础上添加一些额外的 prop

// 类型定义:
function cloneVNode(vnode: VNode, extraProps?: object): VNode

// 示例:
import { h, cloneVNode } from 'vue'

const original = h('div')
const cloned = cloneVNode(original, { id: 'foo' }) // 克隆一个有额外prop的节点

isVNode()

判断一个值是否为 vnode 类型,返回一个Boolean

resolveComponent()

按名称手动解析已注册的组件。

此方法只针对无法通过引入vue文件的方法来获取组件的情况,什么时候我们没办法通过引入vue文件的方法获取到组件呢?请看如下示例:

// 全局注册组件
Vue.component('GlobalComponent', {
  template: '<div>Global Component</div>'
})

// 渲染函数
function render() {
  const component = resolveComponent('GlobalComponent')
  return h(component)
}

在上述示例中,我们在全局注册了一个组件 GlobalComponent,但我们无法通过直接导入的方式在渲染函数中使用它。因此,我们使用 resolveComponent('GlobalComponent')获取组件定义,并将其传递给 h() 函数进行渲染。

备注:如果你可以直接引入组件就不需使用此方法。

为了能从正确的组件上下文进行解析,resolveComponent() 必须在setup() 或渲染函数内调用。

如果组件未找到,会抛出一个运行时警告,并返回组件名字符串。

resolveDirective()

按名称手动解析已注册的指令。

function resolveDirective(name: string): Directive | undefined

备注:如果你可以直接引入组件就不需使用此方法。

以下是无法通过导入指令的方式进行手动获取指令的情况:

import { h, withDirectives, resolveDirective } from 'vue'

// 自定义指令的名称注册
Vue.directive('my-directive', {
  mounted(el, binding) {
    // 指令逻辑
  },
  updated(el, binding) {
    // 指令逻辑
  }
})

// 渲染函数
function render() {
  const directive = resolveDirective('my-directive')
}

在上述示例中,我们通过名称注册了一个自定义指令 my-directive,但无法通过直接导入的方式在渲染函数中使用它。为了解决这个问题,我们使用 resolveDirective('my-directive') 来获取指令定义 为了能从正确的组件上下文进行解析,resolveDirective() 必须在setup() 或渲染函数内调用。

如果指令没有找到,会抛出一个运行时警告,并返回 undefined

withDirectives()

用于给 vnode 增加自定义指令

类型:

function withDirectives(
  vnode: VNode,
  directives: DirectiveArguments
): VNode

// [Directive, value, argument, modifiers]
type DirectiveArguments = Array<
  | [Directive]
  | [Directive, any]
  | [Directive, any, string]
  | [Directive, any, string, DirectiveModifiers]
>

用自定义指令包装一个现有的 vnode。第二个参数是自定义指令数组。每个自定义指令也可以表示为 [Directive, value, argument, modifiers] 形式的数组。如果不需要,可以省略数组的尾元素。

示例:

// <div v-pin:top.animate="200"></div> 
const vnode = withDirectives(h('div'), [ [pin, 200, 'top', { animate: true }] ])

withModifiers()

用于向事件处理函数添加内置 v-on 修饰符

类型:

function withModifiers(fn: Function, modifiers: string[]): Function

示例:

const vnode = h('button', { 
// 等价于 v-on:click.stop.prevent
onClick: withModifiers(() => {
// ... 
}, ['stop', 'prevent']) })

一些要点

v-model 指令扩展为 modelValue 和 onUpdate:modelValue

诸如 <KeepAlive><Transition><TransitionGroup><Teleport> 和 <Suspense> 等内置组件在渲染函数中必须导入才能使用

渲染函数中v-if:

// 判断必须是响应式依赖
h('div', [ok.value ? h('div', 'yes') : h('span', 'no')])