Vue知识点8-Watch

核心功能1 :监听 ref 基础类型

  1. **watch 作用**:用来**监视响应式数据的变化**,数据变化后执行回调函数。

**监听 ref 基础类型**

复制代码
watch(sum, (newVal, oldVal)=>{})
  • 直接传入 `ref` 对象本身(不用 `.value`)

  • 回调参数:`newValue` 新值、`oldValue` 旧值

**watch 返回值:停止监听函数**

  • `const stopWatch = watch(...)`

  • 调用 `stopWatch()` 可以**手动取消监视**,后续数据再变化,回调不再执行

  • 本例逻辑:sum ≥5 时,调用停止函数,关闭监听

核心:watch 监听 ref 基本类型直接传 ref 对象;它返回一个停止函数,可以手动终止侦听。

javascript 复制代码
<template>
  <div class="person">
    <h2>Watch监视Ref定义的基本类型的值</h2>
    <h2>当前求和:{{ sum }}</h2>
    <button @click="changeSum">点我+1</button>
  </div>
</template>


<script lang="ts">
//导出组件名称,叫做"App"
export default {
  name: "Person"
}
</script>

<script lang="ts" setup>
import {ref, watch} from "vue"

let sum = ref(0)

function changeSum() {
  sum.value += 1
}

const stopWatch = watch(sum, (newValue, oldValue) => {
  console.log(newValue, oldValue)
  if (sum.value >= 5) {
    console.log("RefImpl sum.value值已经超过5,不再监视")
    //与watch返回值一致
    stopWatch()
  }
})

</script>

<style scoped>
.person {
  background-color: green;
}
</style>

核心功能2 :监听 ref 对象类型

1.ref可以包裹对象,person是RefImpl,真实对象在person.value里

2.监听ref对象,deep默认false:只监听整个person.value被替换,修改内部属性不触发

整个对象替换案例:person.value = {name: "李四", age: 20}

3.deep设为true:深度监听,替换对象、修改内部属性都能触发

4.deep设为true,只改对象内部属性时,newValue和oldValue是同一个对象,看不出新旧区别

5.immediate默认false,初始化不执行;immediate:true初始化立刻执行回调,newValue是初始值,oldValue是undefined

6.watch可以接收返回的停止函数,调用就能取消监听

7.监听ref基础类型不用deep,监听ref里面对象的属性变化需要开启deep:true

javascript 复制代码
<template>
  <div class="person">
    <h2>Watch监视Ref定义的基本类型的值</h2>
    <h2>当前求和:{{ sum }}</h2>
    <button @click="changeSum">点我+1</button>
    <hr>
    <h2>Watch监视Ref定义的对象类型的值</h2>
    <h2>姓名:{{ person.name }}</h2>
    <h2>年龄:{{ person.age }}</h2>
    <button @click="changPerson">改变人</button>
  </div>
</template>


<script lang="ts">
//导出组件名称,叫做"App"
export default {
  name: "Person"
}
</script>

<script lang="ts" setup>
import {ref, watch} from "vue"

let sum = ref(0)
//ref引用对象类型,person是RefImpl,提取值需要.value
let person = ref({name: "张三", age: 18})

function changPerson() {
  person.value = {name: "李四", age: 20}
}

function changeSum() {
  sum.value += 1
}

const stopWatch = watch(sum, (newValue, oldValue) => {
  console.log(newValue, oldValue)
  if (sum.value >= 5) {
    console.log("RefImpl sum.value值已经超过5,不再监视")
    //与watch返回值一致
    stopWatch()
  }
})

/**
 * 第一个参数监视的对象
 * 第二个参数,回调函数,参数1新值,参数2旧值
 * 如果是对象的属性改变,新值与旧值相同
 * 如果是对象的属性改变,新值与旧值相同
 * 如果是对象的改变,新值是新对象,旧值是旧对象
 */
watch(person, (newValue, oldValue) => {
  console.log(newValue, oldValue) //deep=true  {name:"张三",age:18}  undefined
}, {
  deep: false, //true监控值属性变化
  immediate: false//true初始化时就执行一次
})

</script>

<style scoped>
.person {
  background-color: green;
}
</style>

