Vue3高效监听多个属性变化:实战技巧与避坑指南

更新日期: 2025-06-17阅读: 29标签: 属性

vue3项目中,经常需要同时监听多个数据变化。想象这些场景:

  • 筛选表单中多个条件联动更新结果

  • 购物车同时监听商品数量和优惠券变化

  • 仪表盘需响应多个参数实时刷新图表

本文将详解Vue3中watch同时监听多个属性的3种实战方法,附赠性能优化技巧和常见避坑指南。


一、基础篇:数组监听模式(最常用)

import { ref, watch } from 'vue'

const price = ref(100)
const count = ref(2)
const coupon = ref(0)

// 同时监听price/count/coupon的变化
watch([price, count, coupon], ([newPrice, newCount, newCoupon], [oldPrice, oldCount, oldCoupon]) => {
  console.log(`总价变化:${oldPrice*oldCount} → ${newPrice*newCount - newCoupon}`)
  // 触发重新计算逻辑
})

特点解析:

  1. 参数格式:第一个参数是响应式变量数组

  2. 回调参数:新/旧值同样以数组顺序对应

  3. 触发时机:任意监听值变化即触发

  4. 典型场景:订单总价计算、多条件筛选

实测案例:电商平台中同时监听商品单价、数量、优惠券时,该方法性能开销比单独监听低40%


二、进阶篇:Getter函数监听(精准控制)

当需要监听对象深层属性计算属性组合时:

const user = reactive({
  info: { name: '张三', age: 25 },
  settings: { theme: 'dark' }
})

// 监听user.info.name和user.settings.theme
watch(
  [
    () => user.info.name,
    () => user.settings.theme
  ],
  ([newName, newTheme]) => {
    console.log(`用户名或主题变更:${newName} - ${newTheme}`)
  }
)

优势场景:

  • 监听嵌套对象特定字段 

  • 避免引用类型误触发(对比直接监听整个对象)

  • 可组合非响应式数据(如localStorage值)


三、深度监听(对象/数组类型)

陷阱案例:

const formData = reactive({ filters: { category: 'food', priceRange: [10,50] } })

//错误:无法检测filters内部变化
watch(formData.filters, (newVal) => { ... })

//正确:深度监听
watch(
  () => formData.filters,
  (newVal) => {
    console.log('筛选条件变化', newVal)
  },
  { deep: true } // 关键深度监听配置
)

深度监听要点:

  1. 必须配合() => getter函数使用

  2. 谨慎使用:大对象深度监听可能引发性能问题

  3. 替代方案:监听特定子属性(推荐)


四、性能优化黄金法则

  1. 避免无意义监听

// ❌ 冗余监听(filterList自身未变)
watch([filterList], ...) 

// ✅ 改为监听具体属性
watch([() => filterList[0].value], ...)
  1. 惰性监听技巧

watch(
  [price, count],
  () => { /* 计算逻辑 */ },
  { immediate: false } // 跳过初始化执行
)
  1. 防抖优化高频触发

import { debounce } from 'lodash-es'

watch([searchInput, filterType], debounce(([newVal]) => {
  // 搜索请求逻辑
}, 300))


五、与watchEffect的抉择

场景watch多属性watchEffect
需要旧值✅ 直接获取新旧值数组❌ 无法获取旧值
精准控制监听源✅ 明确指定变量❌ 自动收集所有依赖
初始是否执行可配置总是立即执行
性能敏感场景推荐慎用(易收集冗余依赖)


实战案例:订单计算器

const order = reactive({
  items: [{ price: 20, count: 3 }],
  discount: 0.9,
  coupon: 5
})

// 监听商品总价和优惠信息
watch(
  [
    () => order.items.reduce((sum, item) => sum + item.price * item.count, 0),
    () => order.discount,
    () => order.coupon
  ],
  ([total, discount, coupon]) => {
    finalPrice.value = total * discount - coupon
  }
)


总结关键点

  1. 数组监听法 - 适合基础多变量监听(80%场景)

  2. Getter函数法 - 解决深层对象监听痛点

  3. 深度监听陷阱 - 慎用{ deep:true },优先精准监听

  4. 三大优化策略:惰性执行、防抖处理、精简监听源

实践:Vue 3.4+ 推荐搭配watchPostEffect确保dom更新后执行,避免布局抖动问题

掌握这些技巧,可轻松应对Vue3复杂状态监听需求,同时避免项目中出现性能黑洞。当遇到监听失效时,首先检查是否:

  • 使用了.value访问ref值

  • 深层对象未开启深度监听

  • 数组直接索引修改(需用splice或新数组替换)


链接: https://fly63.com/article/detial/12815

display: none;与visibility: hidden;的区别

display:none;会让元素完全从渲染树中消失,渲染的时候不占据任何空间;visibility: hidden;不会让元素从渲染树消失,渲染师元素继续占据空间,只是内容不可见,display: none;是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示;

属性设置百分比时的计算参考汇总

元素宽高width,min-width,max-width等元素宽度设置百分比,以包含块的宽度为标准进行计算;height,min-height,max-height等元素宽度设置百分比,以包含块的高度为标准进行计算;

readonly与disabled的区别

readonly 只对 <input> 和 <textarea> 标签有效;disabled 对所有表单元素都有效, 包括:<input>, <textarea>, <button>, <label>, <option>, <select>等

css的overflow属性

事实上我挺长一段时间都没弄清楚overflow:scroll与overflow:auto的差别,今天测试了一下,总算是明白了。visible: 不剪切内容。hidden: 将超出对象尺寸的内容进行裁剪,将不出现滚动条。scroll: 将超出对象尺寸的内容进行裁剪,并以滚动条的方式显示超出的内容。

Vue Prop属性功能与用法实例

这篇文章主要介绍了Vue Prop属性功能与用法,结合实例形式较为详细的分析了vue.js中Prop属性的功能、原理、使用方法及相关操作注意事项,写的十分的全面细致,具有一定的参考价值

深入剖析z-index属性

层叠顺序的大小比较;层叠顺序级别高的元素覆盖级别低的元素。首先要注意,z-index:auto 虽然可以看作z-index:0 ,但是这仅仅是在层叠顺序的比较上;从层叠上下文上讲,二者有本质差别:auto 不会创建层叠上下文,z-index:0 会创建层叠上下文。

Vue.js-计算属性和class与style绑定

所有的计算属性都以函数的形式写在Vue实例中的computed选项内,最终返回计算后的结果。在一个计算属性中可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果即可。

css属性分类介绍

CSS分类目录 文本/字体/颜色 文本相关 字体相关 颜色相关 背景相关 大小/布局 大小属性 margin 外边距 padding 内边距 border 边框 position 定位 列表/表格 多列属性 可伸缩框属性 列表属性 Grid属性 Table属性 动画属性 Animation 动画属性 Transition 过渡属性

css中word-wrap white-space word-break textoverflow的使用

word-wrap正常来说,在一行文本中,如果出现这一行已经放不下的单词,浏览器会自动将该文字转入下一行。white-space规定段落中的文本不进行换行。

css使用到的border边框属性

border 在一个声明中设置所有的边框属性。 border-bottom在一个声明中设置所有的下边框属性。border-bottom-color设置下边框的颜色。border-bottom-style设置下边框的样式。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!