前言
Vue3.0 在去年9月正式发布了,也有许多小伙伴都热情的拥抱Vue3.0。去年年底我们新项目使用Vue3.0来开发,这篇文章就是在使用后的一个总结, 包含Vue3新特性的使用以及一些用法上的变更。
为什么要升级Vue3
使用Vue2.x的小伙伴都熟悉,Vue2.x中所有数据都是定义在data中,方法定义在methods中的,并且使用this来调用对应的数据和方法。那Vue3.x中就可以不这么玩了, 具体怎么玩我们后续再说, 先说一下Vue2.x版本这么写有什么缺陷,所以才会进行升级变更的。
回顾Vue2.x实现加减
<template>
<div class="homePage">
<p>count: {
{ count }}</p>
<p>倍数: {
{ multiple }}</p>
<div>
<button style="margin-right:10px" @click="increase">加1</button>
<button @click="decrease">减一</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
};
},
computed: {
multiple() {
return 2 * this.count;
},
},
methods: {
increase() {
this.count++;
},
decrease() {
this.count++;
},
},
};
</script>
上面代码只是实现了对count
的加减以及显示倍数, 就需要分别在data、methods、computed中进行操作,当我们增加一个需求,就会出现下图的情况:
当我们业务复杂了就会大量出现上面的情况, 随着复杂度上升,就会出现这样一张图, 每个颜色的方块表示一个功能:
甚至一个功能还有会依赖其他功能,全搅合在一起。
当这个组件的代码超过几百行时,这时增加或者修改某个需求, 就要在data、methods、computed以及mounted中反复的跳转,这其中的的痛苦写过的都知道。
那我们就想啊, 如果可以按照逻辑进行分割,将上面这张图变成下边这张图,是不是就清晰很多了呢, 这样的代码可读性和可维护性都更高:
那么vue2.x版本给出的解决方案就是Mixin, 但是使用Mixin也会遇到让人苦恼的问题:
- 命名冲突问题
- 不清楚暴露出来的变量的作用
- 逻辑重用到其他 component 经常遇到问题
关于上面经常出现的问题我就不一一举例了,使用过的小伙伴多多少少都会遇到。文章的重点不是Mixin,如果确实想知道的就留言啦~
所以,我们Vue3.x就推出了Composition API主要就是为了解决上面的问题,将零散分布的逻辑组合在一起来维护,并且还可以将单独的功能逻辑拆分成单独的文件。接下来我们就重点认识Composition API。
Composition API
setup
setup 是Vue3.x新增的一个选项, 他是组件内使用 Composition API的入口。
setup执行时机
我在学习过程中看到很多文章都说setup 是在 beforeCreate和created之间, 这个结论是错误的。实践是检验真理的唯一标准, 于是自己去检验了一下:
export default defineComponent ({
beforeCreate() {
console.log("----beforeCreate----");
},
created() {
console.log("----created----");
},
setup() {
console.log("----setup----");
},
})
setup 执行时机是在beforeCreate之前执行,详细的可以看后面生命周期讲解。
::: warning 由于在执行setup 时尚未创建组件实例,因此在 setup 选项中没有 this。:::
setup 参数
使用setup时,它接受两个参数:
- props: 组件传入的属性
- context
setup中接受的props是响应式的, 当传入新的props 时,会及时被更新。由于是响应式的, 所以不可以使用ES6解构,解构会消除它的响应式。
错误代码示例, 这段代码会让props不再支持响应式:
// demo.vue
export default defineComponent ({
setup(props, context) {
const { name } = props
console.log(name)
},
})
那在开发中我们想要使用解构,还能保持props的响应式,有没有办法解决呢?大家可以思考一下,在后面toRefs学习的地方为大家解答。
接下来我们来说一下setup接受的第二个参数context,我们前面说了setup中不能访问Vue2中最常用的this对象,所以context中就提供了this中最常用的三个属性:attrs、slot 和emit,分别对应Vue2.x中的 $attr属性、slot插槽 和$emit发射事件。并且这几个属性都是自动同步最新的值,所以我们每次使用拿到的都是最新值。
reactive、ref与toRefs
在vue2.x中, 定义数据都是在data中, 但是Vue3.x 可以使用reactive和ref来进行数据定义。
那么ref和reactive他们有什么区别呢?分别什么时候使用呢?说到这里,我又不得不提一下,看到很多网上文章说(reactive用于处理对象的双向绑定,ref则处理js基础类型的双向绑定)。我其实不太赞同这样的说法,这样很容易初学者认为ref就能处理js基本类型, 比如ref也是可以定义对象的双向绑定的啊, 上段代码:
setup() {
const obj = ref({count:1, name:"张三"})
setTimeout(() =>{
obj.value.count = obj.value.count + 1
obj.value.name = "李四"
}, 1000)
return{