直接用 computed 动态计算宽度,通过 ref 存储 window.innerWidth 并在 onMounted 中监听 resize 更新,computed 基于此响应式变量按比例、限制或 calc() 生成带单位的样式值,避免副作用与 DOM 直读。

直接用 computed 计算宽度,核心是把“当前屏幕宽”和“设计基准宽”挂钩,再结合缩放逻辑或比例约束,让宽度值随窗口实时变化。它不是写死像素,而是表达一种动态关系。
绑定窗口宽度并响应式更新
Vue 中的 computed 本身不监听事件,需配合 ref 或 reactive 存储当前宽度,并在 onMounted + window.addEventListener('resize') 中更新它。computed 再基于这个响应式变量做计算:
- 定义
const windowWidth = ref(window.innerWidth) - 在
onMounted里添加 resize 监听器,每次触发都赋值windowWidth.value = window.innerWidth - 用
computed(() => windowWidth.value / 1920)得到相对于 1920px 设计稿的缩放比
用 computed 输出 CSS 可用的 width 值
不要在 style 里硬写 width: {{ scaleRatio }}em,而是让 computed 返回带单位的字符串或数值,再绑定到内联样式或 class:
-
const containerWidth = computed(() => `${windowWidth.value * 0.8}px`)→ 宽度始终为视口 80% -
const cardWidth = computed(() => Math.max(320, Math.min(600, windowWidth.value * 0.4)))→ 限制最小 320px、最大 600px 的弹性卡片宽 - 配合
:style="{ width: containerWidth }"或:class="{ 'wide-layout': windowWidth.value > 1200 }"
结合 calc() 实现更灵活的布局表达
computed 可以生成符合 CSS calc() 语法的字符串,交由浏览器最终解析,避免 JS 过度干预样式逻辑:
-
const sidebarWidth = computed(() => `calc(${windowWidth.value}px - 240px)`)→ 左侧固定 240px,右侧自适应 -
const gridCols = computed(() => Math.floor(windowWidth.value / 320))→ 动态算出每行几列,再用grid-template-columns: repeat(v-model:gridCols, 1fr) - 注意空格:必须写成
`calc(100% - ${gap.value}px)`,不能省略运算符两侧空格
规避常见陷阱
computed 是同步求值机制,不适合直接读取 DOM 尺寸(如 offsetWidth),也不应包含副作用操作(如修改 state 或发请求):
- ❌ 错误:在 computed 里调用
document.querySelector(...).offsetWidth - ❌ 错误:在 computed 中执行
router.push()或api.fetch() - ✅ 正确:把 DOM 尺寸读取封装进 watch 或 onMounted 里的回调,只把结果作为响应式源供 computed 使用
- ✅ 正确:用
window.matchMedia替代频繁 resize,尤其在折叠屏或横竖屏切换场景下更稳定


















