前言

使用 Composition API 编写的代码更易读,并且场景不复杂,这使得阅读和学习变得更容易。

解决了 vue 2.x 选项式 API 的一些痛点:

  • 基于 Vue2 的大型组件很难维护。
  • 基于 Vue2 封装的组件逻辑复用困难。
  • Vue2TypeScript 支持有限。

一般我们的项目都是 vue 2.x, 如果想使用 composition-api 可以使用这个插件: @vue/composition-api

一、 引入到项目中

1. 安装

npm install @vue/composition-api
# or
yarn add @vue/composition-api

2. 配置

main.js 中添加一下配置:

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)

二、 使用


1. reactive 和 ref

1.1. reactive

接收一个普通对象然后返回该普通对象的响应式代理。

响应式转换是“深层的”:会影响对象内部所有嵌套的属性。基于 ES2015 的 Proxy 实现,返回的代理对象不等于原始对象。建议仅使用代理对象而避免依赖原始对象。

<template>
  <div>
    <span></span>
    <br>
    <span></span>
    <br>
    <button @click='addAge'>改变属性</button>
    <button @click='changePeople'>改变对象</button>
    <button @click='changeObject'>改变 reactive</button>
  </div>
</template>
<script>
// 导入 reactive
import { reactive } from '@vue/composition-api'

export default {
  // 代替之前的 beforeCreate, create
  setup () {
    let people = reactive({name: 'blank', age: 25})
    function addAge () {
      people.age ++
    }

    function changePeople () {
      people = { name: 'shawn', age: 21 }
      console.log(people)
    }

    function changeObject () {
      people = reactive({ name: 'jesse', age: 18 })
      console.log(people)
    }

    // 返回用到的方法和数据
    return { people, addAge, changePeople, changeObject }
  }
}
</script>

1.2. ref

接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value

如果传入 ref 的是一个对象,将调用 reactive 方法进行深层响应转换。

<template>
  <div>
    <!-- > age 默认不用加 value < -->
    <span></span>
    <br>
    <button @click='addAge'>改变</button>
  </div>
</template>
<script>
import { ref } from '@vue/composition-api'

export default {
  setup () {
    let age = ref(25)
    function addAge () {
      // 需要 .value
      age.value ++
    }
    return { age, addAge }
  }
}
</script>

2. watch

vue2.x 中的 watch 一样

<template>
  <div>
    <!-- > age 默认不用加 value < -->
    <span></span>
    <br>
    <button @click='addAge'>改变</button>
  </div>
</template>
<script>
import { watch } from '@vue/composition-api'

export default {
  setup () {
    let age = ref(25)
    function addAge () {
      // 需要 .value
      age.value ++
    }
    watch(
      () => age.value,
      (to, from) => {
        alert(to);
      }
    )
    return { age, addAge }
  }
}
</script>

其他关键字如下:

beforeCreate -> 使用 setup()
created -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured

注:setup()this 不可用,是 undefined


3. setup 中传入的属性

  • props
  • context
    • root: vue2.x 中的 this
    • emit: vue2.x 中的 this.$emit
    • attrs: vue2.x 中的 this.$attrs
    • slots: vue2.x 中的 this.$slots
<script>
import { watch } from '@vue/composition-api'

export default {
  // props: 组件中传递的参数
  setup (props, context) {
    // this
    console.log(context.root)
    // this.$emit
    console.log(context.emit)
    // this.$attrs
    console.log(context.attrs)
    // this.$slots
    console.log(context.slots)
  }
}
</script>

4. 依赖注入 provide 和 inject

provideinject 提供依赖注入,功能类似 2.xprovide/inject。两者都只能在当前活动组件实例的 setup() 中调用

<template>
  <div>
    <span></span>
    <button @click='addAge'>改变</button>
    <InjectVue />
  </div>
</template>
<script>
import { provide, reactive } from '@vue/composition-api'

import InjectVue from './inject.vue'

export default {
  setup () {
    let person = reactive({name: 'blank', age: 25})
    provide('person', person)

    function addAge () {
      person.age ++
    }

    return { person, addAge }
  },
  components: {
    InjectVue
  }
}
</script>

inject.vue

<template>
  <div>
    <span>inject: </span>
    <button @click='changePerson'>改变</button>
  </div>
</template>
<script>
import { inject } from '@vue/composition-api'

export default {
  setup () {
    let person = inject('person')

    function changePerson () {
      person = {name: 'shawn', age: 21}
      console.log(person)
    }

    return { person, changePerson }
  }
}
</script>

可以使用 ref 来保证 providedinjected 之间值的响应

参考文档:

https://composition-api.vuejs.org/zh/api.html
https://github.com/vuejs/composition-api
https://v3.cn.vuejs.org/api/composition-api.html