uni-app(uni-app-x)自定义导航栏组件 uni-nav-bar 完全指南:安全区适配、三区布局与 slot 扩展
2026/9/20 13:08:59 网站建设 项目流程

uni-app(uni-app-x)自定义导航栏组件 uni-nav-bar 完全指南:安全区适配、三区布局与 slot 扩展

【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app

uni-nav-bar 是 uni-app / uni-app-x 官方提供的轻量级自定义导航栏组件,用于在页面关闭原生导航栏(navigationStyle: "custom")后,用纯声明式的方式重建顶部导航区域。本文将围绕该组件在仓库中的官方文档(readme.md)与真实源码(uni-nav-bar.vue)展开,带你掌握安全区适配原理、left/mid/right 三区布局、返回箭头、标题与前景色控制,以及如何用 slot 和外部 class 完成任意自定义。

一、组件定位:接管被关闭的原生导航栏

在 uni-app 中,页面默认自带原生导航栏。当页面需要沉浸式设计、自定义标题栏样式或与内容区域一体化时,通常会在pages.json中把该页面的导航样式改为自定义:

{ "pages": [ { "path": "pages/index/index", "style": { "navigationStyle": "custom" } } ] }

配置"navigationStyle": "custom"之后,原生导航栏不再渲染,页面顶部完全交由开发者自己控制。此时即可引入本组件替代原生导航栏。仓库自身的演示工程在 src/pages.json 中即为navbar-lite/navbar-lite页面配置了"navigationStyle": "custom",并在 navbar-lite.uvue 中直接使用了组件:

<uni-nav-bar :title="title" :is-left="isLeft" :navigationBarTextStyle="navigationBarTextColor"></uni-nav-bar>

从 package.json 的uni_modules.platforms声明可以看出,该组件的 uni-app-x 版本支持 Android、iOS、HarmonyOS、Web(safari/chrome)以及微信小程序端,属于纯跨端组件,无需额外原生依赖。

二、安全区适配与尺寸约定

组件在模板根部对顶部安全区做了自动适配(见 uni-nav-bar.vue):

<view style="flex-direction: row;padding-top: var(--status-bar-height);box-sizing: content-box;align-items: center;position: relative;">

核心要点:

  • 通过padding-top: var(--status-bar-height)让出顶部状态栏(刘海屏/挖孔屏)的高度,状态栏区域不再遮挡内容;
  • 外层使用box-sizing: content-box,确保内层内容高度不受 padding 影响;
  • 除去状态栏高度后,组件主体高度固定为44px,这也是 iOS 原生导航栏的标准高度,视觉上与系统保持一致;
  • 组件左右两边默认各让出 6px 边距(见样式区.uni-left-class-buildin { margin-left: 6px }.uni-right-class-buildin { margin-right: 6px }),让按钮不至于贴边。

需要自定义左右间距时,通过left-classright-class传入自定义样式类覆盖即可,同时组件底部也预留了--uni-safe-area-inset-bottom一类的安全区变量供页面内容使用(参见 navbar-lite.uvue 的用法)。

三、left / mid / right 三区布局

组件内部结构分为三个区域(见 uni-nav-bar.vue):

区域默认行为默认宽度自定义方式
left显示返回箭头(44×44px 点击区)44px(含 6px 左边距)slot name="left"替代;left-class修饰样式;hideDefaultBack隐藏箭头
mid显示title属性设置的标题屏幕宽度 − 左右边距 − left 宽 − right 宽(样式实现为left: 52px; right: 52px,即 6+44)slot name="mid"替代;mid-class修饰样式
right默认不显示内容44px(含 6px 右边距)slot name="right"填充内容;right-class修饰样式

从源码可以确认,mid 区域的绝对定位区间为left: 52px; right: 52px(注释中明确 52 = padding 6 + 44),因此标题默认居中于「两侧各 52px」的安全区间内。flatten属性用于降低该节点的层级负担,保证绝对定位内容正确覆盖。

3.1 left 区域:返回箭头与点击区放大

默认返回箭头并非使用图片,而是由两个 view 通过 CSS 旋转拼出的箭头(uni-nav-bar.vue):

