useClosePopupOnScroll
/**
* 当 popup 指定的最近一个父级元素滚动时,关闭 popup
*/
import { onUnmounted, ref } from 'vue';
// 寻找某个 el 最近的父元素
function findClosestParent(el, selector) {
if (typeof el.closest === 'function') {
return el.closest(selector);
} else {
// 对于不支持 closest 方法的浏览器, 我们可以使用 while 循环来向上遍历 DOM 树
while (el) {
if (el.matches(selector)) {
return el;
}
el = el.parentElement;
}
}
// 如果在 DOM 树中无法找到匹配的元素, 则返回 null
return null;
}
/**
* @parentSelector 指定的最近一个父级元素
* @popupContainer 指定的 popup 容器, 默认是 #app
*/
export function useClosePopupOnScroll(
parentSelector: string,
popupContainer = document.querySelector('#app'),
) {
const popupVisible = ref(false);
return {
popupVisible,
getPopupContainer(trigger) {
const parentElement = findClosestParent(trigger, parentSelector);
// 找不到直接返回
if (!parentElement) return popupContainer;
function closePopup() {
popupVisible.value = false;
}
parentElement.addEventListener('scroll', closePopup);
onUnmounted(() => {
parentElement.removeEventListener('scroll', closePopup);
});
return popupContainer;
},
};
}
使用
<template>
<a-popover
v-model:visible="popupVisible"
trigger="click"
placement="topLeft"
:getPopupContainer="getPopupContainer"
>
....
</a-popover>
</template>
<script setup lang='ts'>
import { useClosePopupOnScroll } from '@/hooks/web/useClosePopupOnScroll';
const { popupVisible, getPopupContainer } = useClosePopupOnScroll('.ant-table-body');
</script>