跳至内容

功能组件
重大变更

概述

就变更而言,从高层次来看

  • 功能组件在 3.x 中的性能提升与 2.x 相比已微不足道,因此我们建议直接使用有状态组件
  • 功能组件只能使用接收 propscontext(即 slotsattrsemit)的普通函数创建
  • 重大变更: functional 属性在单文件组件 (SFC) <template> 上已移除
  • 重大变更: { functional: true } 选项在由函数创建的组件中已移除

有关更多信息,请继续阅读!

简介

在 Vue 2 中,功能组件有两个主要用例

  • 作为性能优化,因为它们比有状态组件初始化得快得多
  • 返回多个根节点

但是,在 Vue 3 中,有状态组件的性能已得到提升,以至于差异微不足道。此外,有状态组件现在还包括返回多个根节点的能力。

因此,功能组件的唯一剩余用例是简单组件,例如用于创建动态标题的组件。否则,建议像往常一样使用有状态组件。

2.x 语法

使用 <dynamic-heading> 组件,该组件负责渲染出适当的标题(即 h1h2h3 等),这可以在 2.x 中作为单文件组件编写为

js
// Vue 2 Functional Component Example
export default {
  functional: true,
  props: ['level'],
  render(h, { props, data, children }) {
    return h(`h${props.level}`, data, children)
  }
}

或者,对于那些更喜欢单文件组件中的 <template> 的人

vue
<!-- Vue 2 Functional Component Example with <template> -->
<template functional>
  <component
    :is="`h${props.level}`"
    v-bind="attrs"
    v-on="listeners"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>

3.x 语法

由函数创建的组件

现在在 Vue 3 中,所有功能组件都是使用普通函数创建的。换句话说,无需定义 { functional: true } 组件选项。

它们将接收两个参数:propscontextcontext 参数是一个包含组件的 attrsslotsemit 属性的对象。

此外,与在 render 函数中隐式提供 h 不同,h 现在是全局导入的。

使用前面提到的 <dynamic-heading> 组件示例,以下是它现在的外观。

js
import { h } from 'vue'

const DynamicHeading = (props, context) => {
  return h(`h${props.level}`, context.attrs, context.slots)
}

DynamicHeading.props = ['level']

export default DynamicHeading

单文件组件 (SFC)

在 3.x 中,有状态组件和功能组件之间的性能差异已大幅减少,在大多数用例中将微不足道。因此,使用 functional 在 SFC 上的开发人员的迁移路径是移除属性并将所有对 props 的引用重命名为 $props,并将所有对 attrs 的引用重命名为 $attrs

使用我们之前提到的 <dynamic-heading> 示例,以下是它现在的外观。

vue
<template>
  <component
    v-bind:is="`h${$props.level}`"
    v-bind="$attrs"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>

主要区别在于

  1. functional 属性已从 <template> 上移除
  2. listeners 现在作为 $attrs 的一部分传递,可以移除

下一步

有关新功能组件的用法以及对渲染函数的总体变更的更多信息,请参阅