vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3中ref数组的监听

Vue3中ref数组的监听实现方式

作者:BillKu

Vue3中监听ref定义的数组,需根据监听需求选择合适的监听方法,对于空数组,推荐使用深度监听来捕捉数组内部变化,同时,确保修改数组的方式是响应式的,以保证监听器能正常工作,根据具体需求,可以选择直接深度监听、监听数组长度变化或提取属性监听等方案

在Vue 3中,监听一个由 ref 定义的数组【特别是像你这样初始化为空数组的情况 const jjdData = ref<JJD[]>([])】,关键在于理解你希望监听何种类型的变化。

下面用一个表格汇总主要的监听场景和方法,方便你快速了解:

监听场景推荐写法说明
数组被整体替换watch(jjdData, (newVal) => { ... })监听整个数组的引用变化。
数组内部变化(增删元素)及元素自身变化watch(jjdData, (newVal) => { ... }, { deep: true })最常用。深度监听,可响应数组方法和元素属性的变化。
仅监听数组长度的变化watch(() => jjdData.value.length, (newLen) => { ... })只关心元素数量的增减,不关心具体内容变化。
监听数组中特定对象属性的变化watch(() => jjdData.value.map(item => item.someProperty), (newVals) => { ... })例如,只关心每个 JJD 对象的 id 或 name 属性是否变化。

监听器的详细写法与注意事项

1.基本监听与深度监听

对于你的 jjdData,如果它最初是空数组,然后在组件挂载后被赋值(例如通过异步请求),你需要使用深度监听来捕捉数组本身以及其内部对象元素的变化。

import { watch } from 'vue';

// 深度监听,可以响应数组替换、数组方法调用以及对象元素属性的变化
watch(
  jjdData,
  (newArray, oldArray) => {
    console.log('数组发生了变化', newArray);
    // 在这里执行你的副作用逻辑
  },
  { deep: true } // 关键配置
);

注意

当监听 reactive 定义的响应式数据时,会强制开启深度监视,但对于 ref 定义的数组,需要显式配置 deep: true

使用 deep: true 时,oldArray 可能与 newArray 相同,因为它们指向同一个响应式代理对象。

2.提取属性进行监听

如果只想监听数组内对象某些特定属性的集合变化,可以使用计算属性提取后再监听,这有助于减少不必要的回调。

import { watch, computed } from 'vue';

// 提取出所有需要监听的属性,组成一个新数组
const somePropertyList = computed(() => jjdData.value.map(item => item.someProperty));

watch(somePropertyList, (newValues, oldValues) => {
  // 比较 newValues 和 oldValues 来确定具体哪个索引的属性发生了变化
  console.log('某个对象的someProperty发生了变化', newValues);
});
// 或者使用getter函数
watch(
  () => jjdData.value.map(item => item.someProperty),
  (newVals, oldVals) => { ... }
);

3.动态管理监听器(适用于大型动态数组)

对于频繁增删元素的大型数组,如果需要为每个元素的特定属性建立单独的监听器,可以考虑动态管理监听器,但通常复杂度较高。

import { watch, onScopeDispose } from 'vue';

const stops = new Map(); // 用来存储每个监听器的停止函数

// 监听整个数组的变化,以管理针对每个元素的监听器
watch(
  () => [...jjdData.value],
  (newArr, oldArr) => {
    // 逻辑:对比新老数组,为新增元素创建监听器,为删除的元素移除监听器
    // ... (具体实现可参考搜索结果中的示例:cite[2])
  },
  { deep: true }
);

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

除非有非常精确的需求,否则更推荐使用前面提到的深度监听或提取属性监听的方法。

确保响应式变化的注意事项

为了让监听正常生效,你需要确保修改数组的方式是响应式的:

如何选择监听方案

总结

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

您可能感兴趣的文章:
阅读全文