直接用 watcheffect 监听响应式 ref 的 screenwidth 实现动态布局控制,比纯 css 媒体查询更灵活,适用于图表重绘、条件加载组件、动画开关等行为层逻辑。

直接用 watchEffect 监听 window.innerWidth,配合响应式 ref 管理布局状态,比纯 CSS 媒体查询更灵活——尤其适合需要动态触发逻辑(比如图表重绘、组件加载、动画开关)的场景。
核心思路:把屏幕宽度变成响应式依赖
Vue 不允许直接在 watchEffect 中监听非响应式值(如 window.innerWidth),所以得先把它“包装”成响应式数据:
- 用
ref创建一个screenWidth,初始值为window.innerWidth - 在
window.resize回调中更新它,watchEffect就能自动追踪变化 - 避免重复绑定/解绑:用
onMounted和onUnmounted控制生命周期
基础实现代码(Vue3 + setup script)
以下是最简可用版本,已处理初始化、resize 同步和内存安全:
import { ref, onMounted, onUnmounted, watchEffect } from 'vue'
const screenWidth = ref(window.innerWidth)
onMounted(() => {
const updateWidth = () => { screenWidth.value = window.innerWidth }
window.addEventListener('resize', updateWidth)
onUnmounted(() => window.removeEventListener('resize', updateWidth))
})
watchEffect(() => {
if (screenWidth.value
<h3>结合真实 UI 场景的增强用法</h3>
<p>不只是改 class,还能驱动更复杂的交互行为:</p>
-
图表自适应重绘:当宽度突变时,主动调用 ECharts 的
resize()方法,避免模糊或错位 - 条件加载组件:小屏下懒加载精简版图表组件,大屏才加载带缩放/导出功能的完整版
-
动态设置字体根号:根据
screenWidth.value计算html.fontSize,让 rem 布局真正线性响应 -
手表级精细控制:对
的视口,强制切换为单列垂直流、放大点击区域、禁用 hover 效果
注意事项与避坑点
实际项目中容易忽略的关键细节:
- 不要在
watchEffect内直接操作 DOM 或调用第三方库方法(如echarts.init),应封装为可复用函数或组合式 API - 避免高频触发:resize 事件可能每秒触发数十次,
watchEffect本身有防抖机制,但业务逻辑里仍建议加节流(例如用setTimeout延迟执行重绘) - 服务端渲染(SSR)不适用:
window对象不存在,需加if (typeof window !== 'undefined')判断 - 与 CSS 媒体查询互补而非替代:CSS 处理视觉层(颜色、间距、显隐),
watchEffect处理行为层(加载、计算、通信)










