Comparison Api是什么?
一组基于函数的附加API,允许灵活地组成组件逻辑。
a set of additive, function-based APIs that allow flexible composition of component logic.
单看官方解释也很苍白,接下来用个官方例子来说明一下:
<template>
<button @click="increment">
Count is: {{ state.count }}, double is: {{ state.double }}
</button>
</template>
<script>
import { reactive, computed } from 'vue'
export default {
setup() {
const state = reactive({
count: 0,
double: computed(() => state.count * 2)
})
function increment() {
state.count++
}
return {
state,
increment
}
}
}
</script>
上面例子中的reactive和computed就都是Comparison Api提供的函数,用于给代码附加某项功能。
reactive 等价于 2.0版本的Vue.observable(),computed跟2.0的计算属性一致。
在2.x里面,变量的响应式跟计算属性直接在组件作用域中可用;而3.0中,需要从vue中引入才能在组件中使用。
这涉及到另外一个概念:有状态组件跟无状态组件。
有状态组件 vs 无状态组件
以上面的例子为例,把它改造为有状态组件(也就是2.x的写法):
<template>
<button @click="increment">
Count is: {{ state.count }}, double is: {{ state.double }}
</button>
</template>
<script>
export default {
data() {
return {
state: {
count: 0
}
};
},
computed: {
double: () => this.state.count * 2
},
methods: {
increment() {
this.state.count++
}
}
}
</script>
在有状态组件中,组件包含了this跟各种周期函数。而无状态组件,它是一个没有状态的组件,简单来说,就是没有this了,没有各种生命周期函数了。你需要用的时候,都从Comparison Api中去引入调用。
那这样做的好处是什么?
Comparison Api设计的动机
代码组织&逻辑复用
现有的api强制我们执行代码组织,让一切都变得不灵活。例如我想在上面的代码中添加一个显示用户登录状态的功能时,我只能在data、computed、methods代码块中继续添加代码,随着功能的增长,复杂组件的代码变得越来越难以推理。
而且受制于执行代码组织的限制,使得在多个组件之间提取和重用逻辑的成本很高。
给出官方的一张图片,说明如果我们对这些逻辑问题中的每一个进行彩色编码,我们会注意到在使用组件选项表示它们时有多分散:

接下来我们用Composition API来编写“创建新文件夹”功能进行比较:
function useCreateFolder (openFolder) {
// originally data properties
const showNewFolder = ref(false)
const newFolderName = ref('')
// originally computed property
const newFolderValid = computed(() => isValidMultiName(newFolderName.value))
// originally a method
async function createFolder () {
if (!newFolderValid.value) return
const result = await mutate({
mutation: FOLDER_CREATE,
variables: {
name: newFolderName.value
}
})
openFolder(result.data.folderCreate.path)
newFolderName.value = ''
showNewFolder.value = false
}
return {
showNewFolder,
newFolderName,
newFolderValid,
createFolder
}
}
在这个官方例子中,与“创建新文件夹”功能相关的所有逻辑都被封装在一个函数中,还可以通过具体的命名来描述功能。这种方式可以用来解耦组件的所有逻辑问题。

类型推导
开发人员在大型项目上的另一个常见功能要求是对TypeScript有更好的支持。Vue当前的API在与TypeScript集成时提出了一些挑战,这主要是因为Vue依赖单个this上下文来公开属性(例如在methods使用this是指向组件实例而不是methods对象的点后面的内部函数)。换句话说,Vue现有的API在设计时就没有考虑类型推断,在与TypeScript搭配时会产生很多复杂性。
而在3.0组件中使用的都是普通的变量和函数,不存在this上下文;用建议的API编写的代码可以享受完整的类型推断,几乎不需要手动类型提示。
总结
根据文档来说,从2.x升级到3.0开发个人觉得是比较平滑的,我觉得只要抓住两个重点去理解,1小时升级3.0开发不是梦。
- 3.0相比较2.x,它的组件中没有
this上下文跟周期函数,所有这些都需要从Comparison Api中引入 - 2.x只能在页面组件中使用周期函数,3.0中所有封装的逻辑组件都可以从Comparison Api中引入周期函数进行调用。