在 Vue.js 里,当使用数组遍历渲染页面元素并把 ref 存储到数据仓库(例如使用 Pinia 作为状态管理库)时,若数组数据删除使得页面上相关 DOM 节点移除,数据仓库里对应的 ref 不会自动删除。下面详细说明原因及解决办法。
原因分析
- 数据仓库的独立性:数据仓库(如 Pinia)是独立于 DOM 的状态管理系统,它不会自动感知 DOM 节点的变化。即便 DOM 节点被移除,数据仓库里存储的 ref 依然存在。
- Vue 的响应式更新:Vue 的响应式系统主要关注数据的变化并更新 DOM,但不会自动清理数据仓库里的 ref。
解决办法
要保证数据仓库里的 ref 和页面上的 DOM 节点同步,需要在数据更新时手动清理 ref。以下是一个示例:
import { defineStore } from 'pinia';
export const useSlideState = defineStore('slideState', {
state: () => ({
allDataObj: [
{ title: '本人信息', id: 0, flag: 1, comIndex: 1 },
{ title: '家庭信息', id: 1, flag: 1, comIndex: 2 },
{ title: '工作信息', id: 2, flag: 1, comIndex: 3 },
{ title: '其他信息', id: 3, flag: 1, comIndex: 4 },
],
slideFlag: { table1: 0, table2: 0, table3: 0, table4: 0 },
slideState: {
table1: 0,
table2: 0,
table3: 0,
table4: 0,
},
all: {
table1: [{ a: 1, b: 2 }, { c: 3, d: 4 }],
table2: [{ a: 1, b: 3 }]
},
// 假设这里存储 ref
itemRefs: []
}),
actions: {
removeItem(index) {
// 删除数组中的数据
this.allDataObj.splice(index, 1);
// 手动清理对应的 ref
this.itemRefs.splice(index, 1);
}
}
});
代码解释
- itemRefs:在状态里添加一个数组 itemRefs 来存储 ref。
- removeItem 方法:在删除 allDataObj 数组里的数据时,同时使用 splice 方法删除 itemRefs 数组中对应位置的 ref。
总结
数据仓库里存储的 ref 不会随 DOM 节点的删除自动清理,需要在数据更新时手动处理。