Vue3中提出的一个新概念, 作用: 聚合代码 & 逻辑重用
Vue的组件化做的相当出色, 帮助我们更好的拆分代码和约束代码, 增加可读性, 但是2.x有几个问题也是开发者们时刻在关注的
代码逻辑不够聚合, 比较分散, 如果我们的组件代码量一多, 找相同的代码逻辑会显得比较困难
上面的图我把相同逻辑代码用同样的颜色框在了一起, 抛出方法本身的调用以外, 我们依旧可以很清晰的发现这些逻辑是分散的, 非聚合的, 跟react不同, vue只能拆分功能组件却很难拆分逻辑, 所以当我们逻辑一多, 一个组件里存在十多个方法十多种状态, 四五六七八种逻辑的话框会更加多, 找寻起来会比较麻烦, 特别是这个组件不是你自己写的情况下, 在找寻不同逻辑代码会比较困难
逻辑重用困难, 我们知道在vue中逻辑和模板是强绑定的状态, 也就是说如果你想要复用一段逻辑, 你必须复用这个组件, 这对拆分关注点又是一种伤害, 有的时候我并不是很想要UI, 只想要这段逻辑, 这就很难处理了, 而vue2中只给我们提供了mixin来混入逻辑, 但是mixin的致命缺陷就是让你更难屡清楚逻辑, 毕竟人家的语法一句话就搞定, 发生了什么你都不知道, 可读性非常的差
我本人曾经就有在表单中多个地方使用mixin的场景, 因为每个表格显示的东西和数据结构都不太一样, 但是最后的操作增删改查和分页操作逻辑都一样, 所以必须使用mixin, 然后导致到后期代码比较难理解, 特别是交给同事的时候, 他们是很难一瞬间清晰的去理清楚这些逻辑的, 顺带一提对于react来说由于hoc和hook, renderprops的存在这些都不是问题,所以这算是vue的弊端了
vue的侵入性太强, 导致对typescript这类高阶技术的用法不够自然
基于上面的种种问题, vue推出了composition api的概念
composition api(组合式api)本质上就是vue抽离了一系列方法可以供我们自由引入组合使用, 这里抛出一个问题
在不改变vue模板语法的情况下, vue提供了一个新的函数书写在模板的script
标签中, 该函数名叫做 setup
不讨论具体的文档, 我们直接用composition api来写一个小demo, 该case分别用vue2和vue3咱们都来一次对比一下, 来看看vue3到底是怎么处理之前我提到的三个问题的
vue2的写法如下
// Count.vue
<template>
<div class="composition-test">
{
{
count }}
<button @click="inc">+</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
}
},
methods: {
inc() {
this.count ++;
}
}
}
</script>
<style>
</style>
vue3使用composition api如下
// useCount.ts
import {
ref } from 'vue'
/**
* 你可能不太明白ref是干嘛的, 他并不是vue2中的获取真实dom引用那么简单,
* 如上方这样引入的ref叫做响应式api, 我们如果想实现vue的响应式功能,
* 在vue2中我们直接写在data中就好了, 然后视图和数据就会产生映射,
* 而在vue3的composition api中我们想要达到映射的效果必须手动调用vue给我们提供的响应式api才可以达到目的,
* 这也很正常, 相较于那些魔法(你不知道怎么的就成为响应式了), 这种显示的转换让人更加的清晰和放心
*/
export default function useCount(defaultValue: number ):[any, Function] {
let count = ref(defaultValue || 0);
function inc() {
return count.value++;
}
return [count, inc]
}
// Count.vue
<template>
<div class="composition-test">
{
{
count }}
<button @click="inc">+</button>
</div>
</template>
<script lang="ts">
/*eslint-disable*/
import {
ref } from 'vue';
import useCount from '../hooks/useCount';
export default {
setup( props, context ) {
const [count, setCount] = useCount();
return {
count,
setCount
}
}
}
</script>
<style>
</style>
将两组写法进行对比, 我们发现vue3好像可以单独将同一逻辑的状态和方法都抽离出去聚合成一个js文件( 比如count和inc都是跟计数器相关的逻辑 ), 这使得单个Vue文件如果代码量一多, 我们是不是可以做到更好的拆分成一个一个的js文件, 然后在vue组件里导入并且可以一目了然的知道我们当前用到了哪些逻辑, 根据逻辑去追溯相关的状态和方法, 代码逻辑一旦不分散, 就好维护的多
同时你要知道, composition api的写法帮助你把视图和逻辑完全分离, 这意味着你可以不用引入这个组件也可以用到count及其派生方法, 完全更加直观的实现了mixin的功能
当composition api你基本了解以后, 我们来写个伪代码来看看他恐怖的逻辑抽离性
vue2
...
<script>
export default {
data() {
count: 0,
goods: [],
userInfo: {
},
isVip: false
}
methods: {
fetchData() {
...
},
clickHandler() {
...
}
setCount() {
...
},
setGoods() {
...
},
setUserInfo() {
...
},
setIsVip() {
...
}
}
}
script>
...
Vue3
...
<script>
import {
onMounted} from 'vue';
import useCount from '../hooks/useCount';
import useGoods from '../hooks/useGoods';
import useUserInfo from '../hooks/useUserInfo';
import useIsVip from '../hooks/useIsVip';
import fetchData from '../fetchData';
export default {
setup() {
// 既然useCount是一个函数, 我们可以给他传递参数来更灵活处理数据
const [count, setCount] = useCount(0);
const [goods, setGoods] = useGoods([]);
const [userInfo, setUserInfo] = useUserInfo({
});
const [isVip, setIsVip] = useIsVip(false);
onMounted() {
fetchData();
}
// 除去上方强依赖状态的方法, 其他方法都可以写到最下面
handlerClick = () {
..
}
return {
count, setCount,
goods, setGoods,
userInfo, setUserInfo
isVip, setIsVip,
handlerClick
}
},
}
script>
...
确实跟react越来越像了, 但是人确实要拥抱变化不是吗? 而是人家也没有强制你用setup, 你想用options方式来定义data, methods都随便你, vue3只是提供了一个新的方式来书写代码, react的hook确实是大型项目中开发的优势, vue这么做我个人认为是非常nice的