Vue3-watch 侦听器

123 阅读3分钟

Vue3-watch 侦听器

基础概念

在Vue3中,watch的特性进行了一些的改变和优化,与computed不同的是,watch常常用于监听响应式数据的变化,并且执行一些相关的从操作。比如,发送网络请求,更新DOM操作等。

基本语法

参数

watch(source, callback, options?)

  1. watch的第一个参数是:被监视的数据
  2. watch第二个参数是:监视的回调
  3. watch的第三个参数是:配置对象(deep、immediate等等……)
第一个参数 (被监视的数据)
1.1. 监听ref定义的基本类型数据

监视ref定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变。

let num = ref(1);
watch(num, (newValue, oldValue) => {
  console.log(newValue, oldValue);
});

1.2. 多个监听
let num1 = ref(1);
let num2 = ref(2);
watch([num1, num2], ([newNum1, newNum2], [oldNum1, oldNum2]) => {
  console.log(newNum1, newNum2, oldNum1, oldNum2);
});

2. 监听ref定义的对象类型数据

监视ref定义的【对象类型】数据:直接写数据名

注意:

  • 监视的是对象的【地址值】,若想监视对象内部的属性,需要手动开启深度监视。
  • 若修改的是ref定义的对象中的属性,因为它们是同一个对象(内存地址不变),所以newValueoldValue 都是新值。
  • 若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。
let person = ref({
  name: "zs",
  age: 13,
});

watch(
  person.value,
  (newValue, oldValue) => {
    console.log(newValue, oldValue);
  },
  {
    deep: true,
  }
);
3. 监听reactive定义的对象类型数据

reactive不能定义基本类型数据

监视reactive定义的【对象类型】数据,且默认开启了深度监视,并且是不可关闭的 深度监听。数据中的任何一点蛛丝马迹的变化,都会被监听到。

// 监视`reactive`定义的【对象类型】数据,且默认开启了深度监视。

let person = reactive({
  name: "zs",
  age: 18,
  car: {
    c1: "c1",
    c2: "c2",
  },
});


watch(person, (newValue, oldValue) => {
  console.log("person变化了", newValue);
});

4. 监听ref或reactive定义的数据中的某个属性

监视refreactive定义的【对象类型】数据中的某个属性,注意点如下:

  • 若该属性值不是【对象类型】,需要写成函数形式。
  • 若该属性值是依然是【对象类型】,可直接编,也可写成函数,建议写成函数。

注意点: 若是对象,则监视的是地址值,需要关注对象内部,需要手动开启深度监视。

// 监视`reactive`定义的【对象类型】数据,且默认开启了深度监视。
let person = reactive({
  name: "zs",
  age: 18,
  car: {
    c1: "c1",
    c2: "c2",
  },
});

watch(
  () => person.name,
  (newValue, oldValue) => {
    console.log("person.name变化了", newValue);
  }
);

watch(
  () => person.car,
  (newValue, oldValue) => {
    console.log("person.car变化了", newValue);
  },
  {
    deep: true,
  }
);
5. 组合监听多个数据
let sum = ref(0);
let person = reactive({
  name: "zs",
});

function updateName() {
  person.name += "~";
}

function updateSum() {
  sum.value += 1;
}

watch([sum, person], ([sumNew, personNew], [sumOld, personOld]) => {
  console.log(sumNew, personNew, sumOld, personOld);
  // 1 Proxy(Object) {name: 'zs~'}  0 Proxy(Object)  {name: 'zs~'}
});

watch([sum, () => person], ([sumNew, personNew], [sumOld, personOld]) => {
  console.log(sumNew, personNew, sumOld, personOld);
   // 1 Proxy(Object) {name: 'zs~'}  0 Proxy(Object)  {name: 'zs~'}
});

watch([sum, () => person.name], ([sumNew, personNew], [sumOld, personOld]) => {
  console.log(sumNew, personNew, sumOld, personOld);
  // 1 'zs' 0'zs'
});

清除watch副作用
const id = ref(1)
const data = ref(null)

watch(id, async (newValue, oldValue, onCleanup) => {
  const { response, cancel } = doAsyncWork(id.value)
  // `cancel` 会在 `id` 更改时调用
  // 以便取消之前未完成的请求
  onCleanup(cancel)
  data.value = await response.json()
})

返回值

watch 返回一个函数,函数作用是停止监听

const unwatch = watch(() => {})
// ...当该侦听器不再需要时
unwatch()