细心朋友可能已经发现了,我们在处理touchmovetouchend事件时,通过event.target属性获取的永远等于touchstart起始触发的元素。
也就是说当我们从A元素开始触屏,即使我们现在划到B元素上,event.target返回的还是A。
这个表现与mousemove事件的表现不一致。
可以通过下列方法获得事件真实的target。

document.elementFromPoint

首先可以获取事件触发时的坐标点,通过document.elementFromPoint方法获取当前点对应的元素

1
2
3
4
5
let params = {clientX: 0, clientX: 0};
let clientX = e.touches[0].clientX;
let clientY = e.touches[0].clientY;
params = {clientX, clientY};
let $target = document.elementFromPoint(params.clientX, params.clientY);

判断元素的子孙关系(parentNode、childNodes、isEqualNode)

上述方法获取元素会带来一个问题。
比如:页面元素的从属关系是A->B->C,当我们点击B元素的子元素C,我们获得的target是C。
那就可以遍历检测A与C的子孙关系,进一步获得我们更关心A元素和B元素的关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let el = '父元素A'
let index = -1; // B元素相对于A元素的索引
let aTargetEl = [];
// 遍历获取target元素在dom树中的路径
while ($target.tagName.toLowerCase() != 'body') {
aTargetEl.push($target);
$target = $target.parentNode;
}
for (let idx = 0, len = el.childNodes.length; idx < len; idx++) {
let child = el.childNodes[idx];
// 遍历A的子元素判断是否处于target元素的dom树路径中
for (let i = 0, l = aTargetEl.length; i < l; i++) {
let oEl = aTargetEl[i];
if (child.isEqualNode(oEl)) {
index = idx;
break;
}
}
}