vue3中watch监听的几种情况

一、监听ref创建的基本数据类型

watch的第一个参数直接写需要监听的数据名即可,监听的是其值的变化

js 复制代码
    <div>
      <h1>情况一:监视【ref】定义的【基本类型】数据</h1>
      <h2>当前求和为:{{ sum }}</h2>
      <el-button @click="changeSum">点我sum+1</el-button>
    </div>
    
    
    
// 数据
let sum = ref(0)
// 方法
function changeSum() {
  sum.value += 1
}
// 监视,情况一:监视【ref】定义的【基本类型】数据
const stopWatch = watch(sum, (newValue, oldValue) => {
  console.log('sum变化了', newValue, oldValue)
  if (newValue >= 10) {
    stopWatch()
  }
})

二、监听ref创建的对象类型

  1. watch监听person时,监听的是person的地址值,只有当person的引用地址发生变化时才能监听得到,当写成Object.assign(person.value, { name: '李四', age: 90, son: { age: 5 } })时依然监听不到
  2. 当开启deep: true时,无论修改person中的哪个参数,包括son对象,都能监听得到
js 复制代码
    <div>
      <h1>情况二:监视【ref】定义的【对象类型】数据</h1>
      <h2>姓名:{{ person.name }}</h2>
      <h2>年龄:{{ person.age }}</h2>
      <h2>儿子年龄:{{ person.son.age }}</h2>
      <el-button @click="changeName">修改名字</el-button>
      <el-button @click="changeAge">修改年龄</el-button>
      <el-button @click="changePerson">修改整个人</el-button>
      <el-button @click="changeSonAge">修改儿子年龄</el-button>
    </div>
    
// 数据
let person = ref({
  name: '张三',
  age: 18,
  son: { age: 5 }
})
// 方法
function changeName() {
  person.value.name += '~'
}
function changeAge() {
  person.value.age += 1
}
function changePerson() {
  person.value = { name: '李四', age: 90, son: { age: 5 } }
}
function changeSonAge() {
  person.value.son.age += 1
}
watch(
  person,
  (newValue, oldValue) => {
    console.log('person变化了', newValue, oldValue)
  },
  { deep: true }
)

三、监听reactive定义的对象类型数据,会默认开启深度监听

前面提到,如果是监听ref创建的对象类型数据,需要手动开启深度监听,而监听reactive创建的对象类型数据时,会自动开启深度监听

js 复制代码
    <div>
      <h1>情况三:监视【reactive】定义的【对象类型】数据</h1>
      <h2>姓名:{{ person.name }}</h2>
      <h2>年龄:{{ person.age }}</h2>
      <el-button @click="changeName">修改名字</el-button>
      <el-button @click="changeAge">修改年龄</el-button>
      <el-button @click="changePerson">修改整个人</el-button>
      <hr />
      <h2>测试:{{ obj.a.b.c }}</h2>
      <el-button @click="test">修改obj.a.b.c</el-button>
    </div>
    
// 数据
let person = reactive({ name: '张三', age: 18 })
let obj = reactive({ a: { b: { c: 666 } } })
// 方法
function changeName() {
  person.name += '~'
}
function changeAge() {
  person.age += 1
}
function changePerson() {
  Object.assign(person, { name: '李四', age: 80 })
}
function test() {
  obj.a.b.c += 888
}

// 监视,情况三:监视【reactive】定义的【对象类型】数据,且默认是开启深度监视的
watch(person, (newValue, oldValue) => {
  console.log('person变化了', newValue, oldValue)
})
watch(obj, (newValue, oldValue) => {
  console.log('Obj变化了', newValue, oldValue)
})

四、监听ref或reactive定义的对象类型中的某个属性

  1. 监听的是对象的基本类型数据,要写成函数形式
  2. 监听的是对象的对象类型数据,可以写成函数形式,也可以直接写
  3. 监听的是对象的对象类型数据,并且改变对象时改变了应用地址,例如person.car = { ... },就必须要写成函数形式
js 复制代码
    <div>
      <h1>情况四:监视【ref】或【reactive】定义的【对象类型】数据中的某个属性</h1>
      <h2>姓名:{{ person.name }}</h2>
      <h2>年龄:{{ person.age }}</h2>
      <h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
      <el-button @click="changeName">修改名字</el-button>
      <el-button @click="changeAge">修改年龄</el-button>
      <el-button @click="changeC1">修改第一台车</el-button>
      <el-button @click="changeC2">修改第二台车</el-button>
      <el-button @click="changeCar">修改整个车</el-button>
    </div>
    
// 数据
let person = reactive({ name: '张三', age: 18, car: { c1: '奔驰', c2: '宝马' } })
// 方法
function changeName() {
  person.name += '~'
}
function changeAge() {
  person.age += 1
}
function changeC1() {
  person.car.c1 = '奥迪'
}
function changeC2() {
  person.car.c2 = '大众'
}
function changeCar() {
  // person.car = { c1: '雅迪', c2: '爱玛' }
  Object.assign(person.car, { c1: '雅迪', c2: '爱玛' })
}
// 监视,情况四:监视响应式对象中的某个属性,且该属性是基本类型的,要写成函数式
watch(
  () => person.name,
  (newValue, oldValue) => {
    console.log('person.name变化了', newValue, oldValue)
  }
)
watch(
  () => person.car, // 如果使用 person.car = { ... } 必须要使用函数写法;如果使用Object.assign,可以直接写person.car
  (newValue, oldValue) => {
    console.log('person.car变化了', newValue, oldValue)
  },
  { deep: true }
)

如果需要监听多个数据,可以将2个watch合并为一个:

js 复制代码
watch(
  [() => person.name, () => person.car],
  (newValue, oldValue) => {
    console.log('person.car变化了', newValue, oldValue)
  },
  { deep: true }
)

总结:

  1. 监听ref创建的基本数据类型,必须直接写,不可以写成函数形式
  2. 监听ref创建的对象数据类型,可以直接写,也可以写成函数形式,需要开启deep: true
  3. 监听reactive创建的对象数据类型,必须直接写,不可以写成函数形式,默认开启了deep: true
  4. 监听ref或reactive创建的对象类型中的某个属性,该类型为基本数据类型,必须写成函数形式
  5. 监听ref或reactive创建的对象类型中的某个属性,该类型为对象数据类型,可以直接写,也可以写成函数形式,需要开启deep: true。如果想要监听引用地址变化,必须写成函数形式
序号 情况 是否使用函数写法 是否需要手动开启深度监听
1 监听ref创建的基本数据类型 否。必须直接写,不可以写成函数形式
2 监听ref创建的对象数据类型 皆可。可以直接写,也可以写成函数形式
3 监听reactive创建的对象数据类型 否。必须直接写,不可以写成函数形式 否。默认开启了深度监听
4 监听ref或reactive创建的对象类型中的某个属性,该类型为基本数据类型 是。必须写成函数形式
5 监听ref或reactive创建的对象类型中的某个属性,该类型为对象数据类型 皆可。可以直接写,也可以写成函数形式;如果想要监听引用地址变化,必须写成函数形式
相关推荐
csgo打的菜又爱玩1 小时前
Vue 基础(实战模板与命名指南)
前端·javascript·vue.js
ding_zhikai2 小时前
SD:在一个 Ubuntu 系统安装 stable diffusion Web UI
前端·ubuntu·stable diffusion
gerrgwg4 小时前
Vue-library-start,一个基于Vite的vue组件库开发模板
前端·javascript·vue.js
你的人类朋友5 小时前
【Node】单线程的Node.js为什么可以实现多线程?
前端·后端·node.js
iナナ5 小时前
Spring Web MVC入门
java·前端·网络·后端·spring·mvc
驱动探索者6 小时前
find 命令使用介绍
java·linux·运维·服务器·前端·学习·microsoft
开心不就得了6 小时前
自定义脚手架
前端·javascript
星晨雪海7 小时前
怎么格式化idea中的vue文件
前端·vue.js·intellij-idea
没事多睡觉6667 小时前
Vue 虚拟列表实现方案详解:三种方法的完整对比与实践
前端·javascript·vue.js
white-persist7 小时前
Burp Suite模拟器抓包全攻略
前端·网络·安全·web安全·notepad++·原型模式