# Vue-next 为什么使用 Composition API

Composition API 是 vue-next 的最大特性,可以很明显看出是受 React Hooks 的启发。它主要是为了结局 vue2 中的三个限制:

# vue2 痛点

  1. 代码可读性随着组件变大从而变得更差
  2. 没有完美的代码复用方式
  3. TypeScript 支持有限

# 1 代码可读性随着组件变大从而变得更差

假如有一个组件,负责搜索功能,代码如下:

export default {
  data() {
    return {
      🔍Search🔍
    }
  },
  methods: {
    🔍Search🔍
  }
}
1
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

这也还好,但当我们再添加分页等多个功能,并且每个功能都需要 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

每种功能逻辑分散在不同的地方,难以阅读,每更改一个功能都需要上下滑动在各个部分查找响应代码。

而 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

其中 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.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.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
// 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
// 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.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

# 3.1 优点:

  • 编写的代码更少了,更容易将组件中的功能转为一个个函数
  • Function 学习成本低
  • 比 Mixin 和 Slot 更灵活
  • 在编辑器有更好的代码提示、补全功能

# 3.2 缺点:

  • 需要学习新的语法,将其组合使用
  • 现在有两种方法来编写组件,而不是只有标准语法

更多内容可参考 https://www.vuemastery.com/courses/vue-3-essentials/why-the-composition-api/ (opens new window)

最后更新时间: 10/28/2021, 10:09:40 PM