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创建的对象类型中的某个属性,该类型为对象数据类型 皆可。可以直接写,也可以写成函数形式;如果想要监听引用地址变化,必须写成函数形式
相关推荐
斯~内克2 小时前
Electron 菜单系统深度解析:从基础到高级实践
前端·javascript·electron
数据知道2 小时前
【YAML】一文掌握 YAML 的详细用法(YAML 备忘速查)
前端·yaml
dr李四维2 小时前
vue生命周期、钩子以及跨域问题简介
前端·javascript·vue.js·websocket·跨域问题·vue生命周期·钩子函数
旭久2 小时前
react+antd中做一个外部按钮新增 表格内部本地新增一条数据并且支持编辑删除(无难度上手)
前端·javascript·react.js
windyrain3 小时前
ant design pro 模版简化工具
前端·react.js·ant design
浪遏3 小时前
我的远程实习(六) | 一个demo讲清Auth.js国外平台登录鉴权👈|nextjs
前端·面试·next.js
GISer_Jing3 小时前
React-Markdown详解
前端·react.js·前端框架
太阳花ˉ3 小时前
React(九)React Hooks
前端·react.js
拉不动的猪4 小时前
vue与react的简单问答
前端·javascript·面试