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);
  }
);

总结

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

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

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

相关推荐
Achieve前端实验室11 分钟前
【每日一面】async/await 的原理
前端·javascript·面试
姜至16 分钟前
el-calendar实现自定义展示效果
前端·vue.js
拉不动的猪31 分钟前
webpack分包优化简单分析
前端·vue.js·webpack
德莱厄斯37 分钟前
没开玩笑,全框架支持的 dialog 组件,支持响应式
前端·javascript·github
非凡ghost1 小时前
Affinity Photo(图像编辑软件) 多语便携版
前端·javascript·后端
非凡ghost1 小时前
VideoProc Converter AI(视频转换软件) 多语便携版
前端·javascript·后端
endlesskiller1 小时前
3年前我不会实现的,现在靠ai辅助实现了
前端·javascript
Zyx20071 小时前
用 JavaScript 打造 AI 大脑:前端开发者的新时代——基于 Brain.js 的浏览器端 NLP 实战
javascript·机器学习
麦麦大数据1 小时前
F035 vue+neo4j中医南药药膳知识图谱可视化系统 | vue+flask
vue.js·知识图谱·neo4j·中医·中药·药膳·南药
麦麦大数据2 小时前
F037 vue+neo4j 编程语言知识图谱可视化分析系统vue+flask+neo4j
vue.js·flask·知识图谱·neo4j·可视化·编程语言知识图谱