什么是组合式API?
组合式 API (Composition API) 是一系列 API (响应式API、生命周期钩子、依赖注入)的集合。它不是函数式编程,组合式 API 是以 Vue 中数据可变的、细粒度的响应性系统为基础的,而函数式编程通常强调数据不可变
为什么要有组合式API?
1、更好的逻辑复用
它使我们能够通过组合函数来实现更加简洁高效的逻辑复用。在选项式 API 中我们主要的逻辑复用机制是 mixins,而组合式 API 解决了 mixins 的所有缺陷
组合式函数:
可以参考我的关于组合式函数理解的博客:什么是组合式函数?-CSDN博客
mixins 的缺陷:
-
不清晰的数据来源:
当使用了多个 mixin 时,实例上的数据属性来自哪个 mixin 变得不清晰
-
命名冲突:
多个来自不同作者的 mixin 可能会注册相同的属性名,造成命名冲突
-
隐式的跨mixin交流:
多个 mixin 需要依赖共享的属性名来进行相互作用,这使得它们隐性地耦合在一起
2、更灵活的代码组织
下面通过各功能代码的分布让大家直观感受到选项式API和组合式API的区别(同一个功能的代码用同一个颜色标注)
总结:选项式 API 在单个组件的逻辑复杂到一定程度时,会面临一些无法忽视的限制;组合式API则相对来说会更加灵活整齐,也使代码易于维护
3、更好的类型推导
-
选项式API:(不理想)
2013 年被设计出来的,那时并没有把类型推导考虑进去,因此不得不做了一些复杂到夸张的类型体操才实现了对选项式 API 的类型推导。但尽管做了这么多的努力,选项式 API 的类型推导在处理 mixins 和依赖注入类型时依然不甚理想
-
Class API:(没有继续发展)
基于 Class 的 API 非常依赖 ES 装饰器,在 2019 年我们开始开发 Vue 3 时,它仍是一个仅处于 stage 2 的语言功能。认为基于一个不稳定的语言提案去设计框架的核心 API 风险实在太大了,因此没有继续向 Class API 的方向发展
-
组合式 API :(比较完善)
主要利用基本的变量和函数,它们本身就是类型友好的。用组合式 API 重写的代码可以享受到完整的类型推导,不需要书写太多类型标注
4、更小的生产包体积
<script setup> 形式书写的组件模板被编译为了一个内联函数,和 <script setup> 中的代码位于同一作用域。不像选项式 API 需要依赖 this 上下文对象访问属性,被编译的模板可以直接访问 <script setup> 中定义的变量,无需从实例中代理,这对代码压缩更友好,因为本地变量的名字可以被压缩,但对象的属性名则不能。
5、和 React Hooks 的对比
Hooks:
- Hooks 有严格的调用顺序,并不可以写在条件分支中
- React 组件中定义的变量会被一个钩子函数闭包捕获,若开发者传递了错误的依赖数组,它会变得“过期”,导致非常依赖ESLint 规则以确保传递了正确的依赖,但在一些边缘情况时仍会遇到令人头疼的、不必要的报错信息。
- 昂贵的计算需要使用 useMemo,这也需要传入正确的依赖数组
- 在默认情况下,传递给子组件的事件处理函数会导致子组件进行不必要的更新
- 要解决变量闭包导致的问题,再结合并发功能,使得很难推理出一段钩子代码是什么时候运行的,并且很不好处理需要在多次渲染间保持引用 (通过 useRef) 的可变状态
组合式API:
- 仅调用 setup() 或<script setup> 的代码一次,不需要担心闭包变量的问题。组合式 API 也并不限制调用顺序,还可以有条件地进行调用。
- Vue 的响应性系统运行时会自动收集计算属性和侦听器的依赖,因此无需手动声明依赖。
- 无需手动缓存回调函数来避免不必要的组件更新。
总结:React Hooks 的创造性,它是组合式 API 的一个主要灵感来源。然而,它的设计也确实存在上面提到的问题,而 Vue 的响应性模型恰好提供了一种解决这些问题的方法
总结
组合式 API 提供更高的逻辑复用性和灵活性,使得代码更清晰、更易维护,同时优化了性能和包体积。