Vue 3.0的Composition API跟React的Hooks非常相似,其目标都是提供一种更为内聚的组件间的逻辑复用方式,以解决过往的相关逻辑分散在组件各处导致复用与维护困难的问题。但是在实际使用的层面上两者又有一定的区别,而这是基于两个框架实现思路的差异,Vue的核心是数据响应式而React的核心是函数式。
setup(props, context)
Vue3.0当中,组件的形式仍然是一个对象,只不过对象提供了一个新的setup方法,在这个方法当中,可以利用Composition API实现Vue2.0组件所具备的几乎所有的功能。
这个方法接收两个参数props和context,前者是组件参数,而后者则包括了attrs、slots、emit这三个常用API。
props
props最值得关注的一点就是不要使用解构赋值来获取props中的属性。与React函数组件每次渲染都会执行一遍函数不同,每个组件的setup方法只会执行一遍,所以如果使用解构赋值意味着之后将不会监听到props相关属性的变化。以下面为例:
<script>export default {name: 'HelloWorld',props: {msg: String},setup(props) {const {msg} = propsreturn () => {return <div>{props.msg}</div>}}}</script>
上面的代码在vue-cli会直接报错,警告值会发生丢失。如果要使用解构赋值,则需要先将props通过toRefs进行转换。
const {msg} = toRefs(props)
toRefs的作用就是对一个响应式对象进行转换普通对象,但是这个普通对象的每个key都是一个ref引用。
除此之外,对于可选属性来说,较为保险的做法是使用 toRef(props, 'key') 的做法来获取值,因为直接使用 toRefs(props) 进行解构赋值可能会得到undefined的结果。
context
context包括attrs, slots与emit三个属性。
与props不同的是,attrs跟slots不是响应式(reactive)对象,所以不能使用toRefs来进行结构赋值,只能通过直接访问其属性
this
由于setup是在created之前执行,此时组件实例还没实例化完成,所以setup无法通过this来获取到组件实例。
可有时候我们必须要获取到当前实例(如获取父组件信息),为了解决这一问题,Vue3.0提供getCurrentInstance来访问当前实例,这个函数只能在setup和生命周期函数中生效,其余地方需要通过现在setup或生命周期中执行,然后再进行访问。
模板与渲染函数
与Vue2.0相同,在Vue3.0当中同样有模板和渲染函数两种方式来描述组件结构。
若要在Composition API使用模板,则需要将模板用到的变量作为setup方法的返回值。
如果使用渲染函数,则需要将渲染函数作为setup方法的返回值。
值得注意的是如果使用模板,则无需通过 .value 来访问ref值,vue会帮你自动处理,而渲染函数则不行。
对于使用模板的用户来说,模板的一个很主要的缺点就是需要一个个地将用到的变量写入到setup的返回值当中,而渲染函数中使用JSX则不会有这个问题。
生命周期
这部分值得说的地方不多,处理beforeCreate和created两个方法以外,其他生命周期都能通过引入对应的函数来进行定义,这所以这样做是因为setup就是在这两个生命周期之间进行的,所以如果要执行某些动作,只需要在setup中执行即可。
| Options API | Hook inside setup |
|---|---|
beforeCreate |
Not needed* |
created |
Not needed* |
beforeMount |
onBeforeMount |
mounted |
onMounted |
beforeUpdate |
onBeforeUpdate |
updated |
onUpdated |
beforeUnmount |
onBeforeUnmount |
unmounted |
onUnmounted |
errorCaptured |
onErrorCaptured |
renderTracked |
onRenderTracked |
renderTriggered |
onRenderTriggered |
provide/inject
在Vue2.0当中,provide/inject是作为组件对象的一个属性而存在,而在Composition API中,它们以函数的形式存在。
对于provide而言,可以选择provide一个普通数据也可以provide一个响应式数据。
对于inject而言,相比Vue2.0最大的改进是可以在函数的第二个参数中提供默认值。