核心功能3:监听reactive对象类型

  1. reactive创建的对象,watch直接监听它,默认自动开启深度监视,并且这个deep无法关闭
  2. 不能直接写person = {name:"李四",age:20},这样会切断响应式
  3. 如果想要整体更新reactive对象里面的数据,可以用Object.assign(person,新对象),
  4. 回调函数中回调里 newValue 和 oldValue 是同一个对象
  5. 只修改reactive内部属性时,也会触发,但回调里newValue和oldValue是同一个对象发
  6. immediate默认值是false 案例: watch(person, (newValue, oldValue) => { console.log(newValue, oldValue) })
  7. style加scoped,样式只在当前组件生效
javascript 复制代码
<template>
  <div class="person">
    <h2>Watch监视Reactive定义的对象类型的值</h2>
    <h2>姓名:{{ person.name }}</h2>
    <h2>年龄:{{ person.age }}</h2>
    <button @click="changPerson">改变人</button>
  </div>
</template>


<script lang="ts">
//导出组件名称,叫做"Person"
export default {
  name: "Person"
}
</script>

<script lang="ts" setup>
import {ref, watch,reactive} from "vue"

let person = reactive({name: "张三", age: 18})

function changPerson() {
  // person = {name: "李四", age: 20} 这是无法替换的
  Object.assign(person,{name:"李四",age:20})
}
/**
 * 第一个参数监视的对象
 * 第二个参数,回调函数,参数1与参数2在 监视Reactive对象时时同一个对象
 * 默认开启深度监视且无法关闭
 */
watch(person, (newValue, oldValue) => {
  //都是同一个对象,因为监视的person是同一个,newValue与oldValue是同一个地址
  console.log(newValue, oldValue)
})

</script>

<style scoped>
.person {
  background-color: green;
}
</style>

核心功能4:监听ref或reactive对象中的属性

  1. reactive对象内部属性监听,推荐使用函数返回式作为watch第一个参数 案例:watch(()=>person.name,(newVal,oldVal)=>{console.log(newVal,oldVal)})

  2. 修改reactive对象不能直接person=新对象,会切断响应式,直接修改属性是可行的

  3. 监听reactive里嵌套对象(person.car),即使写成函数形式,想要监听内部属性修改,需要配置deep:true

  4. 只修改嵌套对象内部属性时,回调的newValue和oldValue指向同一个引用

  5. 监视ref或reactive定义的【对象类型】数据中的某个属性,注意点如下: 1.若该属性值是【基本类型】,需要写成函数形式。 2.若该属性值是依然是【对象类型】,可直接编,也可写成函数,建议写成函数。注意

    复制代码
    person.car = {c1: "雅迪", c2: "艾玛"} 是替换属性,不是整个person的Object.assign
  6. immediate默认值为false

  7. style加scoped,样式仅当前组件生效

监听reactive的对象,与监听reactive中对象的对象,有什么区别?

1、直接监听整个reactive对象 watch(person, callback) 自动自带deep深度监听,deep关不掉;person里面不管多少层属性改动都能触发回调。

2、监听reactive里面嵌套的对象 watch(()=>person.car, callback) 不会自动开启deep,想要监听car内部c1、c2这类属性变化,必须手动加deep:true;如果不加deep,只有给car整体替换新对象的时候才触发。

补充: 两种方式,单纯修改内部属性时,newValue和oldValue都是同一个引用。 统一推荐都用函数写法作为watch第一个参数。

javascript 复制代码
<template>
  <div class="person">
    <h2>Watch监视Reactive定义的对象中的属性</h2>
    <h2>姓名:{{ person.name }}</h2>
    <h2>年龄:{{ person.age }}</h2>
    <h2>第一辆车:{{ person.car.c1 }}</h2>
    <h2>第二辆车:{{ person.car.c2 }}</h2>
    <button @click="changName">改变名字</button>
    <button @click="changC1">改变第一辆车</button>
    <button @click="changCar">改变整车</button>
  </div>
</template>


<script lang="ts">
//导出组件名称,叫做"Person"
export default {
  name: "Person"
}
</script>

<script lang="ts" setup>
import {watch, reactive} from "vue"

let person = reactive({name: "张三", age: 18, car: {c1: "奔驰", c2: "宝马"}})

