本文介绍在 Vue 3(尤其是组合式 API)中,如何在父组件挂载后准确获取其 DOM 宽度,并基于该宽度动态计算子组件尺寸(如方格大小),再通过 props 可靠传递给子组件,解决 ref 在 computed 中尚未就绪导致的 undefined 问题。 Vue 3 动态尺寸计算的问题与原因 在
Vue 3 根据父容器宽度动态计算并传递子组件尺寸
作者:技术拾光
时间:2026-06-18
浏览:570
文章目录
本文介绍在 Vue 3(尤其是组合式 API)中,如何在父组件挂载后准确获取其 DOM 宽度,并基于该宽度动态计算子组件尺寸(如方格大小),再通过 props 可靠传递给子组件,解决 ref 在 computed 中尚未就绪导致的 undefined 问题。
Vue 3 动态尺寸计算的问题与原因
在 Vue 3 里,如果你希望子组件(比如一个方格组件)的尺寸能严格跟随父容器(比如一个棋盘容器)的实际渲染宽度来动态变化——例如用 board.offsetWidth / rows 来计算每个方格的大小——那你很可能掉进过一个坑:直接在 computed 里访问 ref 的 DOM 属性,结果发现它根本行不通。
为什么呢?因为 computed 在组件初始化阶段就求值了,而此时 ref 绑定的 DOM 元素还没挂载上,board.value 自然是 undefined,计算自然就失败了。这不是 bug,而是 Vue 响应式系统的固有逻辑——computed 只依赖响应式数据,不关心 DOM 生命周期。
正确的解决方案:使用 ResizeObserver 在 onMounted 中动态更新
正确的解法是:把尺寸值声明为一个普通的 ref,然后在 onMounted 生命周期钩子里,借助 ResizeObserver 去监听父容器的尺寸变化,动态更新这个 ref。这么做的好处是,ResizeObserver 不仅能捕获初始挂载后的尺寸,还能在窗口缩放、布局变动时自动重算,保证尺寸始终是精准的。
来看优化后的父组件代码:
子组件这边就简单多了,只需要消费 squareSize:
关键注意事项与最佳实践
- 必须使用
onMounted:只有在这时,ref才指向真实 DOM,ResizeObserver才能开始监听。 -
ResizeObserver会自动响应变化:不仅处理初始尺寸,还能应对后续的浏览器缩放、父容器 CSS 变更等场景。 - 注意
width: 0.5vh这个写法:0.5vh 极小(在 1080p 屏幕上大约只有 0.9px),很可能导致offsetWidth为 0。建议结合min-width,或者改用vw、百分比等更稳健的单位。 - 别忘了在
onUnmounted里清理:这是好习惯,特别是在频繁切换路由的场景下,能有效避免内存泄漏。 -
v-for务必带上:key:示例中已经补上了:key="i",确保列表渲染的稳定性。
这套方案兼顾了准确性、响应性和可维护性。它是在 Vue 3 里处理“依赖 DOM 尺寸的动态 props”这类需求时,最标准、也最可靠的实践方式。
实用工具推荐
电子包浆
使用 ›绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
图片压缩
使用 ›选择画质和输出格式,预览压缩前后的大小。