函数式组件特点:
- 没有管理任何状态
- 没有监听任何传递给它的状态
- 没有生命周期方法
- 它只是接收一些
prop
的函
我们将这样的组件标记为functional
:
- 无状态 == 无响应式数据
- 无实例 == 无
this
上下文
函数式组件的优点:
- 渲染开销低,因为函数式组件只是函数;
函数式组件基本写法:
{
functional: true,
// Props 是可选的
props: {
// ...
},
// 为了弥补缺少的实例
// 提供第二个参数作为上下文
render: function (createElement, context) {
// ...
}
}
组件需要的一切都是通过 context
参数传递,它是一个包含如下字段的对象:
props
: 提供所有prop
的对象
children:VNode
子节点的数组
slots
: 一个函数,返回了包含所有插槽的对象
scoptedSlots
:(2.6.0) 一个暴露传入的作用域插槽的对象,也以函数形式暴露普通插槽
data
:传递个组件的整个数据对象,作为createElement
的第二个参数传入组件
parent
:对父组件的引用
listeners
:(2.3.0+) 一个包含了:所有父组件为当前组件祖册的事件监听器对象,是data.on
的一个别名
injections
:(2.3.0+) 如果使用了inject
选项,则改对象包含了:应当被注入的属性;
使用场景1:包装组件
程序化地在多个组件中选择一个来代为渲染;
在将 children
、props
、data
传递给子组件之前操作它们;
下面是一个 smart-list
组件的例子,它能根据传入 prop
的值来代为渲染更具体的组件:
var EmptyList = { /* ... */ }
var TableList = { /* ... */ }
var OrderedList = { /* ... */ }
var UnorderedList = { /* ... */ }
Vue.component('smart-list', {
functional: true,
props: {
items: {
type: Array,
required: true
},
isOrdered: Boolean
},
render: function (createElement, context) {
function appropriateListComponent () {
var items = context.props.items
if (items.length === 0) return EmptyList
if (typeof items[0] === 'object') return TableList
if (context.props.isOrdered) return OrderedList
return UnorderedList
}
return createElement(
appropriateListComponent(),
context.data,
context.children
)
}
})
slots()
和children
的对比
children
,可以获取当前组件节点的所有的子节点;
slots()
函数返回了所有的插槽对象;
举例:
<my-functional-component>
<p v-slot:foo>
first
</p>
<p>second</p>
</my-functional-component>
对于以上示例组件:
children
会给你两个段落标签;
slots().default
只会传递第二个匿名段落标签
slots().foo
会传递第一个具名段落标签
总结:
你可以选择使用slots()
让组件感知某个插槽机制,也可以简单地通过传递 children
,移交给其它组件去处理