function changName() {
  // person = {name: "李四", age: 20} 这是无法替换的且切断了响应式
  person.name = "李四"
}

function changC1() {
  person.car.c1 = "奥迪"
}

function changCar() {
  person.car = {c1: "雅迪", c2: "艾玛"}
}

/**
 * 监听对象属性中的基本类型
 * 第一个参数监视的对象属性,建议使用函数
 * 第二个参数,回调函数,参数1新值,参数2旧值
 */
watch(() => {
      return person.name
    },
    (newValue, oldValue) => {
      console.log(newValue, oldValue)
    })

//监听对象中的对象类型
//如果第一个参数直接写的是person.car,那么只能监听到原来的car变化,整个car替换监听不到
//所以第一个参数官方推荐使用函数返回,才能监听的到变化
watch(() => {
      return person.car
    },
    (newValue, oldValue) => {
      //实际上newValue与oldValue是一个,因为是同一个引用地址
      console.log(newValue, oldValue)
    },
    {"deep": true})//监听属性变化

</script>

<style scoped>
.person {
  background-color: green;
}
</style>

核心功能5:监听多个KEY

  1. watch可以监听多个响应式数据,第一个参数传数组,案例:watch(temp, height,(newVal)=>{}),newVal是新值组成的数组,可以解构拿到每一项新值
  2. watchEffect不用明确指定要监听谁,回调内部用到哪些响应式数据,就自动追踪依赖这些数据
  3. watchEffect默认初始化就会执行一次回调,自动收集依赖,后续依赖的数据变化就重新运行回调
  4. watch需要手动指定监听源;watchEffect自动收集依赖
  5. watchEffect没有新旧值参数,拿不到oldValue
  6. watchEffect也会返回停止函数,调用可以停止侦听 案例:const stop = watchEffect(()=>{}) stop()
  7. style加scoped,样式只作用当前组件
javascript 复制代码
<template>
  <div class="person">
    <h2>Watch数组+WatchEffect</h2>
    <h2>水温:{{ temp }}°C</h2>
    <h2>水位:{{ height }}CM</h2>
    <button @click="addTemp">增加水温</button>
    <button @click="addHeight">增加水位</button>
    <button @click="changeAge">年龄</button>
    <button @click="changeName">姓名</button>
  </div>
</template>


<script lang="ts">
//导出组件名称,叫做"Person"
export default {
  name: "Person"
}
</script>

<script lang="ts" setup>
import {reactive, ref, watch, watchEffect} from "vue"

let temp = ref(10);
let height = ref(0);
let person = reactive({name: "张三", age: 18})

function addTemp() {
  temp.value += 10
}

function addHeight() {
  height.value += 10
}

function changeAge() {
  person.age = 19
}

function changeName(){
  person.name = "李四"
}

watch([temp, height, person, ()=>{return person.name}], (newValue,oldValue) => {
  console.log(newValue)  //[10, 0, Proxy(Object), '张三']
  let [t, h] = newValue
  if (t >= 60 || h >= 80 || person.age == 19) {
    alert("发送报警")
  }
})

watchEffect(() => {
  if (temp.value >= 60 || height.value >= 80) {
    alert("发送报警")
  }
})


</script>

<style scoped>
.person {
  background-color: green;
}
</style>
相关推荐
垆边人似月.1 小时前
选型与快速跑通(Tesseract / EasyOCR / PaddleOCR)
前端·python
IT_陈寒1 小时前
一文搞懂Java的核心概念
前端·人工智能·后端
铁皮饭盒1 小时前
workbuddy和codebuddy免费送1000积分, 10秒钟搞定
前端·后端
aloha_7891 小时前
HTML、JavaScript 与 TypeScript 基础速查
javascript·typescript·html
风骏时光牛马1 小时前
从零到落地的AI系统学习进阶路线
前端
橙光成长3 小时前
PDF离线工具箱深度解析:4MB纯前端单文件,40+功能全本地运行,文件绝不上传
前端·pdf·1024程序员节
小poop10 小时前
CSS 基础与实战:从入门到精通网页美化
前端
Csvn11 小时前
运行时性能
前端
Never_every9912 小时前
位图转矢量工具哪个好?实测抠抠图AI位图转矢量工具
大数据·前端