最新版vue3+TypeScript开发入门到实战教程之watch详解

1、watch概述

watch本意是监视、观察。它的功能就是监视数据的变化。数据一旦变化,就会产生两种数据:新数据、旧数据。 如业务场景中,当订单量大多某个数时,就发放优惠卷。watch非常重要,掌握好响应式数据、computed、watch,vue写功能不会有太大问题。 在vue官网明确表达,watch可以监视以下四种数据:

  • ref定义的数据
  • reactive定义的数据
  • 函数返回一个值(getter函数
  • 包含上诉三种值的数组

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

  • 创建组件Fish
  • 引入ref、watch
  • 创建响应式数据name、price
  • watch函数监视price变化
  • 当price超过10,watch停止监视price变化
xml 复制代码
<template>
  <h2>鱼类:{{ name }}</h2>
  <h2>价格:{{ price }}</h2>
  <button @click="addPrice()">增加价格</button>
</template>
<script setup>
import { ref, watch } from 'vue'
let name = ref('鲫鱼');
let price = ref(5);
function addPrice() {
  price.value += 1;
}
let stopWatchPrice = watch(price, (newValue, oldValue) => {
  console.log(newValue, oldValue);
  if (newValue > 10) {
    console.log(stopWatchPrice);
    stopWatchPrice.stop();
  }
})
</script>

运行效果事例: 注意watch函数,监视的是price,而不是price.value。当点击按钮,price超过10,虽然数据在增加,但不再监视price。watch函数返回对象,有stop函数,调用此函数,即可解除监视。控制台打印,其结构如下:

scss 复制代码
() => {
    effect2.stop();
    if (scope && scope.active) {
      remove(scope.effects, effect2);
    }
  }

3、监视ref定义的对象类型数据

监视对象类型的数据,与基础类型的数据不同。当对象中的数据变化时,是无法监视到,但当整个数据改变时,是可以监视的。特点如下:

  • 创建组件Fish,引入ref、watch
  • 创建响应式对象fish,let fish = ref({ name: '鲫鱼', price: 5 });
  • 当改变fish.name值时,无法监视fish的变化
  • 当改变fish.price值时,无法监视fish的变化
  • 当改变整条鱼时,能够监视fish变化
xml 复制代码
<template>
  <h2>鱼类:{{ fish.name }}</h2>
  <h2>价格:{{ fish.price }}</h2>
  <button @click="changeName()">修改鱼类</button>
  <button @click="changePrice()">修改鱼价</button>
  <button @click="changeFish()">更换真个鱼</button>
</template>
<script setup>
import { ref, watch } from 'vue'
let fish = ref({ name: '鲫鱼', price: 5 });

function changeName() {
  fish.value.name += '~';
}
function changePrice() {
  fish.value.price += 1;
}
function changeFish() {
  fish.value = { name: '鲤鱼', price: 10 };
}
watch(fish, (newValue, oldValue) => {
  console.log(newValue, oldValue);
})

运行效果如下: 当修改响应式对象成员变量时,不会引起fish watch函数运行。原因在于watch监视的不是fish.name而是fish。那么如何才能监视fish.namefish.price数据变化呢? watch函数,它有三个参数

  • 一是监视对象
  • 二是监视回调函数,
  • 三是配置对象参数,如deep等等 只有在配置对象开启deep即可。
xml 复制代码
<template>
  <h2>鱼类:{{ fish.name }}</h2>
  <h2>价格:{{ fish.price }}</h2>
  <button @click="changeName()">修改鱼类</button>
  <button @click="changePrice()">修改鱼价</button>
  <button @click="changeFish()">更换真个鱼</button>
</template>
<script setup>
import { ref, watch } from 'vue'
let fish = ref({ name: '鲫鱼', price: 5 });

function changeName() {
  fish.value.name += '~';
}
function changePrice() {
  fish.value.price += 1;
}
function changeFish() {
  fish.value = { name: '鲤鱼', price: 10 };
}
watch(fish, (newValue, oldValue) => {
  console.log(newValue, oldValue);
}, { deep: true })
</script>

运行效果,仔细观看控制台打印的新数据、旧数据。

  • fish.name改变时,新旧数据一样
  • fish.price改变时,新旧数据一样
  • 当fish整个改变时,新旧数据不一样 效果如图: 注意fish.namefish.price,新旧数据是一样的。因为watch是从对象地址取到的数据。

4、watch监视函数返回一个值(getter函数)

它的功能是wath监视响应式对象中一个属性,如监视fish.name,是不允许直接监视,需要写成一个函数的形式。

  • 创建组件Fish,引入reactive, watch
  • 创建响应式对象fish,鱼的名字,鱼的体型:长度、重量
  • 分别监听鱼的名字与体型
  • 点击按钮修改鱼类,鱼的长度、鱼的重量、鱼的体型
xml 复制代码
<template>
  <h2>鱼类:{{ fish.name }}</h2>
  <h2>鱼长度:{{ fish.body.long }}</h2>
  <h2>鱼重量:{{ fish.body.weight }}</h2>
  <button @click="changeName()">修改鱼类</button>
  <button @click="changeFishLong()">修改鱼的长度</button>
  <button @click="changeFishWeight()">修改鱼的重量</button>
  <button @click="changeFishbody()">修改鱼的体型</button>
</template>
<script setup>
import { reactive, watch } from 'vue'
let fish = reactive({ name: '鲫鱼', body: { long: 1, weight: 24 } });

function changeName() {
  fish.name += '~';
}
function changeFishLong() {
  fish.body.long += 1;
}
function changeFishWeight() {
  fish.body.weight += 1;
}
function changeFishbody() {
  fish.body = { long: 100, weight: 300 };
}
watch(() => { return fish.name }, (newValue, oldValue) => {
  console.log('监听fish.name', newValue, oldValue);
})
watch(() => { return fish.body }, (newValue, oldValue) => {
  console.log('监听fish.body', newValue, oldValue);
})
</script>

监听响应式对象中的参数,需要写成一个箭头函数,并返回监听参数即可。具体操作,看下图: 当点击按钮,发现只有修改鱼类、修改鱼的体型,才能监听到变化。这是因为watch监听的地址。若想要能够监听到鱼的长度、鱼的重量,需要再watch加入deep参数即可。

javascript 复制代码
watch(() => { return fish.body }, (newValue, oldValue) => {
  console.log('监听fish.body', newValue, oldValue);
}, { deep: true })

注意点击按钮修改鱼的长度、修改鱼的重量,新旧数据是一致的。

5、watch监视含有响应式对象数组的数据

watch监视的对象是一个数组,数组内可以是ref定义基本类型数据,也可是对象,可以是函数。

javascript 复制代码
watch([() => { return fish.name },() => { return fish.body }], (newValue, oldValue) => {
  console.log('监听素组', newValue, oldValue);
}, { deep: true })

由于使用配置参数deep,操作效果如下:

具体代码

xml 复制代码
<template>
  <h2>鱼类:{{ fish.name }}</h2>
  <h2>鱼长度:{{ fish.body.long }}</h2>
  <h2>鱼重量:{{ fish.body.weight }}</h2>
  <button @click="changeName()">修改鱼类</button>
  <button @click="changeFishLong()">修改鱼的长度</button>
  <button @click="changeFishWeight()">修改鱼的重量</button>
  <button @click="changeFishbody()">修改鱼的体型</button>
</template>
<script setup>
import { reactive, watch } from 'vue'
let fish = reactive({ name: '鲫鱼', body: { long: 1, weight: 24 } });

function changeName() {
  fish.name += '~';
}
function changeFishLong() {
  fish.body.long += 1;
}
function changeFishWeight() {
  fish.body.weight += 1;
}
function changeFishbody() {
  fish.body = { long: 100, weight: 300 };
}
watch([() => { return fish.name },() => { return fish.body }], (newValue, oldValue) => {
  console.log('监听素组', newValue, oldValue);
}, { deep: true })
</script>

6、总结 watch可以监视四种数据,再加上配置函数,内容多且难记。在项目中多练习几次就能熟记。

  • ref定义的数据
  • reactive定义的数据
  • 函数返回一个值(getter函数
  • 包含上诉三种值的数组 在现实开发中,第一种和第三种情况最常用。尤其第三种情况,加函数,加配置参数deep。属于重中之重。
javascript 复制代码
watch(() => { return fish.body }, (newValue, oldValue) => {
  console.log('监听fish.body', newValue, oldValue);
}, { deep: true })
相关推荐
无心使然10 分钟前
Openlayers调用ArcGis要素服务之一 ——要素查询 (/query)
前端·javascript·数据可视化
焰火199915 分钟前
[前端]单文件上传组件
前端·vue.js
kyriewen1117 分钟前
Next.js部署:从本地跑得欢,到线上飞得稳
开发语言·前端·javascript·科技·react.js·前端框架·ecmascript
天天向上10241 小时前
openlayers 加载Shapefile文件
前端·javascript·html
wuxianda10301 小时前
苹果App上架4.3a问题3天解决方案汇报总结
开发语言·javascript·uni-app·ecmascript·ios上架·苹果上架
琹箐1 小时前
今天吃什么干什么随机生成
javascript·css·css3
卷Java1 小时前
ReAct范式实战:让Agent学会边想边做
javascript·react.js·大模型·llm·ecmascript·multi-agent
吴声子夜歌1 小时前
Vue3——UI组件库Element Plus(二)
javascript·vue.js·ui·elementplus
zhensherlock1 小时前
Protocol Launcher 系列:Beorg 高效任务管理的协议支持
前端·javascript·typescript·node.js·自动化·github·js
ppandss11 小时前
JavaWeb从0到1-DAY3.1- Vue(ii)
前端·javascript·vue.js