对于没太了解 Vue3.0 的同窗,在看到 Composition API 时,除了看起来会有一个“高大上”的感受,可能更多的是有点懵逼,心中难免泛起一堆疑惑,这究竟是何方神圣?干了何等大事?承担了何种重任?javascript
下面咱们就一块儿来简明扼要聊聊,用人人都听得懂的话来阐述 Vue3.0 Composition API。前端
首先,这两单词是啥意思?vue
Composition: 构成,组合方式java
API:应用程序接口(Application Programming Interface),指一些预先定义的函数,用来系统之间、组件之间、函数之间交互的一种约定。web
说人话,在 Vue3.0 中是什么意思呢?api
中文名:合成函数微信
“ 以函数为载体,将业务相关的逻辑代码抽取到一块儿,总体打包对外提供相应能力,这就是 Composition API ”less
能够理解它是咱们组织代码,解决逻辑复用的一种方案。编辑器
那 Vue3.0 中为何要以函数为载体,将业务相关代码抽取到一块儿呢?函数
咱们来看下当前的 Vue2.x 的代码组织方式:
export default {
props: {
……
},
data() {
return {
……
};
},
watch: {
……
},
computed: {
……
}
methods: {
……
}
复制代码
上述是咱们再熟悉不过的写法了,在一个组件当中实现某一个功能,可能会有如下几个代码块:
按照这种方式写完代码后,假如是其余人来看这代码,会是什么状况呢?
若是须要查找某个功能的逻辑,就须要在这个组件中,不断的滚动页面去查看各个模块的的代码,若是代码逻辑很复杂的,跳来跳去,看的着实真叫一个难受呀!
这就是当前 Vue2.x 的组织代码形式,叫 Options API,形象以下图(只需关注颜色块区域位置):
图中相同颜色区域表明同一个功能模块,这里给人感受是整个组件代码比较凌乱,功能代码块交错出现,颜色相互穿插,眼花缭乱。
可能有同窗会说了,你这个是基本用法,咱们能够用 Mixins,HOC,Renderless Components 来规避这种问题呀。
You are right ! 这些必定程度上是能够解决这个问题,可是他们都或多或少存在一些问题:
模版中的数据来源不清晰。举例来讲,当一个组件中使用了多个 mixin 的时候,光看模版会很难分清一个属性究竟是来自哪个 mixin。HOC 也有相似的问题。
命名空间冲突。由不一样开发者开发的 mixin 没法保证不会正好用到同样的属性或是方法名。HOC 在注入的 props 中也存在相似问题。
性能。HOC 和 Renderless Components 都须要额外的组件实例嵌套来封装逻辑,致使无谓的性能开销。
另外,将 Vue2.x 现有的 API 在与 Typescript 集成时的确有一些挑战,主要是由于 Vue 依赖于 this 上下文来抛出属性,并且相较于简单的 JavaScript,this 在 Vue 组件中有不少魔法性 (好比:methods 属性里面定义的函数里的 this 指向的是组件实例,而不是 methods 对象)。
除了以上几个缘由外,Composition API 还有两个优点:
类型推导:基于函数的 API 自然对类型推导很友好,由于 TS 对函数的参数、返回值和泛型的支持已经很是完备。
打包尺寸:基于函数的 API 每个函数均可以做为 named ES export 被单独引入,这使得它们对 tree-shaking 很是友好。同时,由于全部的函数名和 setup 函数体内部的变量名均可以被压缩,因此拥有更好的压缩效率。
基于各方权衡,因此整出了 Composition API。
说了这么多,那么 Composition API 在哪里使用呢?
咱们要知道 Composition API 是代码逻辑组合和复用的方案,不是替代组件的方案。换言之,原来组件该怎么划分,如今继续怎么划分,丝绝不受影响。
可是组件内的代码的组织,组件间代码的复用,则和 Composition API 息息相关,好比以下:
listenMouse.js
import { ref, onMounted, onUnmounted } from 'vue'
function useMouse() {
const x = ref(0)
const y = ref(0)
const update = e => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
export default useMouse;
复制代码
这里将 变量定义 x, y,生命周期函数 onMounted,onUnmounted,更新方法 update 都集成到一块了,以函数 useMouse 为载体,统一对外提供监听鼠标位置的 API 服务。因而在任何的组件中均可以使用到该服务,不受限制。
以下在组件中使用 listenMouse 提供的服务:
<template>
<p>Mouse Position:</p>
<p>x:{{ x }},y:{{ y }}</p>
</template>
<script> import useMouse from './listenMouse'; export default { setup (props) { let {x, y} = useMouse(); return { x, y } } } </script>
复制代码
使用 Composition API 的方式,你会发现逻辑复用超简单了,且超清晰,代码更整洁,形象以下图(只需关注颜色块区域位置):
这里相同颜色区域表明同一个功能模块,你会清晰的看到颜色区块井井有理,都是一块一块的,折射的是整洁的代码,咱们须要修改哪一个功能,就直接在哪块代码修改便可。
这就是 Composition API,在组件间的逻辑须要复用的时候,在组件内代码须要剥离的时候,咱们放心大胆的用!
经过对 Composition API 的了解,你会发如今代码组织上有一个很大的变化:干掉了 Vue2.x 中神奇的 this。
在 Vue2.x 中,咱们的代码中大量的使用到了 this,组件中的 props, data,methods 都是绑定到 this 上下文,而后由 this 去访问。
那么使用 Compositon API 以后,当涉及到跨组件之间提取、复用逻辑时,就会很是的灵活。一个合成函数只依赖于它的参数和全局引入的 Vue APIs,而不是充满魔法的 this 上下文。咱们只须要将组件中你想复用的那部分代码抽离,而后将它导出为函数就能够了。
好比上面中的 listenMouse.js,单独导出 useMouse,在其余组件均可以使用。
然而事情可能都有两面性~
最近看到有人用 Composition API 实践应用,功能不大,在阅读完以后,笔者认为在 Vue3.0 的 Composition API 中未来会避免不了出现 “面条代码” 这个问题!
面条代码:代码的控制结构复杂、混乱,逻辑不清,关系耦合,让人一时难以理解。
面条代码的形象例子:
这图让人看了一脸懵逼,如赞成大利面条同样,所有混在一块儿,一时难以确切找到调用出入口和代码之间的关系是如何的。
Options API 和 Composition API 的差别咱们上面已经分析过了,咱们再换个角度总结一下:
Options API 约定:
你会发现 Options APi 都约定了咱们该在哪一个位置作什么事,这反倒在必定程度上也强制咱们进行了代码分割。
如今用 Composition API,再也不这么约定了,因而乎,代码组织很是灵活,咱们的控制代码写在 setup 里面便可。
若是做为一个新手,或者不郑重思考的码农,那么在逻辑愈来愈复杂的状况下,setup 代码量愈来愈多,一样 setup 里面的 return 愈来愈复杂,势必会落入“面条代码”的斡旋之中。
就以我上面提到的,我看完的 Composition API 的实践为例,该应用不大,可是一个 setup 方法整整 350 行代码了……
咱们没有了 this 上下文,没有了 Options API 的强制代码分离。Composition API 给了咱们更加广阔的天地,那么咱们更加须要慎重自约起来。
对于复杂的逻辑代码,咱们要更加剧视起 Composition API 的初心,不要吝啬使用 Composition API 来分离代码,用来切割成各类模块导出。
咱们指望是这样的:
import useA from './a';
import useB from './b';
import useC from './c';
export default { setup (props) { let { a, methodsA } = useA(); let { b, methodsB } = useA(); let { c, methodsC } = useC(); return { a, methodsA, b, methodsB, c, methodsC } } } 复制代码
就算 setup 内容代码量愈来愈大,可是始终围绕着大而不乱,代码结构清晰的路子前进。
setup 是咱们的代码控制器,尽可能不要写入大量的业务逻辑代码。始终秉承着为 “控制器分忧,为 setup 减负” 的思想来撸代码!
固然咱们一样要规避坠入“混沌代码”的魔咒。还需秉承:高内聚,低耦合 的撸代码方针。
让咱们一块儿静待 Vue3.0 正式版的到来!
欢迎关注个人微信公众号,一块儿作靠谱前端!