vue3使用watch监听props的值的注意事项及说明

 更新时间:2025年06月11日 16:59:35   作者:慧慧吖@  
这篇文章主要介绍了vue3使用watch监听props的值的注意事项及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

在 Vue 的响应式系统中,直接监听 props.optionData 并启用 deep: true 仍失效的原因,主要与 响应式代理的复用机制 和 深度监听的实现逻辑 有关。

以下是具体分析:

一、核心原因:响应式代理的复用

父组件传递新对象的代理处理

父组件通过 computed 生成的 optionData 每次都是新对象,但 Vue 在子组件中接收 props.optionData 时会自动将其转换为 响应式代理对象(Proxy)。

若父组件传递的新对象与原代理对象的 结构相同,Vue 可能会 复用已有的代理实例,导致引用地址未发生明显变化。

此时,直接监听 props.optionData 实际监听的是代理对象的引用地址,而非父组件原始对象的地址。

  • deep: true 的局限性
  • deep: true 的作用是递归监听对象 所有层级的属性变化,但前提是 代理对象本身的引用地址已被正确追踪 。

若代理对象的引用地址未变(被复用),即使内部属性发生变化,Vue 也会认为 props.optionData 未发生“顶层”变化,从而跳过深度遍历。

二、实验验证与现象解释

  • 父组件代码示例
// 父组件每次生成新对象
const optionData = computed(() => ({
  title: 'Weekly Sales',
  xAxis: { data: categories.value },
  series: [{ data: values.value }]
}));
  • 子组件监听逻辑
// 直接监听 props.optionData(失效)
watch(
  props.optionData,
  (newVal) => {
    console.log('触发监听');
  },
  { deep: true } // 仍不触发
);
  • 现象解释

引用地址未变:Vue 复用代理对象,导致 props.optionData 的引用地址在子组件中未变化,因此 watch 认为未发生“顶层”变化,跳过深度检查。

依赖收集失败:deep: true 需要访问对象的所有属性以建立依赖关系,但若代理对象未触发属性访问(如未实际使用嵌套属性),依赖链可能不完整。

三、解决方案

  • 改用函数形式监听

通过 函数返回 props.optionData,强制 Vue 在每次依赖收集时重新获取原始值,绕过代理复用机制:

watch(
  () => props.optionData, // 动态获取最新值
  (newVal) => {
    console.log('触发监听');
  },
  { deep: true }
);
  • 强制生成唯一标识

在父组件中为对象添加 唯一键(如时间戳),确保每次生成的新对象结构不同,避免代理复用:

const optionData = computed(() => ({
  ...config,
  _key: Date.now() // 破坏结构一致性
}));
  • 显式触发引用变化

在子组件中手动比较新旧值的 序列化结果,强制触发更新:

watch(
  () => JSON.stringify(props.optionData),
  (newVal, oldVal) => {
    if (newVal !== oldVal) {
      console.log('触发监听');
    }
  }
);

总结

场景直接监听 props.optionData函数形式 () => props.optionData
代理复用可能复用代理,引用地址未变动态获取最新值,绕过代理复用
deep: true 生效条件依赖代理地址变化直接追踪原始对象变化
性能开销低(浅层监听)高(深度递归 + 动态依赖收集)

推荐方案:

  • 优先使用函数形式监听,并结合 deep: true 确保深度属性变化的检测。
  • 若性能敏感,可通过唯一标识或序列化优化依赖链。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue + ElementUI表格内实现图片点击放大效果的两种实现方式

    Vue + ElementUI表格内实现图片点击放大效果的两种实现方式

    这篇文章主要介绍了Vue + ElementUI表格内实现图片点击放大效果的两种实现方式,第一种使用el-popover弹出框来实现而第二种使用v-viewer插件实现,需要的朋友可以参考下
    2024-08-08
  • Vue前端打包的详细流程

    Vue前端打包的详细流程

    这篇文章主要介绍了Vue前端打包的详细流程,下面文章围绕Vue前端打包的相关资料展开详细内容,需要的小伙伴可以参考一下,希望对大家有所帮助
    2021-11-11
  • vue-router传参的4种方式超详细讲解

    vue-router传参的4种方式超详细讲解

    我们在组件切换时经常会有传递一些数据的需求,这样就涉及到了路由传参的问题,下面这篇文章主要给大家介绍了关于vue-router传参的4种超详细方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • 前端面试之vue2和vue3的区别有哪些

    前端面试之vue2和vue3的区别有哪些

    这篇文章主要为大家介绍了前端面试之vue2和vue3的区别有哪些,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • vue中的vue-print-nb如何实现页面打印

    vue中的vue-print-nb如何实现页面打印

    这篇文章主要介绍了vue中的vue-print-nb如何实现页面打印,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • VUE+Element环境搭建与安装的方法步骤

    VUE+Element环境搭建与安装的方法步骤

    这篇文章主要介绍了VUE+Element环境搭建与安装的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • Vuex状态机的快速了解与实例应用

    Vuex状态机的快速了解与实例应用

    Vuex是专门为Vuejs应用程序设计的状态管理工具,这篇文章主要给大家介绍了关于Vuex状态机快速了解与实例应用的相关资料,需要的朋友可以参考下
    2021-06-06
  • Vue render渲染时间戳转时间,时间转时间戳及渲染进度条效果

    Vue render渲染时间戳转时间,时间转时间戳及渲染进度条效果

    这篇文章主要介绍了Vue render渲染时间戳转时间,时间转时间戳及渲染进度条效果,通过实例代码相结合的形式给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-07-07
  • Vue.js实现简单计时器应用

    Vue.js实现简单计时器应用

    这篇文章主要为大家详细介绍了Vue.js实现简单计时器应用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互的实例

    Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互的实例

    这篇文章主要介绍了Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互的实例,帮助大家更好的理解和学习vue,感兴趣的朋友可以了解下
    2020-11-11

最新评论