内容导读
- setup语法糖
- setup语法糖的应用
- 自测练习题
一、setup语法糖
在Composition API组合式API中,在setup函数中声明的数据、函数等内容,都需要通过 return 对外暴露,才能被组件的视图模板(template)使用,这就造成了书写上的不方便。
于是,Vue官方又给我们推出了一个新的setup语法糖,一种简洁高效的语法格式。
使用setup语法糖,就可以不用写setup函数了。并且,数据和函数也不用返回,组件也不需要注册了。
1.1 setup语法糖的基本结构
<template>
</template>
<script setup>
//此处直接写setup函数中的内容
</script>
<style>
</style>
- 在script标签中使用setup属性即可。
- 运行时,script标签中的内容会被重新编译成 setup() 函数的形式。
- 而且,声明的数据、函数不需要通过 return 暴露,即可被 template所使用
1.2 响应数据的使用
<template>
<div>
<p>{
{ num }}</p>
<button @click="add">加</button>
</div>
</template>
<script setup>
let num = 10;
//const num = 10;
//由于num不是响应数据,所以改变num是无效的。
const add = ()=>{
alert("触发了此方法");
num++;
}
</script>
- 直接声明的数据不是响应式的,数据改变时不会响应到视图模板中。
<template>
<div>
<p>{
{ num }}</p>
<p>{
{ dept.deptno }},{
{ dept.dname }},{
{ dept.loc }}</p>
<ul>
<li v-for="user in userArr" :key="user.userId">
{
{user.userId}},{
{user.userName}},{
{user.userAge}}
</li>
</ul>
<button @click="add">加</button>
</div>
</template>
<script setup>
import { reactive, ref } from "vue";
const num = ref(10);
const dept = reactive({
deptno: 20,
dname: "技术部",
loc: '沈阳市',
});
const userArr = ref([
{
userId: 100,
userName: "张三",
userAge: 25,
},
{
userId: 101,
userName: "李四",
userAge: 26,
},
{
userId: 102,
userName: "王五",
userAge: 27,
},
]);
const add = () => {
num.value++; //注意:要使用value属性获取
dept.deptno++;
//userArr.value[0].userAge++;
userArr.value = [];
}
</script>
ref 和 reactive 都可以做响应式数据,它们的区别如下:
- reactive:用于定义引用类型。只能修改数据,不能改变其引用。
- ref:用于定义基本类型和引用类型。可以修改数据,也可以改变其引用。
-
- 在方法中修改数据时需要使用 value属性。因为,Ref的本质是通过Reactive创建的,Ref(10) 就相当于:Reactive({value:10});
- 在视图模板调用可以省略value属性的书写。
1.3 其它语法的使用
下面例子演示了computed计算属性、watch监听、生命周期函数的使用。
<template>
<div>
{
{ num }}
{
{ newNum }}
<button @click="add">add</button>
</div>
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
const num = ref(10);
const newNum = computed(() => {
return num.value*2;
})
const add = ()=>{
num.value++;
}
watch(num,(newValue,oldValue)=>{
console.log(newValue,oldValue);
})
//生命周期函数
onMounted(() => {
console.log("DOM挂载后!");
});
</script>
1.4 引入组件的使用
引入的组件不必注册,可以直接使用。
<template>
<div class="home">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script setup>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
</script>
1.5 父子组件传值的使用
1.5.1 defineProps的使用
defineProps用于父组件向子组件传值。
父组件:
<template>
<div class="home">
<HelloWorld msg="Welcome to Your Vue.js App" :num="num"/>
</div>
</template>
<script setup>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
const num = 20
</script>
子组件:
<template>
<div class="hello">
<h1>{
{ msg }},{
{ num }}</h1>
</div>
</template>
<script setup>
//const myProps = defineProps(['msg','num']);
const myProps = defineProps({
msg:{
type: String
},
num:{
type: Number,
required: true
}
});
</script>
<style scoped>
</style>
defineProps也可以有数组形式和对象形式两种写法。
1.5.2 defineEmits的使用
defineEmits用于子组件向父组件传值。
父组件:
<template>
<div class="home">
<HelloWorld
msg="Welcome to Your Vue.js App"
:num="num"
@childmsg="get"/>
</div>
</template>
<script setup>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
const num = 20;
const get = (value) => {
console.log(value)
}
</script>
子组件:
<template>
<div class="hello">
<h1>{
{ msg }},{
{ num }}</h1>
<button @click="send">给父组件传值</button>
</div>
</template>
<script setup>
const myProps = defineProps(['msg','num']);
const emit = defineEmits(['childmsg']);
const send = () => {
emit('childmsg','子组件向父组件传的值');
}
</script>
<style scoped>
</style>
二、setup语法糖的应用
接下来我们使用setup语法糖重写之前组件文件,观察一下跟之前有什么不同之处。
AddNew组件:
<template>
<div>
<input type="text" v-model="newItem" />
<button @click="handleAdd">添加</button>
</div>
</template>
<script setup>
import { ref } from "vue";
const newItem = ref("");
const emit = defineEmits(["submitNewItem"]);
const handleAdd = () => {
if (newItem.value == "") {
alert("不能为空");
return;
}
emit("submitNewItem", newItem.value);
newItem.value = "";
};
</script>
TheList组件:
<template>
<ol>
<li v-for="(item, index) in list" :key="index" @click="judgeItem(index)">
{
{ item }}
</li>
</ol>
</template>
<script setup>
const emit = defineEmits(['handleDelete','handleJudge']);
const judgeItem = (index) => {
if (myProps.listType) {
emit("handleDelete", index);
} else {
emit("handleJudge", index);
}
};
const myProps = defineProps({
list: {
type: Array,
required: true,
},
listType: {
type: Boolean,
default: false,
},
});
</script>
TodoList组件:
<template>
<div>
<h1>todoList</h1>
<AddNew @submitNewItem="addNewItem"></AddNew>
<TheList :list="todoList" @handleJudge="toDone"></TheList>
<hr />
<TheList
:list="doneList"
:listType="true"
@handleDelete="toDelete"
></TheList>
</div>
</template>
<script setup>
import AddNew from "../components/AddNew.vue";
import TheList from "../components/TheList.vue";
import { reactive } from "vue";
const todoList = reactive([]); //待办事项
const doneList = reactive([]); //完成事项
const addNewItem = (newItem) => {
todoList.push(newItem);
}
const toDone = (index) => {
doneList.push(todoList.splice(index, 1)[0]);
}
const toDelete = (index) => {
doneList.splice(index, 1);
}
</script>
从上可以看出来,应用了setup语法糖代码,更加简洁易读,开发效率更高了。
三、自测练习题
1、简述在setup语法糖中如何做父子组件的数据传递?
2、关于provide和inject模块说法正确的是( )
A. 使用inject可以接收上级组件传递过来的值
B. 父子组件是可以进行双向数据传递的
C.provide只能给直接子组件进行数据传递
D.provide和inject可以作为setup的参数直接使用,不需要引入模块
更多内容请持续关注本站!