# Vue-next 为什么使用 Composition API
Composition API 是 vue-next 的最大特性,可以很明显看出是受 React Hooks 的启发。它主要是为了结局 vue2 中的三个限制:
# vue2 痛点
- 代码可读性随着组件变大从而变得更差
- 没有完美的代码复用方式
- TypeScript 支持有限
# 1 代码可读性随着组件变大从而变得更差
假如有一个组件,负责搜索功能,代码如下:
export default {
data() {
return {
🔍Search🔍
}
},
methods: {
🔍Search🔍
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
当我们还要给这个组件加上排序功能时:
export default {
data() {
return {
🔍Search🔍
👬🏻Sorting👬🏻
}
},
methods: {
🔍Search🔍
👬🏻Sorting👬🏻
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
这也还好,但当我们再添加分页等多个功能,并且每个功能都需要 data、computed、watch、methods 时就会变成如下样子:
export default {
data() {
return {
🔍Search🔍
👬🏻Sorting👬🏻
📃Paging📃
}
},
mounted() {
🔍Search🔍
👬🏻Sorting👬🏻
📃Paging📃
},
computed: {
🔍Search🔍
👬🏻Sorting👬🏻
📃Paging📃
},
watch: {
🔍Search🔍
👬🏻Sorting👬🏻
📃Paging📃
},
methods: {
🔍Search🔍
👬🏻Sorting👬🏻
📃Paging📃
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
每种功能逻辑分散在不同的地方,难以阅读,每更改一个功能都需要上下滑动在各个部分查找响应代码。
而 Composition Api 的 setup 很好的解决了这一问题,将同一功能逻辑写在同一个区域,但并不是全部放在 setup 函数中,可以放入任何地方。可读性非常高:
export default defineComponent({
setup() {
return {
...Search(),
...Sorting(),
...Paging()
}
}
})
function Search() {
🔍Search🔍
onMounted(() => 🔍Search🔍)
computed(() => 🔍Search🔍)
effect(() => 🔍Search🔍)
}
function Sorting() {
👬🏻Sorting👬🏻
computed(() => 👬🏻Sorting👬🏻)
effect(() => 👬🏻Sorting👬🏻)
}
function Paging() {
📃Paging📃
computed(() => 📃Paging📃)
effect(() => 📃Paging📃)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
其中 Search、Sorting 这些函数就称为 “Composition 函数”,也称为 “Vue Hooks”
# 2 没有完美的代码复用方式
vue2 中有三种跨组件代码复用方式,但每个都有局限:
- Mixins
- Mixins Factory
- Scoped Slots
# 2.1 Mixins
const searchMixin = {
data() {
return {
🔍Search🔍
}
},
methods: {
🔍Search🔍
}
}
const PagingMixin = {
data() {
return {
📃Paging📃
}
},
methods: {
📃Paging📃
}
}
export default {
mixins: [searchMixin, PagingMixin]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 2.1.1 优点:
- 可以按照功能模块来组织代码
# 2.1.2 缺点:
- 属性名容易冲突
- 属性来源不清晰,需要进入每个 mixin 查看
- 不清楚各个 mixin 之间的交互关系
- 不能在不同的组件间差异化使用
# 2.2 Mixin Factory
使用一个工厂函数,根据传入配置,返回对应的 Mixin 内容。
function searchMixinFactory({ ...config }) {
🔍Search Config🔍
}
function PagingMixinFactory({ ...config }) {
📃Paging Config📃
}
export default {
mixins: [
searchMixinFactory({
🔍Search Config🔍
}),
PagingMixinFactory({
📃Paging Config📃
})
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2.2.1 优点:
- 可以解决 Mixin 的后面两个缺点,即可以清晰看出各个 mixin 之间的交互关系,并且可以在不同的组件间差异化使用
# 2.2.2 缺点:
- 属性名仍然容易冲突
- 属性来源不清晰,需要进入每个 mixin 查看
- 不能跑在运行时,因此不能动态生成 Mixin
# 2.3 Scoped Slots
// GenericSearch.vue
<template>
<div class="search-container">
<slot v-bind="{ origin, category }">
</div>
</template>
<script>
export default {
props: ['searchConfig']
}
</script>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
// GenericPaging.vue
<template>
<div class="paging-container">
<slot v-bind="{ index, total }">
</div>
</template>
<script>
export default {
props: ['pagingConfig']
}
</script>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
// index.vue
<template>
<GenericSearch :config="searchConfig" v-slot="searchResult">
<GenericPaging :config="pagingConfig" v-slot="pagingResult">
searchData.result
pagingData.output
</GenericPaging>
</GenericSearch>
</template>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 2.2.1 优点:
- 解决了 Slot 几乎所有的缺点
# 2.2.2 缺点:
- 配置只能写在 template 上面
- 暴露的属性只能在 template 上面使用
- 增加了模板嵌套,降低了可读性
- 由于使用了 3 个组件而不是 1 个,因此性能稍差
# 3 Composition Api
Composition Api 解决了上面的问题
function Search(SearchConfig) {
🔍Search🔍
return { origin, category }
}
function Paging(PagingConfig) {
📃Paging📃
return { index, tatal }
}
export default defineComponent({
setup() {
const searchResult = Search(searchConfig)
const pagingResult = Paging(PagingConfig)
return {
searchResult,
pagingResult
}
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 3.1 优点:
- 编写的代码更少了,更容易将组件中的功能转为一个个函数
- Function 学习成本低
- 比 Mixin 和 Slot 更灵活
- 在编辑器有更好的代码提示、补全功能
# 3.2 缺点:
- 需要学习新的语法,将其组合使用
- 现在有两种方法来编写组件,而不是只有标准语法
更多内容可参考 https://www.vuemastery.com/courses/vue-3-essentials/why-the-composition-api/ (opens new window)
← css-scoped promise 实现 →