场景:
有一串列表,点击列表某个 item 时给边框加粗,列表中只允许加粗一个 item。所以需要监听点击 item 外的事件,当点击 item 外时让边框变回原样,item 最左侧是一个展开/关闭内容的 svg 图标。
解决方法:
正常情况下,只需要使用 Node.contains
API 就可以解决,即点击发生时判断触发元素是否不包含在目标元素内,不包含说明在 item 外部触发了点击,这时候把边框还原就可以了。
核心代码:
handleClick = (e) => {
const el = this.getCurrentDom();
if (el && !el?.contains(e.target)) {
xxx // 执行边框还原的逻辑
}
};
遇到的问题:
当点击 svg 图标时,发现 el?.contains(e.target)
的执行结果是 false
的,也就是说 svg 元素没有包含在当前已展开内容的 item 的 dom 内,导致点击了 svg 图标之后边框也被还原了,但实际上 svg 图标在视觉上是在 item 内的,预期应该是点击了 item 内的 svg 图标也不应该让边框还原。
解决方法:
设置 svg 的元素样式属性 pointer-events
为 none
,让 svg 元素无法被事件捕获,不会成为点击事件的 event.target
,让 svg 父级元素被捕获执行相应的点击展开内容的逻辑,就不会被 el?.contains(e.target)
误判为 svg 不在当前 item 内。
遗留问题:
Node.contains
判断时为什么不会包含在父级元素的 dom 内?参考链接: