uni.onWindowResize是最可靠的横竖屏监听方式,不依赖screen.orientation,跨端兼容性好;需在onUnload中清理监听,避免内存泄漏,且应配合CSS媒体查询和响应式变量实现布局适配。
uni.onWindowResize 是目前最可靠的监听方式
它不依赖设备 orientation api,而是基于窗口尺寸变化触发,跨端兼容性最好。h5、微信小程序、app 端均能稳定收到回调,且不会因 ios safari 不支持 screen.orientation 而失效。
使用时注意:
-
uni.onWindowResize返回的是res.size.windowWidth和res.size.windowHeight,判断横竖屏只需比较二者大小:windowWidth > windowHeight≈ 横屏(实际场景中足够可靠) - 必须在
onUnload中调用uni.offWindowResize清理监听,否则页面复用或跳转后可能引发重复执行或内存泄漏 - 不要和
window.addEventListener('resize')混用——H5 端虽可监听,但需手动removeEventListener,而uni.onWindowResize的生命周期更可控
为什么 screen.orientation.type 监听会失败
这个 Web API 在 iOS Safari 和微信小程序里根本不可用,调用 screen.orientation?.type 会返回 undefined 或直接报错。App 端虽有部分支持,但依赖原生层实现,行为不一致。
常见误用场景:
- 在 H5 页面里写
screen.orientation.addEventListener('change', ...)—— Safari 16+ 才开始有限支持,旧版静默失败 - 在小程序里试图读取
screen.orientation—— 微信基础库不暴露该对象,typeof screen.orientation就是'undefined' - 用它做横竖屏判断后直接操作 DOM —— 即使读到了,也难保证样式同步,不如交给 CSS 媒体查询或响应式变量
video 全屏后方向监听失效?不是监听问题,是控制权被劫持
用户点击 <video> 右上角全屏按钮后,iOS WKWebView 会接管 orientation 控制,导致之前设的横屏被覆盖,uni.onWindowResize 仍能触发,但 UI 已“卡”在错误方向。
应对要点:
- 给
<video>加@fullscreen-change="onFullscreenChange",在detail.fullscreen === true时立刻再调一次uni.setScreenOrientation({orientation: 'landscape-primary'}) - 必须提前关闭
controls和enable-danmu,否则原生播放器路径会绕过 JS 层所有方向设置 - Android 上
fullscreen-change可能不触发,所以不能只靠它;建议配合videoContext.requestFullScreen()的 Promise resolve 后补调
监听到变化后,布局适配别硬写 JS 切换
拿到 windowWidth > windowHeight 后,不要手动 document.querySelector 改 class 或 style。容易漏更新、难维护,还破坏响应式语义。
推荐做法:
- 用 Vue 响应式变量(如
isLandscape)驱动条件渲染,或绑定 class 名 - CSS 层优先用
@media (orientation: landscape)写布局规则,浏览器原生响应,性能更好 - 避免在监听回调里频繁调用
setData或this.$forceUpdate(),改用计算属性或 watch 配合防抖
onLoad 阶段就锁屏,大概率静默失败。一定要把关键操作挪到 onReady,必要时加 setTimeout(..., 300) 等 native view 就绪。


