<view v-if="!hideDefaultBack && slots['left']==null" style="width: 44px;height: 44px;justify-content: center;align-items: center;" @click="back"> <view style="width: 12px;height: 12px;transform: rotate(45deg); border-left: 2px solid; border-bottom: 2px solid;" :style="{borderLeftColor:foreColor,borderBottomColor:foreColor}"></view> </view>
  • 内层箭头大小为 12×12px、由左边框与下边框旋转 45° 组成;
  • 外层再套一层 44×44px 的透明容器以扩大点击区域,符合移动端最小触控尺寸规范;
  • 点击调用back(),其实现为uni.navigateBack({})(uni-nav-bar.vue),即返回上一页;
  • 传入hideDefaultBack可隐藏该箭头,此时leftslot 若存在则会替换显示。

3.2 mid 区域:标题与居中/居左切换

mid 区域在slots['mid']为空时渲染title文本,颜色由foreColor控制;传入slot name="mid"后 title 属性不再生效(readme 明确「如果传入 mid slot,则不生效」)。

组件还额外提供了isLeft布尔属性:为true时标题在 mid 区域内左对齐(justify-content: flex-start),否则居中(justify-content: center)。仓库示例页面 navbar-lite.uvue 正是通过点击切换isLeft来演示「标题居中 / 居左」两种形态。

3.3 right 区域:默认空白,slot 自由填充

right 区域默认不渲染任何内容,仅保留 44px 宽度占位,通过slot name="right"放入自定义按钮、文字或图标。

四、属性详解

完整属性定义见组件脚本区(uni-nav-bar.vue):

属性类型默认值说明
hideDefaultBackBooleanfalse是否隐藏默认返回箭头
titleString""标题文本;传入midslot 后不生效
navigationBarTextStyleString""返回箭头与标题的前景色,可选white/black(也支持#fff/#ffffff/#000/#000000等十六进制写法);不传时在非 MP 平台自动读取页面pageStylenavigationBarTextStyle
leftClassString""left 区域外部样式类
midClassString""mid 区域外部样式类
rightClassString""right 区域外部样式类
isLeftBooleanfalse标题是否左对齐(false 为居中)

4.1 navigationBarTextStyle 的前景色获取逻辑

源码中foreColor是一个computed,且存在平台差异(uni-nav-bar.vue):

  • 非 MP 平台:当外部未传入navigationBarTextStyle(为空字符串)时,通过getCurrentInstance()?.proxy?.$page?.getPageStyle()["navigationBarTextStyle"]自动获取页面pageStyle的默认值;只有显式传入时才以传入值为准。
  • MP(小程序)平台:小程序端无法获取pageStyle,因此foreColor直接等于传入的navigationBarTextStyle必须显式传入前景色,否则返回箭头与标题会使用默认色。

这意味着在微信小程序等 MP 端使用本组件时,请务必显式传入navigationBarTextStyle,避免出现颜色与页面风格不一致的情况。

4.2 动态切换前景色示例

仓库演示页 navbar-lite.uvue 展示了通过uni.setNavigationBarColor动态修改导航栏背景、再同步组件前景色的完整写法:

function setNavigationBarColor1() { uni.setNavigationBarColor({ frontColor: '#ffffff', backgroundColor: '#0000', success: () => { navigationBarTextColor.value = '#fff' }, fail: () => { /* ... */ }, complete: () => { /* ... */ } }) }

页面中的navigationBarTextColor为响应式变量,绑定到组件的:navigationBarTextStyle上,前景色随之联动更新。

五、插槽与外部类:三种自定义路径

组件支持两种自定义机制,对应 readme 中的描述:

  1. Slot 替换(内容级自定义)

    • slot name="left":整体替换 left 区域内容(替换后默认返回箭头不再渲染);
    • slot name="mid":替换 mid 区域内容(title属性失效);
    • slot name="right":填充 right 区域自定义内容。
  2. externalClasses(样式级自定义):组件通过defineOptions声明了externalClasses: ['left-class','mid-class','right-class'](uni-nav-bar.vue),在页面使用组件时给left-class/mid-class/right-class传入自定义 class,即可在不改组件源码的情况下覆盖三区样式——例如修改左右边距、调整标题字号、给 right 区增加底色等。

三区默认样式可在组件

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询