从Vue 2到Vue 3的迁移指南之破坏性特性(五、函数式组件)

452 阅读1分钟

1、内容系个人翻译自 Vue 3.0 Beta 版文档中 Migration From Vue 2 章节
2、不一定准确,欢迎交流(别人都翻过几百遍了吧,再说也没人看)
3、水平有限、随时太监

· 从Vue 2到Vue 3的迁移指南之破坏性特性(一、全局API)
· 从Vue 2到Vue 3的迁移指南之破坏性特性(二、全局API的tree-shaking)
· 从Vue 2到Vue 3的迁移指南之破坏性特性(三、v-model)
· 从Vue 2到Vue 3的迁移指南之破坏性特性(四、渲染函数API)

函数式组件

概览

这些变化可以概括为:

  • 函数式组件在 2.x 中所提升的性能在 3.x 中已经是微不足道的了,所以我们推荐仅适用有状态组件

  • 函数式组件现在只能通过使用一个接受了 propscontext(包含了 slotsattrsemit) 的简单函数去创建

  • 破坏性的: 单文件组件中 <template>functional 属性已移除

  • 破坏性的: 创建组件的函数中,{ functional: true } 选项已移除

获取更多信息,请继续阅读!

介绍

在 Vue 2 中,函数式组件主要有两种使用场景:

  • 作为一种性能优化方式,因为它初始化会比有状态的组件更快
  • 返回多个根节点

然而,在 Vue 3 中,有状态组件的性能已经优化到跟前者几乎没区别,除此之外,有状态组件现在也具有返回多个根节点的功能。

结果上看,函数式仅存的作用就是创建一个简单组件,比如创建一个具有动态标题(heading)的组件,除此之外,我们都推荐您像通常情况那样使用有状态组件。

2.x 语法

在 2.x 中,如果我们要使用一个可以动态生成合适标题(heading)(包含了 h1h2h3 等)的 <dynamic-heading> 组件时,用单文件组件我们可以这么写:

// Vue 2 函数式组件例子
export default {
  functional: true,
  props: ['level'],
  render(h, { props, data, children }) {
    return h(`h${props.level}`, data, children)
  }
}

又或者有人更喜欢在单文件组件里面用 <template>

// Vue 2 使用<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 属性的对象。

除此之外,现在 h 需要全局导入,而不是隐式地在 render 函数中提供。

拿前面的 <dynamic-heading> 组件来说,现在是这样的:

import { h } from 'vue'

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

DynamicHeading.props = ['level']

export default DynamicHeading

单文件组件 (SFCs)

3.x 中,有状态组件与函数式组件之间的性能差异已经大幅度减少了,在绝大部分场景中都可以忽略不计。从结果上看,在单文件组件上使用 functional 的开发者只需要把标记去掉即可完成迁移,无需进行其他工作。

拿前面的 <dynamic-heading> 组件来说,现在是这样的:

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

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

主要不同点:

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

后续

获取更多关于函数式组件的用法以及渲染函数的变化,请参阅: