watch监视与watchEffect监视

Watch

什么是watch

watch 的作用是用于监测响应式属性的变化,并在属性发生改变时执行特定的操作,它是 Vue 中的一种响应式机制,允许你在数据发生变化时做出相应的响应,执行自定义的逻辑。

watch 使得在响应式属性变化时能够有更多的控制权和灵活性,让你的组件能够更好地响应数据的变化并执行相应的逻辑。
watch() 默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。

监听数据类型

1.一个 ref() 定义的响应式数据
2. 一个 reactive() 定义的响应式数据
3. 一个getter 函数,返回一个值
4. 以上三种组成的数组。

1. ref定义的基本数据类型

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

    let sum = ref(0);
    function addSum() {
        sum.value++;
    }

    // 监听sum变化,当sum大于10时停止监听
    // 这里watch中的sum不要加value,因为watch监视的是一个ref响应式对象,加了value就成了监视属性
    // watch()返回一个停止函数,调用该函数可以停止监听
    let stopWatch = watch(sum, (newVal, oldVal) => {
      console.log('sum变化了', newVal, oldVal);
      if (newVal > 10) {
        stopWatch(); // 停止监听
      }
    })
</script>

<template>
  <div class="class">
    <h2>当前计数:{{ sum }}</h2>
    <br/>
    <button @click="addSum">sum+1</button>
  </div>
</template>

<style scoped>
  .class {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      height: 100%; /* 使内容占满整个高度 */
      color: rgb(214, 12, 12);
      font-size: 20px;
  }

  button {
      background-color: blue;
      color: white;
      border: none;
      padding: 10px 20px;
      border-radius: 5px;
      cursor: pointer;
      margin-top: 10px;
  }
</style>

在这里插入图片描述

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

<script lang="ts" setup name="Watch02">
import { ref, watch } from 'vue';
  let person = ref({ name: '张三', age: 20 });

  function changeName() { // 改变姓名
    person.value.name = '李四'
  }


  function changeAge() { // 改变年龄
    person.value.age ++;
  }

  function changePerson() { // 改变整个人
    person.value = { name: '王五', age:  90}
  }

  // 监听person的变化,只有执行changePerson函数时才会触发,
  // 因为changeName和changeAge函数不会改变person的地址,只改变了内部属性的值,所以不会触发
  // watch(person, (newVal, oldVal) => { // 监听person的变化
  //   console.log('person 变化了', newVal, oldVal);
  // });
  
  // 深度监听person的变化,会监听到内部属性的变化
  // changeName和changeAge函数也会触发
  watch(person, (newVal, oldVal) => { // 监听person的变化
    console.log('person 变化了', newVal, oldVal);
  }, { deep: true });

</script>

<template>
  <div class="class">
    <h2>姓名:{{ person.name }}</h2>
    <br/>
    <h2>年龄:{{ person.age }}</h2>
    <button @click="changeName">修改姓名</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changePerson">修改整个人</button>
  </div>
</template>

<style scoped>
  .class {
    background-color: #f8f9fa; /* 背景颜色 */
    padding: 20px; /* 内边距 */
    border-radius: 10px; /* 圆角 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
    text-align: center; /* 文本居中 */
    max-width: 500px; /* 最大宽度 */
    margin: 0 auto; /* 水平居中 */
  }

  button {
    background-color: blue;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    margin: 10px 10px 0 10px; /* 外边距 */
    transition: background-color 0.3s ease; /* 按钮背景颜色过渡效果 */
  }
</style>

3.reactivate 定义对象类型数据

监听reactive定义的 对象类型 数据,默认是开启深度监视的,且无法取消深度监视。

<script lang="ts" setup name="Watch03">
import { reactive, watch } from 'vue';
  let person = reactive({ name: '张三', age: 20 });

  function changeName() { // 改变姓名
    person.name = '李四'
  }

  function changeAge() { // 改变年龄
    person.age ++;
  }

  function changePerson() { // 改变整个人
    Object.assign(person, { name: '王五', age:  90})
  }

  // 监听reactive定义的 对象类型 数据,默认是开启深度监视的,就算person变化了一点,都会触发回调函数
  watch(person, (newVal, oldVal) => { // 监听person的变化
    console.log('person 变化了', newVal, oldVal);
  });

</script>

<template>
  <div class="class">
    <h2>姓名:{{ person.name }}</h2>
    <br/>
    <h2>年龄:{{ person.age }}</h2>
    <button @click="changeName">修改姓名</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changePerson">修改整个人</button>
  </div>
</template>

<style scoped>
  .class {
    background-color: #f8f9fa; /* 背景颜色 */
    padding: 20px; /* 内边距 */
    border-radius: 10px; /* 圆角 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
    text-align: center; /* 文本居中 */
    max-width: 500px; /* 最大宽度 */
    margin: 0 auto; /* 水平居中 */
  }

  button {
    background-color: blue;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    margin: 10px 10px 0 10px; /* 外边距 */
    transition: background-color 0.3s ease; /* 按钮背景颜色过渡效果 */
  }
</style>

在这里插入图片描述

4. 监视ref或reactive定义的对象数据类型中的某个属性

