一、为了解决多业务线交叉、难以维护的复杂场景,Vue3认为以业务分割逻辑代码更合理。

例如:当前组件有一个显示某个用户的仓库列表的视图。此外,我们还希望有搜索和筛选功能。在Vue2.x中代码大致如下。

// src/components/UserRepositories.vue

export default {
  components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
  props: {
    user: { 
      type: String,
      required: true
    }
  },
  data () {
    return {
      repositories: [], // 1
      filters: { ... }, // 3
      searchQuery: '' // 2
    }
  },
  computed: {
    filteredRepositories () { ... }, // 3
    repositoriesMatchingSearchQuery () { ... }, // 2
  },
  watch: {
    user: 'getUserRepositories' // 1
  },
  methods: {
    getUserRepositories () {
      // 使用 `this.user` 获取用户仓库
    }, // 1
    updateFilters () { ... }, // 3
  },
  mounted () {
    this.getUserRepositories() // 1
  }
}

如果不熟悉该段代码的人第一次阅读,需要不停在 data、methods、computed 以及各个生命周期中来回查找相关业务代码,如果业务更复杂,代码的碎片化会更严重,导致难以维护。

如果能够将同一个逻辑关注点相关代码收集在一起会更好。而这正是组合式 API 使我们能够做到的。

 

二、组合式API的基础用法

先来写一段简单的组合式API代码:

<script lang="ts">
import { defineComponent, ref, reactive, toRefs } from 'vue'

export default defineComponent({
    setup() {
        let name = ref('')
        let age = ref(0)
        let obj = reactive({
            name: name.value,
            age: age.value
        })

        return toRefs(obj)
    },
})
</script>

(1) setup

  1.1 setup(props, context)

    新的 setup 选项在组件创建之前执行,一旦 props 被解析,就将作为组合式 API 的入口。

    在 setup 中你应该避免使用 this,因为它不会找到组件实例。

    setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法在 setup 中被获取。

  1.2 参数介绍: 

    第一个参数 props

      setup 函数中的第一个参数是 props。props 是响应式的。但不可以解构,否则会失去响应性。

      如果需要解构 props,建议使用 refs 后文介绍

    第二个参数 context

      const { attrs, slots, emit } = context // Attributes,插槽,触发事件

      非响应式,可直接解构: setup(props, { attrs, slots, emit })

      请注意,与 props 不同,attrs 和 slots 是非响应式的。如果你打算根据 attrs 或 slots 更改应用副作用,那么应该在 onUpdated 生命周期钩子中执行此操作。

    

 

  另外在 Vue3 中,beforeCreate 和 created 钩子函数将不再适用,其他钩子有略微改动,参考下图

    

 

 

(2) ref 、reactive 、torefs

  2.1 ref

    ref 接收参数并将其包裹在一个带有 value property 的对象中返回,然后可以使用该 property 访问或更改响应式变量的值

    let name = ref('')
   let age = ref(0)   
return {   name,
     age    }

  2.2 reactive

    如果将对象分配为 ref 值,则通过 reactive 方法使该对象具有高度的响应式。

    setup() {
          let name = ref('')
          let age = ref(0)
          let obj = reactive({
              name: name.value,
              age: age.value
          })
          return toRefs(obj)
      }

 

  2.3 toRefs

    将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref

    const state = reactive({
        foo: 1,
        bar: 2
    })
    const stateAsRefs = toRefs(state)
    // ref 和原始 property 已经“链接”起来了
    state.foo++
    console.log(stateAsRefs.foo.value) // 2
    stateAsRefs.foo.value++
    console.log(state.foo) // 3

 

以上内容参考自 介绍 | Vue.js (vuejs.org)