Vue 3 | 函数式组件变形记
开门见山
从上帝视角看一下发生了什么:
-
官方团队宣称,Vue 3 中函数式组件的性能提升微乎其微(与 Vue 2.x 相比),所以建议直接使用常规组件就好。 -
如果想创建一个函数式组件,写一个接收 props
和context
的普通函数就可以了。 -
废弃:单文件组件(SFC)中 <template>
的functional
属性被干掉了。 -
废弃:通过给 Render 函数传递 { functional: true }
以创建函数式组件的方式也被废弃了。
事情是这样的...
在 Vue 2.x 的版本中,函数式组件主要有以下两个使用场景:
-
因为函数式组件的初始化和渲染都很快(快过常规组件),所以通常作为一种提升性能的角色出现 -
用来返回多个根节点
然而,在 Vue 3 中,常规组件的性能有了很大提升,相比之下,这时的函数式组件在性能上失去了以往的优势。另外,现在的常规组件也支持返回多个根节点了。因此,函数式组件仅剩的唯一用途就是用来实现简单组件了,比如一个动态生成不同标题的组件(市场被挤压,好可怜)。
2.x 版本是这样的
就用上面提到的例子,那个动态生成不同标题的组件:
// Vue 2 函数式组件
export default {
functional: true,
props: [level],
render(h, { props, data, children }) {
return h(`h${props.level}`, data, children);
}
}
也可以采用 <template>
函数式组件的方式去写:
// Vue 2 用模版实现的函数式组件
<template>
<component :is="`h${props.level}`"/>
</template>
<script>
export default {
props: ['level'],
}
</script>
3.x 安利时刻
在 Vue 3 中,只要是通过普通函数创建的组件,都是函数式组件,也不用传递之前那个 { functional: true }
的参数了。
函数会接受两个参数:props
和 context
。前者不用说了,后者包含了组件的 attrs
、slots
和 emit
等属性。
此外,之前也有提到,h
也不再作为函数的参数了,需要手动从全局引入。
各位观众!现在把上面那个例子改写成 Vue 3 的写法:
import { h } from 'vue';
const DynamicHeading = (props, context) => {
return h(`h${props.level}`, context.attrs, context.slots);
}
DynamicHeading.props = ['level'];
export default DynamicHeading;
还有一件非常幸福的事情:如果我们需要从 Vue 2 的 <template>
函数式组件迁移到 Vue 3,直接把组件的 functional
属性去掉就好了,不需要其他额外的操作。
“如果你想获得关于 Vue 3 函数式组件的更多信息,请访问:https://v3.vuejs.org/guide/migration/functional-components.html#components-created-by-functions(目前还没有中文本)。