Vue3监听对象数组属性变化方法

在Vue3中,监听对象数组中某个属性的变化可以通过以下几种方法实现:

方法一:深度监听整个数组并比较属性变化

使用 watch 函数并启用 deep: true,在回调中遍历比较新旧数组的特定属性。

javascript

复制

下载

复制代码
import { ref, watch } from 'vue';

const items = ref([
  { id: 1, name: 'A' },
  { id: 2, name: 'B' }
]);

watch(
  () => [...items.value], // 创建数组副本确保触发响应
  (newItems, oldItems) => {
    newItems.forEach((newItem, index) => {
      const oldItem = oldItems[index];
      if (oldItem && newItem.name !== oldItem.name) {
        console.log(`Item ${newItem.id}的name变化: ${oldItem.name} => ${newItem.name}`);
      }
    });
  },
  { deep: true }
);

优点 :简单易用,无需动态管理监听器。
缺点:任何数组或元素属性变化都会触发回调,需手动比较属性,可能影响性能。


方法二:为每个元素单独设置监听器

遍历数组并为每个对象的属性设置独立的 watch,动态管理监听器的生命周期。

javascript

复制

下载

复制代码
import { ref, watch, onBeforeUnmount } from 'vue';

const items = ref([
  { id: 1, name: 'A' },
  { id: 2, name: 'B' }
]);

const stops = new Map(); // 使用Map保存监听器的停止函数

// 初始化监听
const setupWatchers = () => {
  items.value.forEach(item => {
    if (!stops.has(item.id)) {
      const stop = watch(
        () => item.name,
        (newVal, oldVal) => {
          console.log(`Item ${item.id}的name变化: ${oldVal} => ${newVal}`);
        }
      );
      stops.set(item.id, stop);
    }
  });
};

// 监听数组变化,动态更新监听器
watch(
  () => [...items.value], // 触发数组变化
  (newItems, oldItems) => {
    // 移除已删除元素的监听
    oldItems.forEach(oldItem => {
      if (!newItems.some(item => item.id === oldItem.id)) {
        const stop = stops.get(oldItem.id);
        if (stop) {
          stop();
          stops.delete(oldItem.id);
        }
      }
    });
    // 添加新元素的监听
    newItems.forEach(newItem => {
      if (!stops.has(newItem.id)) {
        const stop = watch(
          () => newItem.name,
          (newVal, oldVal) => {
            console.log(`Item ${newItem.id}的name变化: ${oldVal} => ${newVal}`);
          }
        );
        stops.set(newItem.id, stop);
      }
    });
  },
  { deep: true, immediate: true }
);

// 组件卸载时清理所有监听
onBeforeUnmount(() => {
  stops.forEach(stop => stop());
  stops.clear();
});

优点 :精确监听目标属性,避免不必要的回调。
缺点:需手动管理监听器,逻辑较复杂。


方法三:提取属性数组并监听变化

使用 computed 提取所有目标属性,监听该数组的变化。

javascript

复制

下载

复制代码
import { ref, watch, computed } from 'vue';

const items = ref([
  { id: 1, name: 'A' },
  { id: 2, name: 'B' }
]);

const names = computed(() => items.value.map(item => item.name));

watch(names, (newNames, oldNames) => {
  newNames.forEach((newName, index) => {
    const oldName = oldNames[index];
    if (oldName !== undefined && newName !== oldName) {
      console.log(`索引${index}的name变化: ${oldName} => ${newName}`);
    }
  });
});

优点 :仅关注特定属性,减少比较范围。
缺点:无法直接关联到原对象,需通过索引处理。

TypeScript 复制代码
// 提取金额数组
const totalArray = computed(() => ckDetail.value.map((item) => item.total));
// 监听金额数组
watch(
  () => totalArray.value,
  () => {
    // 累计出库明细金额,得到出库总额
    ckMaster.value.total = totalArray.value.reduce((pre, cur) => pre + Number(formatToRMB(cur)), 0);
  }
);

总结

  • 推荐方法一:适用于数组较小或变化不频繁的场景,简单快捷。

  • 推荐方法二:适用于大型数组或需要精确控制的场景,但需处理动态监听。

  • 方法三:适用于只需知道属性变化的位置,不关心具体对象的场景。

相关推荐
agenIT3 分钟前
vue3 getcurrentinstance 用法
javascript·vue.js·ecmascript
代码老y7 分钟前
基于springboot的校园商铺管理系统的设计与实现
java·vue.js·spring boot·后端·毕业设计·课程设计·个人开发
码农捻旧15 分钟前
JavaScript 性能优化按层次逐步分析
开发语言·前端·javascript·性能优化
小辉懂编程21 分钟前
2025年最新基于Vue基础项目Todolist任务编辑器【适合新手入手】【有这一片足够了】【附源码】
前端·vue.js·编辑器
我是哈哈hh27 分钟前
【Vue3】生命周期 & hook函数 & toRef
开发语言·前端·javascript·vue.js·前端框架·生命周期·proxy模式
傻虎贼头贼脑42 分钟前
day28JS+Node-JS打包工具Webpack
开发语言·前端·javascript·webpack
Gazer_S2 小时前
【Vue Vapor Mode :技术突破与性能优化的可能性】
vue.js·性能优化
菥菥爱嘻嘻2 小时前
React---day2
前端·javascript·react.js
软件技术NINI2 小时前
html css js网页制作成品——HTML+CSS+js醇香咖啡屋网页设计(5页)附源码
javascript·css·html
coding随想2 小时前
多语言视角下的 DOM 操作:从 JavaScript 到 Python、Java 与 C#
java·javascript·python