vue3 监听函数

635 阅读2分钟

监听属性

与vue2中的watch配置以及功能是一致的,在vue3中需要先引入watch函数才能在setup函数中运行,只有当监听的数据发生了变化才会调用watch函数的回调函数。

监听ref定义的响应式数据

<script setup>
// 引入
import { ref, reactive, watch } from "vue";
let num = ref(0);
let add = () => {
  num.value++;
};
watch(num, (newvalue, oldvalue) => {
  console.log("只有当num变量发生了改变才会执行", newvalue, oldvalue);
});
</script>

<template>
  <div class="app">
    <p>{{ num }}</p>
    <button @click="add">点击num自增</button>
  </div>
</template>

<style scoped lang='scss'>
</style>

image.png

监听多个ref定义的响应式数据

<script setup>
// 引入
import { ref, reactive, watch } from "vue";
let num = ref(0);
let total=ref({name:'tara',title:'6ara'});
let add = () => {
  num.value++;
};
let change=()=>{
  total.value.title='6ara 4ever'
}
watch(num, (newvalue, oldvalue) => {
  console.log("只有当num变量发生了改变才会执行", newvalue, oldvalue);
});
watch(total, (newvalue, oldvalue) => {
  console.log("只有当total变量发生了改变才会执行", newvalue, oldvalue);
});
</script>

<template>
  <div class="app">
    <p>{{ num }}</p>
    <button @click="add">点击num自增</button>
    <p>{{total.title}}</p>
    <button @click="change">change no change </button>
  </div>
</template>

<style scoped lang='scss'>
</style>

也可以接收数组将监听多个属性

watch([num, total], (newValue, oldValue) => {
  if (newValue[0] !== oldValue[0]) {
    console.log("sum变了", newValue[0], oldValue[0]);
  }
  if (newValue[1] != oldValue[1]) {
    console.log("total变了", newValue[1], oldValue[1]);
  }
});

2.gif

ps:当监听的属性是引用数据时,需要整个属性的引用地址改变才算监听的属性发生了改变才会运行watch的回调函数,监听ref定义的响应式数据可以配置deep选项开启深度监听,当引用数据中某个值发生变化也会运行watch的回调函数。

watch(total, (newvalue, oldvalue) => {
  console.log("只有当total变量发生了改变才会执行", newvalue, oldvalue);
},{deep:true});

监听引用数据时就无法正确的获取oldvalue,newVal === oldVal,他们都指向同一个引用地址的对象也就是修改值后的代理对象

image.png

监听reactive定义的响应式数据

监听reactive定义的响应式数据时,监听引用数据时oldvalue也无法正确获取,监听reactive定义的响应式数据时会监听全部属性强制开始了深度监视,deep的配置失效。

<script setup>
// 引入
import { ref, reactive, watch } from "vue";
let person = reactive({
  name: "tara",
  age: 13,
  more: {
    leibie: "girl idoleam",
    member: "BQSEHJ",
  },
});
let change=()=>{
  person.more.member='boram qri soyeon eunjung hyomin jiyeon'
}
watch(person, (newvalue, oldvalue) => {
  console.log("person数据变化了", newvalue, oldvalue);
  console.log(oldvalue===newvalue,6666);
});
</script>

<template>
  <div class="app">
    <h2>团队:{{ person.name }}</h2>
    <h2>出道年龄:{{ person.age }}</h2>
    <h2>成员:{{ person.more.member }}</h2>
    <button @click="change">修改姓名</button>
  </div>
</template>

<style scoped lang='scss'>
</style>

newVal === oldVal,是同一个对象的引用,就是对象本身

image.png

监听reactive所定义的一个响应式数据的某一个属性(某一个属性为引用数据时,不会开启深度监听,当其中的某一个属性变化是监听不到的除非该属性的引用地址发生了变化,需要配置deep为true)

<script setup>
// 引入
import { ref, reactive, watch } from "vue";
let person = reactive({
  name: "tara",
  age: 13,
  more: {
    leibie: "girl idoleam",
    member: "BQSEHJ",
  },
});
let change=()=>{
  person.more.member='boram qri soyeon eunjung hyomin jiyeon'
}
watch(()=>person.more, (newvalue, oldvalue) => {
  console.log("person数据变化了", newvalue, oldvalue);
  console.log(oldvalue===newvalue,6666);
});
watch(()=>person.name,(newvalue, oldvalue) => {
  console.log("person数据变化了", newvalue, oldvalue);
  console.log(oldvalue===newvalue,6666);
})
</script>

<template>
  <div class="app">
    <h2>团队:{{ person.name }}</h2>
    <h2>出道年龄:{{ person.age }}</h2>
    <h2>成员:{{ person.more.member }}</h2>
    <button @click="change">修改姓名</button>
    <button @click="person.name='6ara 4ever'">change</button>
  </div>
</template>

<style scoped lang='scss'>
</style>

2.gif

watch(()=>person.more, (newvalue, oldvalue) => {
  console.log("person数据变化了", newvalue, oldvalue);
  console.log(oldvalue===newvalue,6666);
},{deep:true});

image.png