Appearance
17. Node.contains()
定义
MDN link: MDN Node.contains
Node.contains(otherNode)
返回一个布尔值,判断 otherNode
是否为 Node
的后代节点。下述三种情况,返回的为 true
:
otherNode
是Node
本身otherNode
是Node
的直接子节点otherNode
是Node
的子节点的所有后续子节点
使用场景
- 知道这个方法起源于一个需求:点击下拉菜单以外的地方,则收起该下拉菜单。需要使用
Node.contains()
方法判断是否点击了下拉菜单以外的地方。 - 双击表格中的单元格,则可以编辑单元格内容,点击外边(类似于
unblur
事件)则保存编辑的内容,变为普通表格。也需要这个方法来判断是否点击了该单元格外面。
判断是否点击了某一元素外面,使用 Vue3 + TS 封装的 useClickOutside.ts
hook 如下:(这里只是一个例子,思想是通用的,参考代码逻辑可以写出其他版本的,例如 React 或者原生 JS。)
ts
import { ref, onMounted, onUnmounted, Ref } from 'vue'
// 传入一个 Node/HTMLElement 不行,在 setup 中无法监控到,也就失去了响应式。
// 所以传入的参数应该是一个 Ref 的类型
export default function useClickOutside(
elmentRef: Ref<null | HTMLElement>,
): Ref {
const isClickOutside = ref(false)
// 点击回调事件
const handler = (e: MouseEvent) => {
/* 核心原理
* e.target 返回的是当前响应事件的元素
* 1、dropdown 节点包含 e.target,说明是在下拉菜单里面点的
* 2、dropdown 节点不含 e.target ,说明在外面点击的,就关闭下拉菜单
*/
if (elmentRef.value) {
// 类型不吻合,这里需要 as 断言
if (!elmentRef.value.contains(e.target as HTMLElement)) {
isClickOutside.value = true
} else {
isClickOutside.value = false
}
}
}
onMounted(() => {
document.addEventListener('click', handler)
})
onUnmounted(() => {
document.removeEventListener('click', handler)
})
// 最后返回这个 ref<boolean>
return isClickOutside
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33