# Vue的函数式组件是什么?
Vue 提供了一种称为函数组件的组件类型,用来定义那些没有响应数据,也不需要有任何生命周期的场景,它只接受一些props来显示组件。 特点:
- 无状态:函数式组件本身式没有状态的,也就是没有响应式数据
- 无实例:函数式组件没有实例,也就是没有this上下文
export default {
fuctionl: true,
// Props 是可选的
props: {
// ...
},
// 为了弥补缺少的实例
// 提供第二个参数作为上下文
render: function (createElement, context){
// ...
}
}
# 参数:
- functional: 设置为true,表示该组件为一个函数组件
- props(可选): 传递值到组件内部,2.3.0版本后可以省略,框架会自动将组件上的特性解析为prop
- render函数: 提供渲染函数,来返回一个vnode
# 和正常自定义组件的区别?
- 不维护响应数据
- 无钩子函数
- 没有instance实例
- 在组件内部没有办法像传统组件一样通过this来访问组件属性
- 因为函数式组件精简了很多例如响应式和钩子函数的处理,因此渲染性能会有一定的提高。适用于纯展示且不需要有响应式数据状态的处理的。
# render函数
1. render函数是函数式组件
2. render函数有两个参数,一个是createElement,一个是Context:
- createElemet 是创建虚拟dom的函数
- context 是函数式组件的上下文,它包括:
- - props: 提供所有 prop 的对象
- - children: VNode 子节点的数组
- - slots: 一个函数,返回了包含所有插槽的对象
- - scopedSlots: 一个暴露传入的作用域插槽的对象,也以函数形式暴露普通插槽
- - data: 传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
- - parent: 对父组件的引用
- - listeners: 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名
- - injections: 如果使用了 inject 选项,则该对象包含了应当被注入的属性
由于函数式组件没有创建组件实例,所有传统的通过this来调用的属性,在这里都需要通过context来调用
Vue.compoent('my-fuctional-button', {
functional: true,
render: fuction (createElement, context) {
return createElement('button', context.data, context.children)
}
})
// context 中的 slots() 和 children
// slots 返回的是map化的非作用域插槽,key是slot的名字,value是slot的内容,所有我们可以通过slots().default来调用指定的插槽。
// children 是一个数组,包含了所有的非作用域插槽。所以我们可以很简单的把在所有插槽传递给下一个函数进行处理
<func-comp>
<div slot-scopte="scope">{{ scope.a }}</div>
</func-comp>
Vue.component ('func-comp', {
functional: true,
props: {
name: String
},
render(createElement, context){
return createElement('div', context.data, context.scopedSlots.default({
a:1
}))
}
})
// 显示结果: demo functional component 1
createElement是创建虚拟Dom的函数。此处引入createElement参数:
// @return {VNode}
createElement(
// {String | Object | Function}
// 一个 HTML 标签名、组件选项对象,或者 resolve 了上述任何一种的一个 async 函数。必填项
'div',
// {Object}
// 一个与模板中 attribute 对应的数据对象,可选。
{
// ...
},
// {String | Array}
// 子级虚拟节点(VNode),由'createElement()'构建而成,也可以使用字符串来生成'文本虚拟节点',可选。
[
'先写一些文字',
createElement('h1', '一则头条'),
createElement(MyCompoent, {
props: {
someProp: 'foobar'
}
})
]
)