You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
38 lines
1.0 KiB
38 lines
1.0 KiB
import { onMounted, onUnmounted, Ref } from 'vue'
|
|
|
|
export function useClickOutside(
|
|
elementRef: Ref<HTMLElement | null> | HTMLElement,
|
|
callback: (event: MouseEvent) => void,
|
|
options: {
|
|
ignore?: Ref<HTMLElement | null>[] // 需要忽略的元素
|
|
} = {}
|
|
) {
|
|
const { ignore = [] } = options
|
|
|
|
const handler = (event: MouseEvent) => {
|
|
const el = elementRef instanceof HTMLElement ? elementRef : elementRef.value
|
|
|
|
if (!el) return
|
|
|
|
// 检查点击是否在忽略的元素内
|
|
const isIgnored = ignore.some((ref) => {
|
|
const element = ref?.value
|
|
return element && (element === event.target || element.contains(event.target as Node))
|
|
})
|
|
|
|
if (isIgnored) return
|
|
|
|
// 检查点击是否在目标元素外
|
|
if (!(el === event.target || el.contains(event.target as Node))) {
|
|
callback(event)
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
document.addEventListener('click', handler, true)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
document.removeEventListener('click', handler, true)
|
|
})
|
|
}
|
|
|