Vue 3.0的Composition API跟React的Hooks非常相似,其目标都是提供一种更为内聚的组件间的逻辑复用方式,以解决过往的相关逻辑分散在组件各处导致复用与维护困难的问题。但是在实际使用的层面上两者又有一定的区别,而这是基于两个框架实现思路的差异,Vue的核心是数据响应式而React的核心是函数式。

setup(props, context)

Vue3.0当中,组件的形式仍然是一个对象,只不过对象提供了一个新的setup方法,在这个方法当中,可以利用Composition API实现Vue2.0组件所具备的几乎所有的功能。

这个方法接收两个参数propscontext,前者是组件参数,而后者则包括了attrs、slots、emit这三个常用API。

props

props最值得关注的一点就是不要使用解构赋值来获取props中的属性。与React函数组件每次渲染都会执行一遍函数不同,每个组件的setup方法只会执行一遍,所以如果使用解构赋值意味着之后将不会监听到props相关属性的变化。以下面为例:

  1. <script>
  2. export default {
  3. name: 'HelloWorld',
  4. props: {
  5. msg: String
  6. },
  7. setup(props) {
  8. const {msg} = props
  9. return () => {
  10. return <div>{props.msg}</div>
  11. }
  12. }
  13. }
  14. </script>

上面的代码在vue-cli会直接报错,警告值会发生丢失。如果要使用解构赋值,则需要先将props通过toRefs进行转换。

  1. 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最大的改进是可以在函数的第二个参数中提供默认值。