Web前端系列之Vue新语法setup应用解析

内容导读

  • 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的参数直接使用,不需要引入模块

更多内容请持续关注本站!

猜你喜欢

转载自blog.csdn.net/sinat_30844883/article/details/142881365