1.什么是setup?
vue官方解释:setup()
钩子是在组件中使用组合式 API 的入口,意思就是说是使用vue3的入口函数。
2.setup的使用形式
2.1 需要在非单文件组件中使用组合式 API 时。
直接在script标签上添加setup,将script标签中的内容注入到setup函数,不需要return操作,同时也不能使用this。代码来展示一下在setup中,各种组合式api如何使用,当然还有很多其他的api,这里简单展示主要常见的用法。
<script setup lang="ts">
// 直接将script标签上加上setup, 让这个script标签变成一个setup函数,并且会自动的将script标签中的内容注入到setup函数中
// 在这个script标签中,不需要return,同时也不能使用this。
// setup函数会在组件实例创建之前执行,因此在这个函数中,无法访问到组件实例。
// 在setup函数中,可以使用reactive、ref、watch、onMounted、onUnmounted等API来创建响应式数据、监听数据变化、在组件挂载和卸载时执行一些操作。
// 在setup函数中,可以使用props、emit、slots等API来访问组件的props、emit、slots等属性。
// 在setup函数中,可以使用defineProps、defineEmits、defineExpose等API来定义组件的props、emit、expose等属性。
import {
reactive,
ref,
nextTick,
watch,
onMounted,
onUnmounted,
computed,
} from "vue";
// 接收父组件入参
const props = defineProps({
fatherName: {
type: String,
default: "father",
},
});
// 父组件传递事件
const emit = defineEmits(["changeAge"]);
// 声明ref基础类型响应式数据
const msg = ref("欢迎你的到来");
// 声明reactive对象类型响应式数据
const obj = reactive({
name: "kboy",
age: 18,
});
// 声明计算属性
const computedMsg = computed(() => {
return obj.name + "今年" + obj.age + "岁";
});
const changeObjAge = () => {
obj.age++;
// 执行父组件传递的事件
emit("changeAge", obj.age);
nextTick(() => {
console.log("数据发生改变,dom更新后执行");
});
};
// 监听数据变化
watch(
() => obj.age,
(newVal, oldVal) => {
console.log("obj.age变化了", newVal, oldVal);
}
);
onMounted(() => {
console.log("组件挂载后生命周期钩子");
});
onUnmounted(() => {
console.log("组件卸载后生命周期钩子");
});
// 暴露属性方法给父组件调用执行
defineExpose({
changeObjAge,
});
</script>
<template>
<div class="test-wrap">{{ msg }}!{{ computedMsg }}</div>
</template>
<style scoped lang="scss">
.test-wrap {
color: #000;
}
</style>
2.2 需要在基于选项式 API 的组件中集成基于组合式 API 的代码时。
由于vue3兼容vue2的语法,所以也可以在选项式API中编辑组合式API的代码。具体用法如下:
<template>
<div class="use-method">
<div>{{ msg }}</div>
<div>{{ conflictVar }}</div>
<div>{{ msgForSetup }}</div>
<button @click="changeMsg">修改vue2的msg</button>
<button @click="changeMsgForSetup">修改vue3的msgForSetup</button>
</div>
</template>
<script>
import { ref, toRefs, onMounted } from "vue";
// 由于vue3是兼容vue2的,所以说vue3中也可以使用vue2的语法,但是vue3中推荐使用vue3的语法。
// 接下来就是vue2的语法使用场景。
export default {
name: "use-method",
props: {
fatherMsg: {
type: String,
default: "这是父组件传递过来的数据",
},
},
data() {
return {
msg: "这是vue2定义出来的响应式数据",
conflictVar: "这是vue2中定义出来的冲突变量",
};
},
setup(props, { attrs, slots, emit, expose }) {
// 将props中的fatherMsg解构出来,并使用toRefs方法将其转换为响应式数据。
const { fatherMsg } = toRefs(props);
// 在setup中定义一个响应式数据,并且使用ref方法将其转换为响应式数据。
const msgForSetup = ref("这是vue3中setup定义出来的响应式数据");
const changeMsgForSetup = () => {
msgForSetup.value = "这是vue3中setup修改出来的响应式数据";
};
// 声明一个与vue2中data一样的变量名。权限优先使用setup中的变量。
const conflictVar = ref("这是vue3中setup内定义出来的冲突变量");
onMounted(() => {
console.log("vue3-setup中的onMounted");
});
// 暴露部分属性,方法,供父组件使用。
expose({
msgForSetup,
changeMsgForSetup,
conflictVar,
});
// 必须要将声明出来的变量,方法进行return出去,否则无法在模板中使用。
return {
msgForSetup,
conflictVar,
fatherMsg,
changeMsgForSetup,
};
},
methods: {
changeMsg() {
this.msg = "这是vue2中修改出来的响应式数据";
},
},
};
</script>
<style scoped>
.use-method {
width: 100%;
height: 100%;
background-color: #fff;
color: black;
}
</style>