详解vue3中watch监听的几种情况

 更新时间:2025年03月28日 09:38:38   作者:蓝色海岛  
watch是CompositionAPI的一部分,用于监听响应式数据的变化并执行相应的操作,本文主要介绍了详解vue3中watch监听的几种情况,具有一定的参考价值,感兴趣的可以了解一下

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

watch的第一个参数直接写需要监听的数据名即可,监听的是其值的变化
    <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创建的对象类型

watch监听person时,监听的是person的地址值,只有当person的引用地址发生变化时才能监听得到,当写成Object.assign(person.value, { name: '李四', age: 90, son: { age: 5 } })时依然监听不到
当开启deep: true时,无论修改person中的哪个参数,包括son对象,都能监听得到

   <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创建的对象类型数据时,会自动开启深度监听

  <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定义的对象类型中的某个属性

监听的是对象的基本类型数据,要写成函数形式
监听的是对象的对象类型数据,可以写成函数形式,也可以直接写
监听的是对象的对象类型数据,并且改变对象时改变了应用地址,例如person.car = { ... },就必须要写成函数形式

 <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合并为一个:

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

总结:

监听ref创建的基本数据类型,必须直接写,不可以写成函数形式
监听ref创建的对象数据类型,可以直接写,也可以写成函数形式,需要开启deep: true
监听reactive创建的对象数据类型,必须直接写,不可以写成函数形式,默认开启了deep: true
监听ref或reactive创建的对象类型中的某个属性,该类型为基本数据类型,必须写成函数形式
监听ref或reactive创建的对象类型中的某个属性,该类型为对象数据类型,可以直接写,也可以写成函数形式,需要开启deep: true。如果想要监听引用地址变化,必须写成函数形式

序号情况是否使用函数写法是否需要手动开启深度监听
1监听ref创建的基本数据类型否。必须直接写,不可以写成函数形式
2监听ref创建的对象数据类型皆可。可以直接写,也可以写成函数形式
3监听reactive创建的对象数据类型否。必须直接写,不可以写成函数形式否。默认开启了深度监听
4监听ref或reactive创建的对象类型中的某个属性,该类型为基本数据类型是。必须写成函数形式
5监听ref或reactive创建的对象类型中的某个属性,该类型为对象数据类型皆可。可以直接写,也可以写成函数形式;如果想要监听引用地址变化,必须写成函数形式

到此这篇关于详解vue3中watch监听的几种情况的文章就介绍到这了,更多相关vue3 watch监听内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • VUE中拦截请求并无感知刷新token方式

    VUE中拦截请求并无感知刷新token方式

    这篇文章主要介绍了VUE中拦截请求并无感知刷新token方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • vite基本常见的配置讲解

    vite基本常见的配置讲解

    这篇文章主要给大家介绍了关于vite基本常见配置讲解的相关资料,最近做项目要求将webpack打包方式换成vite,下面将详细讲解一下配置vite需要改动的东西,需要的朋友可以参考下
    2023-11-11
  • vue项目使用.env文件配置全局环境变量的方法

    vue项目使用.env文件配置全局环境变量的方法

    这篇文章主要介绍了vue项目使用.env文件配置全局环境变量的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Vue与Node.js通过socket.io通信的示例代码

    Vue与Node.js通过socket.io通信的示例代码

    这篇文章主要介绍了Vue与Node.js通过socket.io通信的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • 解决vue-router 切换tab标签关闭时缓存问题

    解决vue-router 切换tab标签关闭时缓存问题

    这篇文章主要介绍了解决vue-router 切换tab标签关闭时缓存问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • Vue自定义指令实现checkbox全选功能的方法

    Vue自定义指令实现checkbox全选功能的方法

    下面小编就为大家分享一篇Vue自定义指令实现checkbox全选功能的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • Element修改弹窗类组件的层级的实现

    Element修改弹窗类组件的层级的实现

    本文主要介绍了Element修改弹窗类组件的层级的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 压缩Vue.js打包后的体积方法总结(Vue.js打包后体积过大问题)

    压缩Vue.js打包后的体积方法总结(Vue.js打包后体积过大问题)

    大家都知道,Vuejs的 CLI工具 是基于 webpack 来实现的,所以在项目打包后,会生成的文件会很大。 主要原因是 webpack 将我们所有文件都打包成一个js文件,即使再小的项目,打包之后文件都会变得很大。 下面讲讲最近我遇到的相同问题。
    2020-02-02
  • vue+echarts绘制省份地图并添加自定义标注方式

    vue+echarts绘制省份地图并添加自定义标注方式

    这篇文章主要介绍了vue+echarts绘制省份地图并添加自定义标注方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Vue中引入swiper报错的问题及解决

    Vue中引入swiper报错的问题及解决

    这篇文章主要介绍了Vue中引入swiper报错的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10

最新评论