自定义导航栏需手动处理状态栏、胶囊按钮适配及吸顶逻辑,不能仅靠navigationStyle: "custom";跨端需动态获取statusBarHeight和menuButtonBoundingClientRect,用公式计算customBarHeight,并通过@scroll+requestAnimationFrame实现可靠吸顶。

uni-app 自定义导航栏不能只靠 navigationStyle: "custom" 一配了事——它只是隐藏原生栏,后续所有高度计算、胶囊按钮对齐、状态栏适配、吸顶逻辑都得你手动扛。跨端不一致是最大陷阱,尤其微信/支付宝小程序根本不支持 position: sticky,H5 真机滚动也极易失效。
pages.json 配置后,为什么顶部留白或遮挡?
因为 navigationStyle: "custom" 只关掉了原生栏,但没帮你处理状态栏(statusBarHeight)和胶囊按钮(menuButtonBoundingClientRect)的占位。常见现象:iOS 上标题被状态栏盖住、安卓上返回按钮错位、鸿蒙里整个导航栏压在内容上。
- 必须在
onReady或nextTick后调用uni.getSystemInfo()和wx.getMenuButtonBoundingClientRect()获取真实尺寸 -
customBarHeight不是固定值,得按公式算:menuButton.bottom + menuButton.top - statusBarHeight - 自定义导航栏容器需设
padding-top: statusBarHeight + 'px',再用绝对定位或 flex 拉平胶囊按钮右侧区域
怎么让自定义导航栏在 scroll-view 里正确吸顶?
别用 position: sticky——小程序平台压根不识别该属性,H5 真机滚动时也常“掉下来”。唯一可靠路径是监听 @scroll 手动切 fixed 状态。
-
scroll-view必须设显式高度,例如height: calc(100vh - var(--status-bar-height) - 44px),否则@scroll事件不触发 - 吸顶临界点要用
offsetTop,但不能在mounted里直接取,得等 DOM 渲染完成,推荐onReady+uni.createSelectorQuery() - 吸顶后内容会突然上跳,必须加一个同高的占位
<view class="placeholder"></view>,高度建议用getComputedStyle动态读取,别硬写88rpx -
@scroll回调里禁止频繁查 DOM,用requestAnimationFrame节流,否则卡顿丢帧
封装成组件时,哪些 props 必须暴露?
跨端兼容的自定义导航栏组件,不能只传 title 和 backgroundColor,否则在不同设备上会错位或溢出。
- 必须接收
statusBarHeight和customBarHeight,由父页面统一提供,避免子组件重复调用系统 API -
fixed布尔值要可控,方便在非吸顶页(如首页)关闭 fixed 行为 -
barHeight建议设为 Number 类型,默认值取计算后的customBarHeight,而非写死90 - 左右按钮需支持图标路径(
leftIcon)、文本(leftText)和点击事件(@clickLeft),鸿蒙和 App 端对 image 加载时机敏感,文本 fallback 很关键
最易被忽略的是胶囊按钮右侧空白区域的宽度——它随机型变化极大,微信 iOS 和安卓差异明显,鸿蒙甚至可能没有胶囊按钮。不要试图用固定 padding 模拟,得用 menuButton.right - menuButton.left 动态撑开右侧容器,否则右按钮永远对不齐。


















