Vue提供了一种称为函数式组件的组件类型,用来定义那些没有响应数据,也不需要有任何生命周期的场景,它只接受一些props来显示组件。
什么是函数组件?
把函数式组件想象成组件里的一个函数,入参是渲染上下文(render context),返回值是渲染好的HTML(即render中定义的内容)。 对于函数式组件,可以定义:
- Stateless(无状态):组件自身没有状态
- Instanceless(无实例):组建自身没有实例,即没有this
由于函数式组件有这两个特性,就可以把他用作高阶组件。(高阶组件:可以生成其他组件的组件。)
1、使用方法
在.js文件中,/创建一个名为FunctionButton.js的函数式组件:
export default {
name: 'functional-button',
functional: true,
render(createElement, context) {
return createElement('button', 'click me')
}
}
函数式组件没有this,参数就是靠context来传递
Render context
- props:提供所有的prop对象
- children:VNode子节点的数组
- slots:一个函数,返回了包含所有插槽的对象
- scopedSlots: (2.6.0+)一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽
- parent:对父组件的引用
- listeners:包含了所有父组件为当前组件注册的事件监听的对象。是data.on的别名
- injections:如果使用了inject选项,则该对象包含了应当被注入的属性;
- data(包含了其他属性的引用,nibility):传递给组件的整个数据对象,作为createElement的第二个参数传入组件
2、引用
app.vue中引入上面的函数式组件:
<template>
<FunctionalButton>
click me
</FunctionButton>
</template>
上面的click me就是FunctionButton.js的children属性了,可以在render中改造context(上下文),由.vue来定义组件的button按钮
render(createElement, { children }) {
// context用于传递上下文,包括了children属性
return createElement('button', children)
}
3、事件定义
函数式组件没有实例,事件只能由父组件传递
<template>
<FunctionalButton @click="log">
Click me
</FunctionalButton>
</template>
FunctionButton.js:
render(createElement, { props, listeners, children }) {
return createElement(
'button',
{
attrs: props,
// createElement中click事件对应的事件属性就是on
on: {
click: listeners.click
}
},
children
);
}
上面涉及到的props、listeners要传递很多,可以统一把这个属性集成在data中,可改成:
render(createElement, { data, children }) {
return createElement( 'button', data, children );
}
通过向createElement传入context.data作为第二个参数,就把子组件上的所有attribute和事件监听都传递下去了。
eg:自带hello的button按钮
createElement('button', data, ['hello', ...children])