如何通过对比新旧数组识别拖拽后位置变动的元素
如何通过对比新旧数组确定被拖拽的元素
场景说明
我们有一个代表可拖拽HTML元素的数组,元素顺序可通过拖拽改变。示例如下:
拖拽前的旧数组:
let oldArr = [{id: 'id1'}, {id: 'id2'}, {id: 'id3'}, {id: 'id4'}, {id: 'id5'}, {id: 'id6'}]
将元素id5拖拽至索引2的位置后,得到新数组:
let newArr = [{id: 'id1'}, {id: 'id2'}, {id: 'id5'}, {id: 'id3'}, {id: 'id4'}, {id: 'id6'}]
需求是通过对比新旧数组,确定哪个元素被拖拽到了新位置;若仅两个相邻元素交换顺序,无法判定时返回任意一个即可。
解决方案
核心思路
通过提取元素的唯一标识(这里是id)对比位置变化,找到发生跳跃性移动的元素:
- 先将两个数组转换为仅包含
id的序列,简化对比逻辑 - 遍历序列,找到第一个元素不匹配的索引位置
- 追踪该位置元素在另一个数组中的原始位置,判断是否为被拖拽的目标元素
- 相邻交换场景下,两个元素位置均变化,返回任意一个即可
代码实现
function findDraggedElement(oldArr, newArr) { const oldIds = oldArr.map(item => item.id); const newIds = newArr.map(item => item.id); for (let i = 0; i < oldIds.length; i++) { if (oldIds[i] !== newIds[i]) { // 查找新数组当前元素在旧数组中的位置 const oldPos = oldIds.indexOf(newIds[i]); if (oldPos !== -1 && oldPos !== i) { return newArr[i]; } // 查找旧数组当前元素在新数组中的位置 const newPos = newIds.indexOf(oldIds[i]); if (newPos !== -1 && newPos !== i) { return oldArr[i]; } // 相邻交换场景,返回任意一个元素 return newArr[i]; } } // 数组无变化时返回null return null; } // 测试示例 const oldArr = [{id: 'id1'}, {id: 'id2'}, {id: 'id3'}, {id: 'id4'}, {id: 'id5'}, {id: 'id6'}]; const newArr = [{id: 'id1'}, {id: 'id2'}, {id: 'id5'}, {id: 'id3'}, {id: 'id4'}, {id: 'id6'}]; console.log(findDraggedElement(oldArr, newArr)); // 输出:{id: 'id5'} // 测试相邻交换场景 const oldArr2 = [{id: 'a'}, {id: 'b'}]; const newArr2 = [{id: 'b'}, {id: 'a'}]; console.log(findDraggedElement(oldArr2, newArr2)); // 输出:{id: 'b'}(或{id: 'a'},取决于逻辑顺序)
逻辑说明
- 该方法针对单元素拖拽的常见场景设计,能快速定位被移动的元素
- 若数组完全未发生变化,返回
null - 相邻元素交换时,因无法判定哪个是主动拖拽的元素,代码会优先返回新数组第一个差异位置的元素,符合题目要求
内容的提问来源于stack exchange,提问作者Axel Productions 86
相关产品推荐
相关产品推荐

