【踩坑】Vue3 watch 数据源变化后没有执行回调函数

故事背景

watch 的数据源发生了变化,但是没有调用回调函数

问题定位

数据源是一个 getter 函数,getter 函数返回的是一个 ref 对象。

  • 预期的是: ref 的属性值发生变化后调用回调函数
  • 实际上是:当 watch 的数据源是一个 getter 函数时,回调函数只在函数的返回值发生变化时才会触发,又因为返回值是一个 ref 对象,对象的引用值没有变化,所以认为对象没有变化,不会触发回调函数的调用。

处理方案(2选1)

  1. 将数据源改为响应式对象,即,不使用 getter 函数(当数据源是响应式对象时,侦听器会自动启用深层模式)
  2. 使用 { deep: true } 强制侦听器进入深层模式

扩展内容

📌 注意:数据源使用值和 getter 函数时的区别 watch() 默认是懒监听的,即仅在数据源发生变化时才执行回调函数。

当使用 getter 函数作为数据源时,回调函数只在此函数的返回值发生变化时才会触发,如果想让回调在深层次变更时也能触发,需要使用 { deep: true } 强制侦听器启用深层模式。

js 复制代码
const state = reactive({ count: 0 })
watch(() => state, () => {
  /* 这里数据源是一个 getter 函数,回调函数只在返回值变化时才会触发
   * 因为返回值是一个对象,对象的值是否相同是基于对象在内存中的引用地址进行比较的
   * 在这个场景下,只是修改 state.count 的值,对象在内存中的引用地址不会变化,会被认为是同一个值,所以不会触发回调函数的调用
   * 如果期望在 state.count 变化后,调用回调函数,需要使用 { deep: true } 强制侦听器进入深层级模式
   */
})

当直接侦听一个响应式对象时,侦听器会自动启用深层模式:

js 复制代码
const state = reactive({ count: 0 })
watch(state, () => {
  /* 这里侦听的是一个响应式对象,侦听器默认启用深层次模式 */
})

1点思考

数据源应该优先考虑使响应式对象:ref/reactive(代码写的更少,还会自动启用深层模式)

如果想要侦听的数据不是响应式对象时再考虑使用 getter 函数

参考文档

cn.vuejs.org/api/reactiv...

相关推荐
好奇的候选人面向对象2 分钟前
实现一个左右树形结构一对一关联的组件。这个方案使用两个el-tree组件,并实现它们之间的互相关联选择。
javascript·vue.js·elementui
一 乐6 分钟前
旅游出行|基于Springboot+Vue的旅游出行管理系统设计与实现(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·旅游
我看刑8 分钟前
【已解决】el-date-picker type=“datetime“限制(动态)可选时间范围,精确到分钟!!!
前端·javascript·vue.js
周周爱喝粥呀1 小时前
【基础】Three.js 实现 3D 字体加载与 Matcap 金属质感效果(附案例代码)
前端·javascript·vue.js·3d
局i9 小时前
Vue 指令详解:v-for、v-if、v-show 与 {{}} 的妙用
前端·javascript·vue.js
꒰ঌ小武໒꒱10 小时前
RuoYi-Vue 前端环境搭建与部署完整教程
前端·javascript·vue.js·nginx
局i11 小时前
Vue 中 v-text 与 v-html 的区别:文本渲染与 HTML 解析的抉择
前端·javascript·vue.js
+VX:Fegn089512 小时前
计算机毕业设计|基于springboot+vue的学校课程管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
一 乐13 小时前
水果销售|基于springboot + vue水果商城系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端
JIngJaneIL13 小时前
校园任务平台|校园社区系统|基于java+vue的校园悬赏任务平台系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·校园任务平台