fix: 解决父容器相同时,后渲染的水印没有防御功能的问题

This commit is contained in:
pany 2023-08-31 22:13:36 +08:00
parent f3e71e0795
commit 413305322d

View File

@ -1,7 +1,7 @@
import { type Ref, onBeforeUnmount, ref } from "vue" import { type Ref, onBeforeUnmount, ref } from "vue"
import { debounce } from "lodash-es" import { debounce } from "lodash-es"
type TargetNode<T> = T & { _mutationObserver?: MutationObserver; _resizeObserver?: ResizeObserver } type Observer = { mutationObserver?: MutationObserver; resizeObserver?: ResizeObserver }
type DefaultConfig = typeof defaultConfig type DefaultConfig = typeof defaultConfig
@ -38,6 +38,11 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
let mergeConfig: DefaultConfig let mergeConfig: DefaultConfig
/** 水印元素 */ /** 水印元素 */
let watermarkEl: HTMLElement | null = null let watermarkEl: HTMLElement | null = null
/** 观察器 */
const observer: Observer = {
mutationObserver: undefined,
resizeObserver: undefined
}
/** 设置水印 */ /** 设置水印 */
const setWatermark = (text: string, config: Partial<DefaultConfig> = {}) => { const setWatermark = (text: string, config: Partial<DefaultConfig> = {}) => {
@ -124,9 +129,9 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
} }
/** 监听水印容器的变化DOM 变化 & DOM 大小变化) */ /** 监听水印容器的变化DOM 变化 & DOM 大小变化) */
const addParentElListener = (targetNode: TargetNode<HTMLElement>) => { const addParentElListener = (targetNode: HTMLElement) => {
// 防止重复添加监听 // 防止重复添加监听
if (targetNode._mutationObserver || targetNode._resizeObserver) return if (observer.mutationObserver || observer.resizeObserver) return
// 监听 DOM 变化 // 监听 DOM 变化
addMutationListener(targetNode) addMutationListener(targetNode)
// 监听 DOM 大小变化 // 监听 DOM 大小变化
@ -134,17 +139,17 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
} }
/** 移除对水印容器的监听 */ /** 移除对水印容器的监听 */
const removeParentElListener = (targetNode: TargetNode<HTMLElement>) => { const removeParentElListener = (targetNode: HTMLElement) => {
// 移除 mutation 监听 // 移除 mutation 监听
targetNode._mutationObserver?.disconnect() observer.mutationObserver?.disconnect()
targetNode._mutationObserver = undefined observer.mutationObserver = undefined
// 移除 resize 监听 // 移除 resize 监听
targetNode._resizeObserver?.unobserve(targetNode) observer.resizeObserver?.unobserve(targetNode)
targetNode._resizeObserver = undefined observer.resizeObserver = undefined
} }
/** 监听 DOM 变化 */ /** 监听 DOM 变化 */
const addMutationListener = (targetNode: TargetNode<HTMLElement>) => { const addMutationListener = (targetNode: HTMLElement) => {
// 观察器的配置(需要观察哪些变动) // 观察器的配置(需要观察哪些变动)
const mutationObserverOptions: MutationObserverInit = { const mutationObserverOptions: MutationObserverInit = {
// 观察目标节点属性变动 // 观察目标节点属性变动
@ -173,24 +178,22 @@ export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
}) })
}, 500) }, 500)
// 创建一个观察器实例并传入回调 // 创建一个观察器实例并传入回调
const mutationObserver = new MutationObserver(mutationCallback) observer.mutationObserver = new MutationObserver(mutationCallback)
// 以上述配置开始观察目标节点 // 以上述配置开始观察目标节点
mutationObserver.observe(targetNode, mutationObserverOptions) observer.mutationObserver.observe(targetNode, mutationObserverOptions)
targetNode._mutationObserver = mutationObserver
} }
/** 监听 DOM 大小变化 */ /** 监听 DOM 大小变化 */
const addResizeListener = (targetNode: TargetNode<HTMLElement>) => { const addResizeListener = (targetNode: HTMLElement) => {
// 当 targetNode 元素大小变化时去更新整个水印的大小 // 当 targetNode 元素大小变化时去更新整个水印的大小
const resizeCallback = debounce(() => { const resizeCallback = debounce(() => {
const { clientWidth, clientHeight } = targetNode const { clientWidth, clientHeight } = targetNode
updateWatermarkEl({ width: clientWidth, height: clientHeight }) updateWatermarkEl({ width: clientWidth, height: clientHeight })
}, 500) }, 500)
// 创建一个观察器实例并传入回调 // 创建一个观察器实例并传入回调
const resizeObserver = new ResizeObserver(resizeCallback) observer.resizeObserver = new ResizeObserver(resizeCallback)
// 开始观察目标节点 // 开始观察目标节点
resizeObserver.observe(targetNode) observer.resizeObserver.observe(targetNode)
targetNode._resizeObserver = resizeObserver
} }
/** 在组件卸载前移除水印以及各种监听 */ /** 在组件卸载前移除水印以及各种监听 */