跳转至

17-watch

作用:监视数据的变化,vue2 中的 watch 作用一致,写法有区别 特点:Vue3 中的 watch 只能监测以下四种数据

  • ref 定义的数据
  • reactive 定义的数据
  • 函数返回的一个值 (getter 函数)
  • 一个包含上述内容的数组

监视 ref 定义的基本类型数据

<template>
  <div class="child-wrap">
    <h3>{{title}}</h3>
    求和:{{ sum }}
    <br>
    <button @click="handleClick">点击</button>
  </div>
</template>

<script setup lang="ts">
import { ref , watch} from 'vue';
const title = ref("watch相关")
const sum = ref(0);
function handleClick(){
  sum.value += 1
}

watch(sum, (newValue, oldValue)=> {
  console.log("sum变化了-新值", newValue);
  console.log("sum变化了-旧值", oldValue);
})
</script>
<style lang="" scoped></style>

停止监视方法

const stopWatch =  watch(sum, (newValue, oldValue)=> {
  console.log("sum变化了-新值", newValue);
  console.log("sum变化了-旧值", oldValue);
  if(newValue > 5){
    stopWatch()
    console.log("停止监听");
  }
})

监视 ref 定义的对象数据

直接改数据名,监视的是对象的地址值,若要监视对象内部的数据,要手动开启深度监听

  • 若修改的是 ref 定义的对象中的属性, newValue 和 oldValue 是一样的都是新值,因为监视的是同一个对象
  • 若修改的是整个 ref 定义的对象,newValue 是新值,oldValue 是旧值,因为不是同一个对象

watch

  • 第一个参数监视的数据
  • 第二个参数 数据变化的回调
  • 第三个参数 配置项,可以配置 deep 和 immediate 等其他项
<template>
  <div class="child-wrap">
    <h3>{{title}}</h3>
    <br>
    姓名:{{ sum.name }}
    <br>
    年龄:{{ sum.age }}
    <br>
    <button @click="handleName">切换姓名</button>
    <button @click="handleAge">切换年龄</button>
    <button @click="handleSum">切换所有</button>
  </div>
</template>
<script setup lang="ts">
import { ref , watch} from 'vue';
const title = ref("watch相关-监视ref定义的对象类型")
const sum = ref({
  name: "wang",
  age : 18
});
function handleName(){
  sum.value.name += "~"
}
function handleAge(){
  sum.value.age += 1
}
function handleSum() {
  sum.value = {
    name: "hahha",
    age : 28
  }
}
watch(sum, (newVal, oldVal)=> {
  console.log("newVal", newVal);
  console.log("oldVal", oldVal);
},
{
  deep:true
})
</script>

监视 reactive 定义的对象数据

  • 监视 reactive 定义的数据,默认开启深度监视,不可关闭 (隐式创建深度监听)
<template>
  <div class="child-wrap">
    <h3>{{title}}</h3>
    <br>
    姓名:{{ sum.name }}
    <br>
    年龄:{{ sum.age }}
    <br>
    <button @click="handleName">切换姓名</button>
    <button @click="handleAge">切换年龄</button>
    <button @click="handleSum">切换所有</button>
  </div>
</template>
<script setup lang="ts">
import { reactive, ref , watch} from 'vue';
const title = ref("watch相关-监视reactive定义的对象类型")
const sum = reactive({
  name: "wang",
  age : 18
});
function handleName(){
  sum.name += "~"
}
function handleAge(){
  sum.age += 1
}
function handleSum() {
  Object.assign(sum,{
    name: "hahha",
    age : 28
  })
}
// 监视 reactive 定义的数据,默认开启深度监视
watch(sum, (newVal, oldVal)=> {
  console.log("newVal", newVal);
  console.log("oldVal", oldVal);
})
</script>

监视reactive/ref定义的数据(对象类型)某个属性

  • 若监视的不是对象类型,需要写成函数形式
  • 监视的是响应式对象数据的某个属性,且数据是对象类型,可以直接写,也可以写函数,更推荐函数,

结论:监视的是对象里面的属性,最好写成函数,若是对象监视的地址值,需要关注对象内部,需要手动开启深度监听

watch(()=>{return sum.name}, (newVal, oldVal)=> {
  console.log("newVal", newVal);
  console.log("oldVal", oldVal);
})

 

watch(()=> sum.name, (newVal, oldVal)=> {
  console.log("newVal", newVal);
  console.log("oldVal", oldVal);
})
  • 对象类型,仅监听里面的数据,整个对象变化监听不到
// 只监听对象里面的数据
watch(sum.info, (newVal, oldVal)=> {
  console.log("newVal", newVal);
  console.log("oldVal", oldVal);
})
  • 只监听整个对象,单独的监听不到
watch(()=>sum.info, (newVal, oldVal)=> {
  console.log("newVal", newVal);
  console.log("oldVal", oldVal);
})
  • 开通深度监听, 整个对象新旧值返回的还是不一样的
// 开通深度监听, 整个对象新旧值返回的还是不一样的
watch(()=>sum.info, (newVal, oldVal)=> {
  console.log("newVal", newVal);
  console.log("oldVal", oldVal);
}, {deep:true})