一、Vue3 Composition API 是什么?
Composition API 是 Vue3 中外围逻辑及代码组织办法。Vue 外围团队将 Composition API 形容为:一组基于性能的附加 API,能够灵便的组合组件的逻辑。在基于 Vue2 开发我的项目时,通过 methods、watch、data 等组件属性实现页面逻辑的形式称之为 Option API。Option API 模式不仅导致组件业务扩散、产生胶水代码,而且编写的代码也须要 Vue 编译器将 JS 代码转换为真正的执行代码。Composition API 通过将组件属性作为 JS 函数裸露进去以解决上述问题,通过 Composition API 实现的业务代码无需编译器两头解决,同时 TypeScript 的类型查看机制能够更好的保障代码的强壮。
图 1 Composition API 次要性能函数
二、通过例子理解 Composition API 应用形式
在这个 mini 版本的 TodoList 组件中,首先引入了 reactive、Refs、onMounted 三个函数,其中 reactive 次要是用来创立响应式对象,toRefs 次要是解决响应式对象因解构赋值导致响应式生效的问题,onMounted 则用来拜访 mounted 挂载组件时的钩子函数。
其次,定义 DataPros 的接口类型,通过这个接口类型能够获取 reactive 中定义的属性类型及函数的参数、返回值类型。setup 函数是一个新的 Vue 组件对象,是组件应用 Composition API 的入口,setup 函数蕴含两个参数,第一个是用来获取父组件传值的 props,第二个 content 参数代表组件的上下文对象。这里须要留神的是 this 在 setup 中无奈应用。在 setup 中咱们定义了一个数据类型为 DataProps 名称为 data 的响应式对象,对象内蕴含两个参数和两个业务办法,这些定义的属性和办法都在 reactive 创立的响应式对象中,从而防止了参数定义和逻辑定义拆散的问题。
最初,通过 toRefs 组件,对 data 对象进行包装,使其在解构赋值后不会失落响应式个性,并通过 return 将数据合并到组件模板渲染上下文。
三、应用 Composition API 模块化共享属性和办法
在 Vue2 我的项目中,若想在别的组件共享一些属性和代码能够通过 mixins(混入)和 scoped slots 这两种形式实现,然而这两种形式都存在缺点。mixins 最大的缺点在于咱们对其在组件中注入的属性和办法无所不知,更无奈实现类型推断,且混入的内容可能与以后组件存在抵触(Vue2 有一套欠缺的优先级排列,但熟记较有难度)。scope slots 通过 v -slot 属性精确晓得调用者获取了哪些属性,但只能在 template 中拜访,且只能在以后组件的作用域应用。上面咱们来看怎么通过 Composition API 共享属性和办法:
通过引入 ref 函数,创立了一个名为 nowTime 的属性,并创立了一个名为 getNowTime 的办法,而后咱们就能够在任意组件中通过 import 的形式进行代码共享。这种共享代码的形式既不受模板和组件范畴的限度,也将受害于编译器类型查看机制。值得一提的是,在 Vue3 中 Vuex 也能够采纳此函数式的形式援用,无需净化 Vue 原型。
四、Composition API 响应式对象实现源码剖析
在 Vue3 Composition API 中,创立响应式对象能够通过 reactive API 和 ref API 来实现,接下来咱们将通过源码剖析 reactive API 创立响应式对象的形式(ref API 的实现外围也是基于 reactive API)。
在 GitHub 上拉取 vue-next 仓库,能查看 Vue3 的源代码。开展 vue-next/packages/reactivity/src/reactive.ts 门路,能看 reactive 函数的定义。通过 reactive 的类型申明,咱们能够看到函数接管一个类型为泛型 T 的参数,而这个泛型继承自 object,故 target 的类型为 object 类或为其子类。返回类型为 UnwrapNestedRefs 类型,该类型将判断返回的对象是否继承自 Ref 对象,如果为否则可能为嵌套的 Ref 对象,需用递归解套。进入 reactive 函数外部,咱们看到如果传入的对象为只读则返回对象自身,否则返回 createReactiveObject,执行创立响应式对象。
在 createReactiveObject 函数中,会判断 target 对象是否为对象类型,如果不是则间接返回,开发模式下会在控制台打印正告。接着会判断指标是否曾经为 Proxy 对象,是的话同样返回。通过以上查看后,代码会创立一个新的 proxy 对象来实现对象的响应式,proxy 对象会依据对象的类型抉择应用 collectionHandlers 还是 baseHandlers。
创立响应式对象外围在于实现 get、set 以及其余相干的陷阱函数,reactive 基于 Proxy 实现了这些陷阱函数,并解决了因应用 Object.defineProperty()办法导致的对象属性增加删除、组件下标批改等操作无奈被监听的问题。鉴于篇幅起因,本文仅剖析 baseHandlers 包装响应式数据的实现原理。
createGetter 对象用来生成响应式对象的 get 办法(即 get 陷阱函数),通过 Reflect 反射获取到对象的原始属性当前,会判断对象是否为内置办法,如果为内置办法则不进行代理操作,并在属性不为 readOnly 的状况下执行依赖收集操作,最初通过递归调用,返回响应式 get 对象。
接下来咱们来看 reactive 如何实现对象的 set 陷阱函数。函数首先会判断原来的数据是否为 ref 对象,若为是则间接将新数据赋值给 ref.value 即可 (这便是用 reactive 创立的响应式数据不须要用.value 取值的起因)。程序会判断 key 是否存在,如果不存在则通过 trigger 执行 ADD 操作,否则通过 trigger 执行 SET 操作。Trigger 办法在框架中表演通信员的角色,贯通整个零碎,使得 ref 具备高度的响应性。
五、总结
本文以”什么是 Composition API”开篇,介绍了 Composition API 的具体内容及劣势;而后通过应用 Composition API 创立的 mini TodoList 组件,理解了 Composition API 的应用形式及如何通过组件化共享代码。最初,通过源码剖析了 reactive API 的实现形式。本文旨在通过剖析 Composition API 来帮忙大家更好的了解 Vue3 前端框架,因为意识的局限性可能存在相应疏漏,望大家批评指正。