简介
我们知道,setup函数是vue3中的一大特性函数,是组合式API的入口,我们在模板中用到的数据和函数都需要在里面定义,并且最后通过setup函数导出后才能在template中使用:
<script>
import { ref } from 'vue'
import Card from './components/Card';
export default {
components: {
Card,
},
setup(props, ctx){
const count = ref(0);
const add = () => {
count.value ++
}
const sub = () => {
count.value ++
}
return {
count,
add,
sub,
}
}
}
</script>
但是setup函数使用起来比较臃肿,所有的逻辑都写在一个函数中定义;我们发现这样简单的变量和函数,需要频繁的定义导出,再次定义导出,在实际项目开发中会很麻烦,我们写的时候也是需要不断的来回切换,而且变量一多还容易搞混。
于是更好用的setup语法糖出现了,将setup属性添加到<script>
标签,上面的变量和函数可以通过语法糖简写成如下:
<script setup>
import { ref } from 'vue';
const count = ref(0)
const add = () => {
count.value ++
}
const sub = () => {
count.value ++
}
</script>
通过上面的一个简单的小案例,我们就发现setup语法糖不需要显示的定义和导出了,而是直接定义和使用,使代码更加简洁、高效和可维护,使代码更加清晰易读,我们接着来看下还有哪些用法。
基本用法
上面的案例我们已经知道了在setup语法糖中,不需要再繁琐的进行手动导出;不过setup语法糖不支持设置组件名称name,如果需要设置,可以使用两个script标签:
<script>
export default {
name: 'HomeView',
};
</script>
<script setup>
import { ref } from 'vue';
// ...
</script>
如果设置了lang属性,script标签和script setup标签需要设置成相同的属性。
生命周期
Vue3中取消了create的生命周期函数,在其他的生命周期函数前面加上了on,例如onMounted、onUpdated;同时新增了setup函数替代了create函数,setup函数比mounte函数更早执行,因此我们可以在代码中导入函数钩子,并使用它们:
<script lang="ts" setup>
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onActivated,
onDeactivated,
onErrorCaptured,
} from "vue";
onBeforeMount(()=>{
// ...
})
</script>
和vue2的8个生命周期函数相比,在setup函数中,排除了beforeCreate和created,加上onActivated和onDeactivated2个在keep-alive中使用的函数钩子,和一个onErrorCaptured异常捕获钩子,一共有9个生命周期的函数钩子可供使用。
响应式
响应式是vue3和vue2比较大的一处不同之处,vue2在data中定义的数据会自动劫持成为响应式,而vue3默认返回的数据不是响应式的,需要通过ref和reactive来定义数据,ref定义简单的数据类型,而reactive定义复杂数据类型,使之成为响应式:
<script lang="ts" setup>
import { ref, reactive } from 'vue';
const count = ref(0);
const person = reactive({
name: 'jone',
age: 18,
})
</script>
虽然ref是用来定义简单数据类型,不过对于对象和数组的复杂数据类型也能使用,不过使用时都需要加上.value:
<script lang="ts" setup>
import { ref, reactive } from 'vue';
const list = ref([]);
const person = ref({
name: 'jone',
age: 18,
});
list.value.push(23);
console.log(person.value.name)
// 报错
// 类型“number”的参数不能赋给类型“object”的参数。
const count = reactive(2)
</script>
ref和reactive看起来用法是相同的,但使用ref时,操作变量值的时候需要用.value
,因此适用零散的单个变量;如果是多个相关联的变量,比如用户的一系列信息,姓名、性别、住址等,使用ref定义单个变量较为麻烦,就可以使用reactive组合成对象。
如果我们想要用到复杂数据类型中的某个属性,还想要和原来的数据保持关联,比如person中的name或者age,只通过解构的方式,数据响应性会丢失,页面并不会改变:
<template>
<div>{
{ name }} {
{ age }}</div>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue';
const person = reactive({
name: 'jone',
age: 18,
});
const { name, age } = person;
setTimeout(() => {
// 页面上的数据并不会响应改变
person.name = "hello";
}, 1500);
</script>
这个时候,我们就可以使用toRef()
函数来关联两个变量,这个函数的功能相当于创建了一个ref对象,并将其值指向对象中的某个属性:
<script lang="ts" setup>
import { ref, reactive, toRef } from 'vue';
const person = reactive({
name: