在现代Web开发中,响应式设计已成为前端开发的“标配”。虽然 CSS 的 @media 媒体查询能解决大部分样式适配问题,但总有一些业务逻辑、数据交互、动画特效等需求必须依赖 JavaScript 进行动态响应。这时,window.matchMedia 就变得非常有用!
一、window.matchMedia 是什么?
window.matchMedia 是原生 JS 提供的 API,可以在代码中使用CSS媒体查询语法判断当前窗口是否符合特定条件,还能监控条件变化,极大丰富了响应式开发的能力。
核心功能:
- 判断页面是否匹配某个媒体查询条件
- 动态监听窗口变化,做出行为层、数据层的自适应调整
二、常见用法详解
const mql = window.matchMedia('(max-width: 768px)');
console.log(mql.matches); // true表示小屏(如手机),false表示大屏
matches: 当前窗口是否符合对应条件,布尔值- 查询条件可以任意使用 CSS 支持的 @media 语法,如 orientation、min-width、color-gamut等
三、监听窗口变化
想让代码能实时感知窗口变化,只需监听 change 事件:
const mql = window.matchMedia('(max-width: 768px)');
mql.addEventListener('change', (e) => {
if (e.matches) {
// 移动端
console.log('进入移动端模式');
} else {
// 桌面端
console.log('进入桌面端模式');
}
});
四、实际应用场景举例
- 智能菜单自适应:移动端只显示“汉堡”,桌面展示全功能菜单
- 多端素材动态切换:小屏走低清图片,大屏走高清资源
- 异步数据响应:小屏只拉取概要信息,大屏展示完整数据
- 交互细节切换:如动画、卡片宽高、侧栏布局等根据窗口及时调整
五、window.matchMedia 与 CSS @media 的区别
| 方向 | CSS @media | window.matchMedia |
|---|---|---|
| 控制目标 | 纯样式 | 样式 + JS 行为 |
| 响应方式 | 样式自动切换 | 可执行任意 JS 逻辑 |
| 实时性 | 样式自动应用 | 支持动态事件监听 |
| 场景 | 适合经典自适应布局 | 智能业务、动画、懒加载 |
这两者是互补关系,建议配合使用,保证体验和性能最优。css-tricks
六、进阶技巧
- 多条件组合:如 (min-width: 600px) and (orientation: landscape)
- 结合框架:React/Vue中可以做 hooks、watchers、全局配置等
- 解除监听:mql.removeEventListener('change', handler) 避免内存泄漏
- 多媒体类型支持:不仅可判断屏幕尺寸,还能判断打印模式等 window.matchMedia 的这两项进阶用法实际能为响应式开发带来灵活的适配能力:
多条件组合
-
matchMedia 支持完整 CSS 媒体查询语法,因此可以用
and/or等方式混合条件,比如:const mql = window.matchMedia("(min-width: 600px) and (orientation: landscape)"); if (mql.matches) { // 当前是宽屏并且为横屏 } -
任何复杂组合如颜色模式、分辨率、设备类型等都可以检测。实际开发常用于桌面与移动、平板横竖屏等各种场景的差异化体验处理。
-
还可以通过 change 事件动态监听这些模式的变化,实现自适应行为或布局即时切换。
结合框架:React/Vue实战
React
-
可以包装成自定义 Hook(如 useMediaQuery/useMatchMedia),在组件中直接用布尔值控制渲染:
function useMediaQuery(query) { const [matches, setMatches] = React.useState(window.matchMedia(query).matches); React.useEffect(() => { const mql = window.matchMedia(query); const handler = (e) => setMatches(e.matches); mql.addEventListener('change', handler); return () => mql.removeEventListener('change', handler); }, [query]); return matches; } // 用法:const isWideLandscape = useMediaQuery('(min-width: 600px) and (orientation: landscape)');
Vue
- 可以用 Vue 的 watcher/watchEffect 监听 matchMedia 结果变化,更新响应式数据并驱动模板切换。
- 或者借助如 vue3-mq 等库,全局管理媒体状态,任何组件都能访问这些适配状态。
解除监听:mql.removeEventListener('change', handler)
-
必须解绑,避免泄漏:监听事件后,如果组件卸载或响应模式切换,记得用
removeEventListener解绑,释放回调和内存,否则浏览器持续保留引用,导致回调“僵尸”与内存泄漏问题,影响性能或产生莫名 bug。 -
用法示例:
const mql = window.matchMedia('(max-width: 600px)'); const handler = (e) => { // 业务逻辑 }; mql.addEventListener('change', handler); // 在不再需要监听时 mql.removeEventListener('change', handler); -
兼容旧浏览器:部分老版本仅支持 addListener/removeListener,需兼容写法。
多媒体类型支持(不仅是屏幕尺寸)
-
更广泛场景:matchMedia 不只判断屏幕尺寸,还能检查设备类型和渲染模式。例如,响应“打印”样式:
// 检查是否处于打印预览模式 const printMql = window.matchMedia('print'); if (printMql.matches) { // 进入打印模式 } -
应用场景
- 检测横竖屏模式:
(orientation: portrait) - 检查是否在投影仪上显示:
(projection) - 响应“打印”媒体:
(media: print) - 动态切换 UI 或样式,满足多终端适配和无障碍需求.
- 检测横竖屏模式:
-
实际意义:这带来比 CSS 媒体查询更强的动态感知能力,可以让 JavaScript 也参与响应式交互和特定动作,比单纯切换样式更灵活。
七、常见误区与注意点
- 只在浏览器环境可用(window 对象存在时)
- 多处 addEventListener 后要合理移除
- 不同浏览器旧版实现细节可能有差异,需兼容处理(如 addListener/ removeListener)
八、结语
window.matchMedia 是现代前端响应式开发强力武器,不仅仅能做“适配”,还能提升页面智能水平和交互体验。CSS 解决“该怎么展示”,JS 进一步决定“该做什么和怎么做”,两者结合让你的Web项目适用于任何设备和场景!