matchmedia 监听不到变化是因为它返回的是静态快照,matches 属性仅在创建时取值,必须用 addeventlistener('change', handler) 显式监听;移除时需传入相同函数引用以防内存泄漏;ssr 环境需检查 window.matchmedia 是否存在;多查询应独立管理而非合并。

matchMedia 为什么监听不到变化?
直接调用 matchMedia 返回的 MediaQueryList 对象,不加监听器就指望它自动响应屏幕缩放或旋转——这是最常见的误用。它本身是静态快照,matches 属性只在创建时取值,后续变化不会自动更新。
必须显式绑定事件监听,且推荐用 addEventListener(现代标准),而不是已废弃的 addListener。
- 错误写法:
const mql = matchMedia('(max-width: 768px)'); console.log(mql.matches); // 只执行一次 - 正确做法:用
addEventListener('change', handler)订阅状态变更 - 注意:handler 函数内应重新读取
mql.matches,不要依赖闭包中旧的值
如何正确添加和移除 matchMedia 监听器?
监听器必须可清理,否则容易造成内存泄漏,尤其在组件卸载、单页应用路由切换时。
matchMedia 返回的对象支持 removeEventListener,但必须传入与添加时**完全相同的函数引用**——不能用匿名函数,也不能每次新建一个箭头函数。
- ✅ 正确:定义具名函数或保存函数引用:
const handler = () => { ... }; mql.addEventListener('change', handler); mql.removeEventListener('change', handler); - ❌ 错误:
mql.addEventListener('change', () => { ... }); mql.removeEventListener('change', () => { ... }); // 两个箭头函数不是同一引用 - 补充:部分旧环境(如 IE10)只支持
addListener/removeListener,需兼容时做判断
matchMedia 在 SSR 或服务端渲染环境会报错吗?
会。Node.js 环境没有 window 和 matchMedia,直接执行会抛出 ReferenceError: window is not defined 或 TypeError: matchMedia is not a function。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
React/Vue 等框架的服务端渲染阶段必须做运行时检查,不能简单包裹 typeof window !== 'undefined' 就完事——还要确保 window.matchMedia 存在且为函数。
- 安全写法:
if (typeof window !== 'undefined' && window.matchMedia) { const mql = window.matchMedia(...); } - 更稳妥:用 try/catch 包裹整个初始化逻辑,避免因 UA 模拟或特殊运行时导致意外失败
- 注意:Next.js 等框架的
useEffect内执行天然安全,但自定义 Hook 或工具函数仍需手动防护
监听多个媒体查询时,要不要合并成一个 query?
不要强行合并。比如把 (max-width: 768px) 和 (prefers-reduced-motion: reduce) 硬拼成一个字符串,会导致语义混乱、调试困难,且无法单独响应不同条件。
每个 matchMedia 实例独立管理,互不影响。实际项目中建议按功能拆分,例如:
- 布局适配:用
matchMedia('(min-width: 1024px)') - 动效偏好:用
matchMedia('(prefers-reduced-motion: reduce)') - 深色模式:用
matchMedia('(prefers-color-scheme: dark)')
每个实例各自绑定 handler,各自清理。合并在逻辑上无收益,反而增加耦合和排查成本。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










