最终代码如下:
import { DirectiveBinding } from 'vue';
// 用于存储 DOM 元素和 ResizeObserver 实例之间的映射关系
const resizeObservers = new WeakMap();
function handleResize(el: HTMLElement, binding: DirectiveBinding): void {
const onResize = binding.value;
let observer = resizeObservers.get(el);
if (!observer) {
// 如果当前元素上不存在 ResizeObserver 实例,则创建一个新的实例并进行监听
observer = new ResizeObserver((entries) => {
const entry = entries[0];
const width = Math.round(entry.contentRect.width);
const height = Math.round(entry.contentRect.height);
onResize({ width, height });
});
observer.observe(el);
resizeObservers.set(el, observer);
} else {
// 如果当前元素上已经存在 ResizeObserver 实例,则更新回调函数
observer.disconnect();
observer = new ResizeObserver((entries) => {
const entry = entries[0];
const width = Math.round(entry.contentRect.width);
const height = Math.round(entry.contentRect.height);
onResize({ width, height });
});
observer.observe(el);
resizeObservers.set(el, observer);
}
}
function removeResize(el: HTMLElement): void {
const observer = resizeObservers.get(el);
if (observer && observer.disconnect) {
observer.disconnect();
resizeObservers.delete(el);
}
}
export default {
mounted(el: HTMLElement, binding: DirectiveBinding) {
handleResize(el, binding);
},
updated(el: HTMLElement, binding: DirectiveBinding) {
handleResize(el, binding);
},
unmounted(el: HTMLElement) {
removeResize(el);
},
};
在上述示例代码中,我们使用了一个 WeakMap
对象 resizeObservers
来保存 DOM 元素和 ResizeObserver 实例之间的映射关系。在指令的 mounted
钩子函数中,我们首先尝试从 resizeObservers
中获取当前元素的 ResizeObserver 实例。如果不存在,则创建一个新的实例,并进行监听;如果已经存在,则直接更新回调函数即可。
在指令的 updated
钩子函数中,我们也直接调用 handleResize
函数进行处理,该函数会自动判断是否已经存在 ResizeObserver 实例并进行相应的更新操作。
在指令的 unmounted
钩子函数中,我们同样需要将当前元素上的 ResizeObserver 实例卸载,并从 resizeObservers
中删除对应的键值对。
对于每个需要使用 v-resize
指令的组件,我们只需要像下面这样在模板中使用即可:
<template>
<div v-resize="onResize">...</div>
</template>
<script>
export default {
methods: {
// 处理元素大小变化的回调函数
onResize({ width, height }) {
console.log(`width: ${width}, height: ${height}`);
},
},
};
</script>
在上述示例代码中,我们传递了一个处理元素大小变化的回调函数 onResize
给 v-resize
指令,并在该函数中进行相应的逻辑处理。