<script lang="ts" setup name="Watch04">
import { reactive, watch } from 'vue';
    let person = reactive({
        name: '张三',
        age: 20,
        Car: {
            name: '宝马',
            color: '红色'
        }
    });

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

    function changeAge() {
        person.age += 1;
    }

    function changeCarName() {
        person.Car.name = '奔驰';
    }

    function changeCarColor() {
        person.Car.color = '蓝色';
    }

    function changeCar() {
        person.Car= { name: '兰博基尼', color: '黑色' }
    }

    // 监听person中某个基本类型的值的变化,这里只监视person.name,
    // 要写成一个getter函数,() => { return person.name },这里简写了
    watch(() => person.name, (newVal, oldVal) => {
        console.log('person changed', newVal, oldVal);
    });

    // 监听person中某个对象的值的变化,这里监视person.Car,
    // 加上deep:true选项,可以监视对象内部值的变化(car.name, car.color)
    // 不加deep:true选项,只监视car对象本身的变化
    watch(() => person.Car, (newVal, oldVal) => {
        console.log('person changed', newVal, oldVal);
    }, { deep: true });
</script>

<template>
  <div class="class">
    <h2>姓名:{{ person.name }}</h2>
    <br/>
    <h2>年龄:{{ person.age }}</h2>
    <br/>
    <h2>车品牌:{{ person.Car.name }}</h2>
    <br/>
    <h2>车颜色:{{ person.Car.color }}</h2>
    <button @click="changeName">修改姓名</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeCarName">修改车品牌</button>
    <button @click="changeCarColor">修改车颜色</button>
    <button @click="changeCar">修改整辆车</button>
  </div>
</template>

<style scoped>
  .class {
    background-color: #f8f9fa; /* 背景颜色 */
    padding: 20px; /* 内边距 */
    border-radius: 10px; /* 圆角 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
    text-align: center; /* 文本居中 */
    max-width: 500px; /* 最大宽度 */
    margin: 0 auto; /* 水平居中 */
  }

  button {
    background-color: blue;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    margin: 10px 10px 0 10px; /* 外边距 */
    transition: background-color 0.3s ease; /* 按钮背景颜色过渡效果 */
  }
</style>

5.上述类型数组

<script lang="ts" setup name="Watch05">
import { reactive, watch } from 'vue';
    let person = reactive({
        name: '张三',
        age: 20,
        Car: {
            name: '宝马',
            color: '红色'
        }
    });

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

    function changeAge() {
        person.age += 1;
    }

    function changeCarName() {
        person.Car.name = '奔驰';
    }

    function changeCarColor() {
        person.Car.color = '蓝色';
    }

    function changeCar() {
        person.Car= { name: '兰博基尼', color: '黑色' }
    }
	// 监听person的name和Car属性
    watch([() => person.name, () => person.Car], (newVal, oldVal) => {
        console.log('person changed', newVal, oldVal);
    }, { deep: true });

</script>

<template>
  <div class="class">
    <h2>姓名:{{ person.name }}</h2>
    <br/>
    <h2>年龄:{{ person.age }}</h2>
    <br/>
    <h2>车品牌:{{ person.Car.name }}</h2>
    <br/>
    <h2>车颜色:{{ person.Car.color }}</h2>
    <button @click="changeName">修改姓名</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeCarName">修改车品牌</button>
    <button @click="changeCarColor">修改车颜色</button>
    <button @click="changeCar">修改整辆车</button>
  </div>
</template>

<style scoped>
  .class {
    background-color: #f8f9fa; /* 背景颜色 */
    padding: 20px; /* 内边距 */
    border-radius: 10px; /* 圆角 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
    text-align: center; /* 文本居中 */
    max-width: 500px; /* 最大宽度 */
    margin: 0 auto; /* 水平居中 */
  }

  button {
    background-color: blue;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    margin: 10px 10px 0 10px; /* 外边距 */
    transition: background-color 0.3s ease; /* 按钮背景颜色过渡效果 */
  }
</style>

WatchEffect

使用watch监视时需要传入需要监视的对象,当需要监视多个对象时就要先把这些对象先告诉watch,然后才能监视。但是当需要监视的对象太多时,需要将他们全部告诉watch,些许麻烦。watchEffect可以省略这一步,直接写对象变化后的处理。

<script lang="ts" setup name="WatchEffect">
import { ref, watchEffect } from 'vue';
    let temp = ref(30)
    let height = ref(10)

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

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

    // watchEffect 不需要传值,直接写监听对象处理函数
    watchEffect(() => {
      console.log('watchEffect', temp.value)
      if (temp.value > 50) {
        console.log('温度超过50度了,现在是', temp.value, '度')
      }
    })
</script>

<template>
  <div class="class">
    <h2>温度:{{ temp }}</h2>
    <br/>
    <h2>高度:{{ height }}</h2>
    <br/>
    <button @click="changeTemp">修改温度</button>
    <button @click="changeHeight">修改高度</button>
  </div>
</template>

<style scoped>
  .class {
    background-color: #f8f9fa; /* 背景颜色 */
    padding: 20px; /* 内边距 */
    border-radius: 10px; /* 圆角 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 阴影 */
    text-align: center; /* 文本居中 */
    max-width: 500px; /* 最大宽度 */
    margin: 0 auto; /* 水平居中 */
  }

  button {
    background-color: blue;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    margin: 10px 10px 0 10px; /* 外边距 */
    transition: background-color 0.3s ease; /* 按钮背景颜色过渡效果 */
  }
</style>

在这里插入图片描述

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值