一、效果展示
二、代码
getSize.ts
import { ref, Ref, watchEffect } from "vue";
export const getWidth = (domRef: Ref<HTMLElement | null>) => {
const width = ref<number>(0);
const height = ref<number>(0);
const observer = new ResizeObserver(() => {
if (domRef.value) {
width.value = domRef.value.clientWidth;
height.value = domRef.value.clientHeight;
}
console.log("width", width.value);
});
//设置一个变量来存储dom元素,让ResizeObserver知道它要监听哪个元素
//因为domRef.value可能会变化,所以我们需要一个变量来存储它,这样我们就可以在domRef.value变化的时候取消监听,防止内存泄漏并提高性能
//如果在该函数中需要同时监听多个dom,可以考虑使用weakMap来存储dom和ResizeObserver实例
let observerDom: HTMLElement | null = null;
watchEffect(() => {
const newDom = domRef.value;
//如果我们传入的dom存在,就让ResizeObserver监听它
//如果我们传入的dom不存在,就让ResizeObserver取消监听
if (newDom) {
observerDom = newDom;
observer.observe(observerDom);
} else if (observerDom) {
observer.unobserve(observerDom);
}
});
return { width, height };
};
组件中使用:
<template>
<div class="page">
<div class="observerDom" ref="observerRef">{{ width.width }}</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { getWidth } from "./getSize";
const observerRef = ref();
const width = getWidth(observerRef);
</script>
<style scoped>
.page {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #8c4141;
}
.observerDom {
width: 60%;
height: 60px;
background-color: #f1f1f1;
}
</style>