Vue3中如何在for循环内监听数组指定索引的元素?
at(index)能监听数组单个元素变化 核心原因
Vue3的watch依赖追踪需要通过getter函数关联响应式数据源,直接传递数组元素值无法触发监听,而把数组元素的访问逻辑放在getter里,能让Vue追踪到数组本身的响应式变化。
具体拆解
直接监听
myArray.value[i]无效的问题
当你在循环里写watch(myArray.value[i], ...)时,myArray.value[i]会在循环执行时直接算出当前索引的元素值(比如第一个循环里就是{0: '1'}),watch拿到的是这个静态对象,和原响应式数组没有关联。后续即使数组该索引的元素被替换,watch也感知不到——因为它没追踪数组的响应式依赖,只盯着初始的那个对象。getter函数的作用
用() => head_blend_data.value.at(i)作为watch的第一个参数时,Vue会把这个函数当作依赖追踪的入口:每次触发监听检查时,都会执行这个函数,函数内部访问了响应式数组head_blend_data.value,并获取对应索引的元素。这相当于告诉Vue:“我要监听这个数组第i个位置的元素变化”。当数组该位置的元素更新时,getter函数执行的结果会变化,watch就会触发回调。Vue2和Vue3的差异
Vue2用$watch('arr.0', ...)能生效,是因为它基于Object.defineProperty对数组索引做了特殊处理;但Vue3改用Proxy后,不再支持这种字符串路径的监听方式,必须通过getter显式追踪对数组的访问操作。at(index)只是语法选择
这里用at和直接写head_blend_data.value[i]效果完全一样,关键是把访问数组元素的逻辑放在getter函数里,让Vue能捕捉到对响应式数组的依赖。比如换成下面的代码也能正常工作:watch(() => head_blend_data.value[i], (newVal) => { console.log(newVal, i) })
内容的提问来源于stack exchange,提问作者CaptainCrasi

