什么是函数式组件?
我们可以把函数式组件想象成组件里的一个函数,入参是渲染上下文(render context),返回值是渲染好的HTML
对于函数式组件,可以这样定义:
- Stateless(无状态):组件自身是没有状态的
- Instanceless(无实例):组件自身没有实例,也就没有this
由于函数式徐建拥有拥有这两个特性,我们就可以把它用作高阶组件(High order components),所谓高阶,就是可以生成其他组件的组件。
函数式组件的特点
- 没有管理任何状态
- 没有监听任何传递给它的状态
- 没有生命周期方法
- 只接收一些prop的函数
函数式组件的优点
渲染开销低,因为函数式组件只是函数
为什么要使用函数式组件
速度快
因为函数式组件没有状态,所以我们不需要像vue的响应式 系统一样需要经过额外的 初始化。
函数式组件任然会对响应的变化 做出响应式变化,比如新传入props,但是在组件本身中,它无法知道数据什么时候发生变化,因为它不维护自身状态。
对于大型应用程序,在使用函数式组件之后,你会看到DOM的渲染和更新会有很大的改进。
函数式组件的适用场景
函数式组件可能不适用很多情况。因为使用JavaScript框架的目的是构建响应式的应用程序
适用场景:
- 一个简单的展示组件,也就是所谓的dumb组件,例如button组件,pills,tags,cards,甚至整个页面都是静态文本,比如about页面
- “高阶组件”用于接收一个组件作为参数,返回一个被包装过的组件
- v-for循环中每项通常都是很好的候选项。
functional:true加上render function,就是一个简单的函数式组件了
demo:
创建一个的函数式组件:
export default {
name: 'functional-button',
functional: true,
render(createElement, context) {
return createElement('button', 'click me')
}
}
函数式组件没有this,参数就靠context来传递
context的属性:
- props
- children
- slots(a slots object)
- parent
- listeners
- injections
- data
其中上面的data包含了其他属性的引用,nibility。
现在创建一个来引入上面的函数式组件
<template>
<FunctionalButton>
click me
</FunctionButton>
</template>
上面的click me就是的children属性,我们可以把组件改造下,有来定义组件的button按钮
export default {
name: 'funtional-button',
functional: true,
render(createElement, { children }) {
return createElement('button', children)
}
}
上面用了ES6参数的解构,用{children}来代替context
事件定义
函数式组件没有实例,事件只由父组件传递。下面在上定义一个最简单的click事件。
<template>
<FunctionalButton @click="log">
Click me
</FunctionalButton>
</template>
对应的
export default {
functional: true,
render(createElement, { props, listeners, children }) {
return createElement(
'button',
{
attrs: props,
on: {
click:
}
},
children
);
}
};
简单写法
vue中设计的api比较人性化,我们可以将props、listeners统一集中在data中。
export default {
functional: true,
render(createElement, { data, children }) {
return createElement( 'button', data, children );
}
};
createElement('button', data, ['hello', ...children])