函数式组件
定义
在 Vue 中,常规组件通常是用选项对象来定义的,例如:
ts
export default {
props: { msg: String },
setup(props) {
return () => h('div', props.msg)
}
}
export default {
props: { msg: String },
setup(props) {
return () => h('div', props.msg)
}
}而函数式组件则不是一个对象,而是一个普通函数:
ts
const MyComp = (props) => {
return h('div', props.msg)
}函数式组件是一种定义自身没有任何状态的组件的方式。它们很像纯函数:接收 props,返回 vnodes。
函数式组件在渲染过程中不会创建组件实例 (也就是说,没有 this),也不会触发常规的组件生命周期钩子。
ts
function MyComponent(props, { slots, emit, attrs }) {
// ...
}配置
大多数常规组件的配置选项在函数式组件中都不可用,除了 props 和 emits。我们可以给函数式组件添加对应的属性来声明它们:
ts
MyComponent.props = ['value']
MyComponent.emits = ['click']如果这个 props 选项没有被定义,那么被传入函数的 props 对象就会像 attrs 一样会包含所有 attribute。除非指定了 props 选项,否则每个 prop 的名字将不会基于驼峰命名法被一般化处理。
对于有明确 props 的函数式组件,attribute 透传的原理与普通组件基本相同。然而,对于没有明确指定 props 的函数式组件,只有 class、style 和 onXxx 事件监听器将默认从 attrs 中继承。在这两种情况下,可以将 inheritAttrs 设置为 false 来禁用属性继承:
ts
MyComponent.inheritAttrs = false函数式组件可以像普通组件一样被注册和使用。如果你将一个函数作为第一个参数传入 h,它将会被当作一个函数式组件来对待。
标注类型
具名函数式组件
ts
import type { SetupContext } from 'vue'
type FComponentProps = {
message: string
}
type Events = {
sendMessage(message: string): void
}
function FComponent(
props: FComponentProps,
context: SetupContext<Events>
) {
return (
<button onClick={() => context.emit('sendMessage', props.message)}>
{props.message} {' '}
</button>
)
}
FComponent.props = {
message: {
type: String,
required: true
}
}
FComponent.emits = {
sendMessage: (value: unknown) => typeof value === 'string'
}匿名函数式组件
ts
import type { FunctionalComponent } from 'vue'
type FComponentProps = {
message: string
}
type Events = {
sendMessage(message: string): void
}
const FComponent: FunctionalComponent<FComponentProps, Events> = (
props,
context
) => {
return (
<button onClick={() => context.emit('sendMessage', props.message)}>
{props.message} {' '}
</button>
)
}
FComponent.props = {
message: {
type: String,
required: true
}
}
FComponent.emits = {
sendMessage: (value) => typeof value === 'string'
}