我们使用了forEach
方法来遍历layerList.value
数组,并在遍历的过程中使用splice
方法来删除元素。为了解决直接修改数组长度可能导致的索引问题,我们采取了从后向前遍历的
以下是不对的
function resetChecked() {
// for (let i = 0; i < layerList.value.length; i++) {
// const item = layerList.value[i]
// item.checked = false
// dataChange(false, item)
// }
}
function dataChange(checked, node) {
if (checked) {
layerList.value.push(node)
} else {
layerList.value.splice(
layerList.value.findIndex(item => item.id === node.id),
1
)
}
}
策略。
下面是该方法的具体解释:
function resetChecked() {
for (let i = layerList.value.length - 1; i >= 0; i--) {
const item = layerList.value[i];
// 从后向前遍历,这样删除元素不会影响后续的索引
if (item.checked) {
item.checked = false;
// 调用dataChange函数,传递当前节点和'reset'作为type参数
dataChange(false, item, 'reset');
// 注意:这里没有立即删除元素,只是标记了checked为false
}
// 由于我们是从后向前遍历,所以即使数组的长度在循环中减少,
// 也不会影响前面的索引,因为i的值在每次循环时都会减1。
}
// 循环结束后,所有标记为checked的项都已经被遍历过,并且已经调用了dataChange
// 此时,可以安全地删除所有checked被设置为false的项
layerList.value = layerList.value.filter(item => item.checked);
}
在这个循环中:
-
layerList.value.length - 1
:我们从数组的最后一个元素开始遍历,这样做的原因是当我们删除元素时,后面的元素会向前移动,填补被删除元素的位置,这样就不会影响到未处理的元素的索引。 -
i >= 0
:这是循环的继续条件,只有当索引i
大于或等于0时,循环才会继续执行。 -
i--
:每次循环结束时,我们减少索引i
的值,这样就能保证我们总是从数组的末尾开始处理。 -
if (item.checked)
:我们检查当前遍历到的节点是否被选中(checked
属性为true
)。 -
item.checked = false
:如果节点被选中,我们将其checked
属性设置为false
,以取消选中。 -
dataChange(false, item, 'reset')
:调用dataChange
函数,通知其他部分节点状态的变化。这里的false
表示节点未被选中,item
是要操作的节点对象,'reset'
是一个特殊的标记,表示这是一次重置操作。 -
layerList.value = layerList.value.filter(item => item.checked)
:循环结束后,我们使用filter
方法创建一个新的数组,其中只包含checked
属性为true
的元素。这样就删除了所有未选中的节点,同时避免了在遍历过程中直接修改数组长度的问题。
通过从后向前遍历数组,我们可以确保在删除元素时不会影响到未处理的元素的索引,从而避免了潜在的错误。