对变化的总体概述:
- 在 3.x 中,2.x 带来的函数式组件的性能提升可以忽略不计,因此我们建议只使用有状态的组件
- 函数式组件只能由接收
props和context(即:slots、attrs、emit) 的普通函数创建 - 非兼容:
functionalattribute 已从单文件组件 (SFC) 的<template>中移除 - 非兼容:
{ functional: true }选项已从通过函数创建的组件中移除
vue2中函数式组件的定义方式
// 基于render的函数式组件
export default {
functional: true,
props: ['level'],
render(h, { props, data, children }) {
return h(`h${props.level}`, data, children)
}
}
<!-- 结合 <template> 的函数式组件示例 -->
<template functional>
<component
:is="`h${props.level}`"
v-bind="attrs"
v-on="listeners"
/>
</template>
<script>
export default {
props: ['level']
}
</script>
在vue3中,所有的函数式组件都是用普通函数创建的
换句话说,不需要定义{functional:true}组件选项,它将接收两个参数:props和context,context参数是一个对象,包含组件attrs,slots和emit属性,现在不是在render函数中隐式提供h而是全局写入h函数
声明Functional.vue组件(只写js文件也可以)
Function.vue
<script>
import {h} from 'vue'
// vue3中函数式组件只能使用函数的方式声明
function head(props,context) {
console.log(context,'context')
return h(`h${props.level}`,context.attrs,context.clots)
}
//对于属性验证和声明可以通过静态属性的方式来声明
head.props=['level']
export default head
</script>
此时我们可以看到输出的context为

app.vue组件
<template>
<div>
app
<Function level="2">
这是一个动态的元素
</Function>
</div>
</template>
<script>
import Function from "./components/Function.vue"
export default {
components:{
Function
}
}
</script>
此时就可以看到页面加载为

官方建议,非必要情况上,没有必要使用函数式组件
如果需要从vue2的<template>函数式组件迁移到vue3中,直接把组件的template上的functional属性去掉就可以 ,不需要其他额外的操作
<template>
<component
:is="`h${$props.level}`"
v-bind="$attrs"
/>
</template>
<script>
export default {
props:['level']
}
</script>

此时可以看到h2组件渲染到app上
