一、为了解决多业务线交叉、难以维护的复杂场景,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)