目录一、先给一个面试标准答案二、为什么不能只用 window.resize三、最推荐方案ResizeObserver1. 原理2. Vue 3 基本写法3. Vue 2 写法四、ResizeObserver 回调里能拿到什么五、在 Vue 中常见应用场景1. 图表自适应2. 表格 / 卡片自适应布局3. 弹窗 / 抽屉内容高度变化4. 文本折叠 / 展开判断5. 虚拟列表 / 自适应列表项高度六、Vue 中应该放在哪个生命周期Vue 3Vue 2七、如果元素是 v-if 控制的怎么办示例八、如果要更工程化怎么封装方案1封装成 HookuseResizeObserver.js使用方案2封装成自定义指令九、ResizeObserver 和 window.resize 的区别十、如果面试官问兼容性怎么处理十一、实际开发中要注意什么1. 记得清理 observer2. 避免在回调里做重计算3. 注意观察时机4. 注意循环触发问题十二、面试中怎么回答才算精彩高分回答模板十三、一个简洁好背版十四、代码模板面试可直接写Vue 3十五、顺手补一个追问如果监听很多元素怎么办十六、一句话总结这是 Vue 面试里一个很实用的问题。如果你只回答用window.onresize这个答案通常不够好因为它只能监听窗口大小变化但很多时候元素尺寸变化并不一定是窗口变化导致的比如父容器布局变化内容增减导致撑开折叠面板展开收起侧边栏伸缩字体加载完成后重排表格、图表、弹窗内部自适应所以更好的回答要体现你知道监听窗口变化和监听元素本身变化不是一回事Vue 里推荐怎么做生命周期怎么处理如何封装复用性能和兼容性怎么考虑一、先给一个面试标准答案在 Vue 中监听元素尺寸变化最推荐的方式是使用ResizeObserver。它可以直接监听某个 DOM 元素的宽高变化比监听window.resize更准确因为元素尺寸变化不一定由窗口变化引起。在 Vue 里通常会通过ref获取元素在mounted/onMounted中创建ResizeObserver在组件卸载时调用disconnect()清理。如果项目需要兼容老环境可以降级为window.resize、轮询或第三方方案但在现代项目中ResizeObserver是首选。如果这个能力要复用我会进一步封装成一个 Hook 或自定义指令。这段已经是比较完整的面试回答。二、为什么不能只用window.resize这是你回答里可以加分的点。window.resize只能监听浏览器窗口尺寸变化但元素尺寸变化有很多情况和窗口无关比如侧边栏展开 - 主内容区变窄 接口数据回来 - 卡片高度变高 Tab 切换 - 容器重新布局 弹窗内容变多 - 高度变化 flex / grid 布局重新计算 - 元素尺寸变化所以面试时你可以说window.resize只能算间接方案不够精准真正监听元素尺寸变化应该用ResizeObserver。三、最推荐方案ResizeObserver1. 原理ResizeObserver是浏览器提供的 API用来观察某个元素的内容区域或边框盒尺寸变化它和IntersectionObserver类似都是观察者模式。2. Vue 3 基本写法template div refboxRef classbox 内容区域 /div /template script setup import { ref, onMounted, onBeforeUnmount } from vue const boxRef ref(null) let observer null onMounted(() { observer new ResizeObserver((entries) { for (const entry of entries) { const { width, height } entry.contentRect console.log(元素宽度变化:, width) console.log(元素高度变化:, height) } }) if (boxRef.value) { observer.observe(boxRef.value) } }) onBeforeUnmount(() { observer observer.disconnect() }) /script style .box { width: 200px; min-height: 100px; background: #eee; } /style3. Vue 2 写法template div refbox classbox内容/div /template script export default { mounted() { this.observer new ResizeObserver((entries) { entries.forEach(entry { const { width, height } entry.contentRect console.log(width, height) }) }) this.observer.observe(this.$refs.box) }, beforeDestroy() { this.observer this.observer.disconnect() } } /script四、ResizeObserver回调里能拿到什么回调参数entries中每一项都是一个ResizeObserverEntry。最常用的是entry.contentRect.width entry.contentRect.height它表示元素内容区域的尺寸。例如const observer new ResizeObserver((entries) { const entry entries[0] console.log(entry.contentRect.width) console.log(entry.contentRect.height) })五、在 Vue 中常见应用场景这部分说出来很加分说明你不是只会 API。1. 图表自适应比如 ECharts、Chart.js 容器大小变了需要重新resizeobserver new ResizeObserver(() { chart.resize() })2. 表格 / 卡片自适应布局容器宽度变化后重新计算列数、断点或卡片排列。3. 弹窗 / 抽屉内容高度变化内容变化时重新定位底部按钮、滚动区域等。4. 文本折叠 / 展开判断监听容器高度变化决定是否展示“展开更多”。5. 虚拟列表 / 自适应列表项高度当列表项高度动态变化时进行重新测量。六、Vue 中应该放在哪个生命周期这个也是面试常考点。Vue 3初始化onMounted清理onBeforeUnmount或onUnmountedVue 2初始化mounted清理beforeDestroy/destroyed为什么因为要等 DOM 渲染出来才能拿到真实元素并开始观察。七、如果元素是v-if控制的怎么办这个是实际项目里很常见的问题。如果元素不是一开始就存在而是之后才渲染出来那就要监听它出现或在nextTick后再观察示例template div v-ifvisible refboxRef classbox/div /template script setup import { ref, watch, nextTick, onBeforeUnmount } from vue const visible ref(false) const boxRef ref(null) let observer null watch(visible, async (val) { if (val) { await nextTick() observer new ResizeObserver((entries) { const { width, height } entries[0].contentRect console.log(width, height) }) if (boxRef.value) { observer.observe(boxRef.value) } } else { observer observer.disconnect() observer null } }) onBeforeUnmount(() { observer observer.disconnect() }) /script八、如果要更工程化怎么封装这个很适合拿高分。方案1封装成 HookuseResizeObserver.jsimport { onMounted, onBeforeUnmount } from vue export function useResizeObserver(targetRef, callback) { let observer null onMounted(() { observer new ResizeObserver((entries) { callback(entries) }) if (targetRef.value) { observer.observe(targetRef.value) } }) onBeforeUnmount(() { observer observer.disconnect() }) }使用template div refboxRef classbox/div /template script setup import { ref } from vue import { useResizeObserver } from ./useResizeObserver const boxRef ref(null) useResizeObserver(boxRef, (entries) { const { width, height } entries[0].contentRect console.log(width, height) }) /script方案2封装成自定义指令export default { mounted(el, binding) { const observer new ResizeObserver((entries) { binding.value binding.value(entries[0]) }) observer.observe(el) el._resizeObserver observer }, unmounted(el) { el._resizeObserver el._resizeObserver.disconnect() } }使用template div v-resizehandleResize/div /template script setup const handleResize (entry) { console.log(entry.contentRect.width, entry.contentRect.height) } /script九、ResizeObserver和window.resize的区别这是面试很容易追问的点。对比项window.resizeResizeObserver监听对象浏览器窗口DOM 元素精准度低高是否能感知布局变化不一定可以适合场景响应式页面整体变化元素自适应、容器尺寸监听性能/语义一般更合理十、如果面试官问兼容性怎么处理你可以这样答ResizeObserver在现代浏览器里支持已经比较好了。如果项目有老旧浏览器兼容要求我会做降级处理比如优先用ResizeObserver不支持时退化成window.resize必要时配合节流、轮询或 polyfill这样回答比较稳。十一、实际开发中要注意什么这部分很加分。1. 记得清理 observer不清理容易内存泄漏尤其是列表、弹窗、keep-alive 场景。observer.disconnect()2. 避免在回调里做重计算尺寸变化可能会频繁触发如果你在回调里做大量计算性能会受影响。可以考虑节流防抖requestAnimationFrame延迟批处理3. 注意观察时机如果 DOM 还没挂载ref.value是null要在onMounted或nextTick后执行。4. 注意循环触发问题如果你在ResizeObserver回调里又直接修改了当前元素尺寸可能会再次触发 observer形成循环。比如observer new ResizeObserver(() { el.style.width el.offsetWidth 10 px })这种写法就有风险。十二、面试中怎么回答才算精彩如果想答得比别人更好不要只说“用ResizeObserver”而要体现三个层次原理场景工程化高分回答模板在 Vue 中监听元素尺寸变化我首选ResizeObserver。因为window.resize只能监听窗口大小变化而元素尺寸变化很多时候是由内容变化、父容器布局变化、flex/grid 重排等引起的不一定会触发窗口 resize。具体实现上我会通过ref获取目标元素在mounted/onMounted中创建ResizeObserver监听该元素的尺寸变化在回调里通过entry.contentRect.width和entry.contentRect.height获取最新宽高在组件销毁时调用disconnect()清理监听避免内存泄漏。如果是项目中的通用能力我通常会进一步封装成一个 Composition API Hook 或自定义指令方便多个组件复用。如果需要兼容老环境再降级到window.resize或 polyfill。像图表自适应、弹窗内容变化、表格容器变化这类场景ResizeObserver都非常适合。这段答出来已经属于比较出彩的回答了。十三、一个简洁好背版Vue 中监听元素尺寸变化推荐用ResizeObserver而不是只监听window.resize。因为元素尺寸变化不一定由窗口变化引起也可能是内容变化或布局变化导致的。在 Vue 里一般会通过ref获取元素在mounted/onMounted里开始观察在beforeUnmount时disconnect()清理。如果要复用可以封装成 Hook 或自定义指令。十四、代码模板面试可直接写Vue 3template div refboxRef classbox内容/div /template script setup import { ref, onMounted, onBeforeUnmount } from vue const boxRef ref(null) let observer null onMounted(() { observer new ResizeObserver(([entry]) { const { width, height } entry.contentRect console.log(width:, width) console.log(height:, height) }) if (boxRef.value) { observer.observe(boxRef.value) } }) onBeforeUnmount(() { observer observer.disconnect() }) /script十五、顺手补一个追问如果监听很多元素怎么办可以这样回答如果要监听很多元素我会尽量复用逻辑并注意性能避免在每次尺寸变化时做过重计算。可以把监听逻辑封装起来必要时对回调做节流或批处理。如果只是监听列表容器而不是每一项都要监听我会优先减少观察目标数量。这个很像有项目经验的人会说的话。十六、一句话总结Vue 中监听元素尺寸变化最推荐ref ResizeObserver比window.resize更精准并且要注意挂载时机、销毁清理和工程化封装。