更新记录
1.0.0(2026-07-15) 下载此版本
自定义头部导航栏
平台兼容性
uni-app(3.8.0)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
kex-nav-bar
自定义导航栏(uni-app Vue3 / <script setup>)。
支持双标题、搜索态、左右插槽、自定义左侧图标、角标/多操作、滚动沉浸、渐变/毛玻璃、返回拦截。
本组件面向 Vue3。使用自定义导航栏的页面必须配置
"navigationStyle": "custom"。
平台兼容
| App | H5 | 微信小程序 | 支付宝 | 其它小程序 | 鸿蒙 |
|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ |
安装
- 将插件放入项目
uni_modules/kex-nav-bar - easycom 会自动引入,无需手动
import - 在
pages.json对应页面开启自定义导航:
{
"path": "pages/xxx/index",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": ""
}
}
基本用法
<template>
<kex-nav-bar
title="标题"
right-text="更多"
@clickRight="onRight"
/>
<view class="page-body">页面内容</view>
</template>
<script setup>
const onRight = () => {
uni.showToast({ title: '更多', icon: 'none' })
}
</script>
默认行为说明:
fixed默认开启,导航固定在顶部placeholder默认开启,页面内容不会被导航遮挡leftArrow+autoBack默认开启,点击左侧自动navigateBack- 微信小程序默认
capsule=true,右侧会自动避让胶囊按钮
详细用法
1. 双标题 + Loading
<kex-nav-bar
title="订单详情"
subtitle="待发货 · 预计明天送达"
:loading="true"
/>
2. 左侧:文字 / 隐藏箭头 / 自定义图标
<!-- 左侧文字(可与箭头同时显示) -->
<kex-nav-bar title="详情" left-text="返回" />
<!-- 不要返回箭头 -->
<kex-nav-bar title="首页入口" :left-arrow="false" />
<!-- 自定义左侧图片图标 -->
<kex-nav-bar
title="详情"
left-icon="/static/close.png"
:left-icon-size="20"
/>
leftIcon有值时优先于默认返回箭头。支持本地路径或网络图片。
3. 左侧:自定义点击事件
默认点击左侧会返回上一页。若要自己处理,请同时关掉 autoBack:
<template>
<kex-nav-bar
title="编辑"
left-icon="/static/close.png"
:auto-back="false"
@clickLeft="onClose"
/>
</template>
<script setup>
const onClose = () => {
// 自己处理:弹窗确认、关弹层、跳转等
uni.showModal({
title: '提示',
content: '确定离开?',
success: (res) => {
if (res.confirm) uni.navigateBack()
}
})
}
</script>
4. 左侧:插槽完全自定义
需要用 uni-icons、字体图标、多个按钮时,用 #left 插槽:
<template>
<kex-nav-bar title="筛选" :auto-back="false" @clickLeft="onLeft">
<template #left>
<image
src="/static/menu.png"
style="width: 22px; height: 22px"
mode="aspectFit"
/>
</template>
</kex-nav-bar>
</template>
<script setup>
const onLeft = () => {
console.log('点击左侧区域')
}
</script>
说明:
- 使用
#left后,内置箭头 /leftIcon/leftText不再渲染 - 外层左侧区域仍会触发
@clickLeft - 若插槽内部自己
@click.stop,可能拦掉外层事件,请按需处理
5. 返回拦截 beforeBack
仍走默认返回,但在返回前二次确认:
<script setup>
const beforeBack = async () => {
const [err, res] = await uni.showModal({
title: '提示',
content: '内容未保存,确定离开?'
})
// 返回 false 阻止返回;返回 true / undefined 继续返回
return !!(res && res.confirm)
}
</script>
<template>
<kex-nav-bar title="编辑资料" :before-back="beforeBack" />
</template>
6. 首页按钮 homeButton
栈底页无法返回时,可显示首页按钮:
<kex-nav-bar
title="个人中心"
home-button
home-url="/pages/index/index"
@clickHome="onHome"
/>
7. 右侧:文字 / 角标 / 多操作
<script setup>
const actions = [
{ text: '添加', badge: 3 },
{ text: '更多' }
]
const onRight = () => {
console.log('单按钮右侧')
}
const onAction = (item, index) => {
console.log('多操作', item, index)
}
</script>
<template>
<!-- 右侧文字 -->
<kex-nav-bar title="设置" right-text="保存" @clickRight="onRight" />
<!-- 数字角标:badge=数字;红点:badge=true -->
<kex-nav-bar
title="消息中心"
right-text="消息"
:badge="12"
@clickRight="onRight"
/>
<kex-nav-bar title="通知" right-text="未读" :badge="true" />
<!-- 多个右侧操作 -->
<kex-nav-bar
title="通讯录"
:right-actions="actions"
@clickAction="onAction"
/>
</template>
rightActions 单项支持:
| 字段 | 说明 |
|---|---|
| text | 按钮文案 |
| badge | 角标:数字 / 字符串 / true(红点) |
| onClick | 可选,单项点击回调(也会同时触发 clickAction) |
配置了
rightActions后,rightText/badge不再作为默认右侧内容展示。
8. 右侧插槽自定义
<kex-nav-bar title="详情">
<template #right>
<view style="display:flex;flex-direction:row;align-items:center">
<text @click="onShare">分享</text>
<text style="margin-left:12px" @click="onMore">更多</text>
</view>
</template>
</kex-nav-bar>
9. 中间区域插槽(完全自定义标题区)
<kex-nav-bar>
<template #left>
<text>关闭</text>
</template>
<!-- 默认插槽 = 中间 -->
<view>
<text>自定义中间内容</text>
</view>
<template #right>
<text>分享</text>
</template>
</kex-nav-bar>
10. 搜索模式
可输入搜索:
<template>
<kex-nav-bar
mode="search"
v-model:search-value="keyword"
search-placeholder="搜商品/订单"
@search="onSearch"
/>
</template>
<script setup>
import { ref } from 'vue'
const keyword = ref('')
const onSearch = (val) => {
console.log('搜索', val)
}
</script>
只读搜索框(点击跳转独立搜索页):
<kex-nav-bar
mode="search"
search-placeholder="搜一搜"
:search-readonly="true"
@searchClick="goSearchPage"
/>
11. 主题 / 渐变 / 暗色 / 毛玻璃
<!-- 主题色预设 -->
<kex-nav-bar title="消息" theme="primary" />
<kex-nav-bar title="成功" theme="success" />
<kex-nav-bar title="警告" theme="warning" />
<kex-nav-bar title="错误" theme="error" />
<!-- 自定义渐变背景 -->
<kex-nav-bar
title="活动"
color="#ffffff"
gradient="linear-gradient(90deg, #2979ff, #00c6ff)"
/>
<!-- 背景图 -->
<kex-nav-bar
title="详情"
color="#ffffff"
background-image="/static/nav-bg.png"
/>
<!-- 暗色 + 毛玻璃(毛玻璃主要在 H5 / 部分 App Webview 生效) -->
<kex-nav-bar title="设置" dark blur :border="false" />
也可直接覆盖颜色:
<kex-nav-bar
title="自定义"
color="#ffffff"
background-color="#111111"
/>
12. 滚动沉浸(透明 → 实体渐变)
关键点(缺一不可):
transparent:placeholder="false",让头图/内容钻到导航下方- 页面
onPageScroll把scrollTop传给组件 - 建议设置
background-color(渐入后的实体色)
<template>
<view class="page">
<kex-nav-bar
title="滚动沉浸"
subtitle="上滑看背景渐变"
transparent
:placeholder="false"
:scroll-top="scrollTop"
:scroll-threshold="160"
background-color="#ffffff"
/>
<!-- 头图要能延伸到导航下方;用 navHeight 给内容区留安全内边距 -->
<view class="banner" :style="{ paddingTop: navHeight + 'px' }">
<text>头图区域</text>
</view>
<view class="body">
<view v-for="i in 40" :key="i">内容行 {{ i }}</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onPageScroll } from '@dcloudio/uni-app'
const scrollTop = ref(0)
const navHeight = ref(0)
onPageScroll((e) => {
scrollTop.value = e.scrollTop || 0
})
</script>
也可用组件实例方法:
<kex-nav-bar ref="navRef" transparent :placeholder="false" />
<script setup>
import { ref } from 'vue'
import { onPageScroll } from '@dcloudio/uni-app'
const navRef = ref(null)
onPageScroll((e) => {
navRef.value?.setScrollTop(e.scrollTop || 0)
})
</script>
常见踩坑:
| 现象 | 原因 | 处理 |
|---|---|---|
| 上滑完全没渐变 | 没传 scrollTop / 没写 onPageScroll |
按上面示例绑定 |
| 有滚动值但几乎看不出变化 | placeholder 仍为 true,内容没钻到导航下 |
设 :placeholder="false",并做头图垫高 |
| 标题一开始看不清 | 头图较亮 / 较暗 | 传 color 固定字色,或依赖默认沉浸切换 |
13. 获取导航高度(用于页面垫高)
<template>
<kex-nav-bar
title="详情"
:placeholder="false"
@heightChange="onHeight"
/>
<view :style="{ paddingTop: navHeight + 'px' }">内容</view>
</template>
<script setup>
import { ref } from 'vue'
const navHeight = ref(0)
const onHeight = (h) => {
navHeight.value = h
}
// 或
// const h = navRef.value?.getHeight()
</script>
14. 布局宽度微调
<kex-nav-bar
title="很长的主标题文字可能会挤左右"
:left-width="60"
:right-width="80"
:title-size="15"
:subtitle-size="10"
/>
微信端若右侧被胶囊挡住,保持 capsule 默认 true 即可;不需要避让时:
<kex-nav-bar title="标题" :capsule="false" />
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| title | String | '' | 主标题 |
| subtitle | String | '' | 副标题 |
| leftText | String | '' | 左侧文字 |
| rightText | String | '' | 右侧文字(单按钮) |
| leftArrow | Boolean | true | 显示返回箭头;leftIcon 有值时不显示 |
| leftIcon | String | '' | 左侧自定义图标(图片路径) |
| leftIconSize | Number | String | 22 | 左侧图标宽高(px) |
| autoBack | Boolean | true | 点击左侧是否自动返回;自定义点击请设 false |
| homeButton | Boolean | false | 无法返回时显示首页按钮 |
| homeUrl | String | /pages/index/index | 首页路径 |
| beforeBack | Function | null | 返回前拦截;返回 false 或抛错则阻止 |
| color | String | '' | 文字/图标色(覆盖主题) |
| backgroundColor | String | '' | 背景色(覆盖主题) |
| gradient | String | '' | 渐变背景,如 linear-gradient(...) |
| backgroundImage | String | '' | 背景图路径 |
| dark | Boolean | false | 暗色模式 |
| fixed | Boolean | true | 固定顶部 |
| placeholder | Boolean | true | fixed 时占位;滚动沉浸请设 false |
| statusBar | Boolean | true | 预留状态栏高度 |
| border | Boolean | true | 底部分割线(沉浸滚动到位后也会显示) |
| shadow | Boolean | false | 阴影 |
| transparent | Boolean | false | 透明底,配合 scrollTop 背景渐入 |
| blur | Boolean | false | 毛玻璃(H5 / 部分端) |
| scrollTop | Number | 0 | 页面滚动距离,驱动沉浸过渡 |
| scrollThreshold | Number | 120 | 完成不透明过渡所需滚动像素 |
| mode | String | title | title / search |
| searchValue | String | '' | 搜索值,可用 v-model:search-value |
| searchPlaceholder | String | 搜索 | 搜索占位文案 |
| searchReadonly | Boolean | false | 搜索框只读(点击跳转搜索页) |
| loading | Boolean | false | 标题旁 loading |
| badge | Number | String | Boolean | '' | 右侧角标;true 为红点 |
| rightActions | Array | [] | 多个右侧操作,见上方用法 |
| height | Number | String | 44 | 导航栏高度(px,不含状态栏) |
| leftWidth | Number | String | 70 | 左侧宽度(px) |
| rightWidth | Number | String | 70 | 右侧宽度(px;多按钮时为 minWidth) |
| zIndex | Number | String | 998 | 层级 |
| titleSize | Number | String | 16 | 主标题字号 |
| subtitleSize | Number | String | 11 | 副标题字号 |
| capsule | Boolean | true | 微信小程序避让胶囊 |
| theme | String | default | default / primary / success / warning / error |
Events
| 事件 | 说明 | 回调 |
|---|---|---|
| clickLeft | 点击左侧区域 | — |
| clickRight | 点击右侧(单按钮模式) | — |
| clickTitle | 点击标题区域 | — |
| clickHome | 点击首页按钮 | — |
| clickAction | 点击多右侧操作某一项 | (item, index) |
| update:searchValue | 搜索值变化 | String |
| search | 键盘确认搜索 | String |
| searchClick | 点击搜索框 | — |
| searchFocus | 搜索框聚焦 | event |
| heightChange | 总高度变化(含状态栏) | Number |
Slots
| 插槽 | 说明 |
|---|---|
| default | 中间区域;传入后覆盖默认标题/搜索 |
| left | 左侧区域;传入后覆盖箭头/leftIcon/leftText |
| right | 右侧区域;传入后覆盖 rightText/badge/rightActions |
Expose(组件实例方法)
通过 ref 调用:
| 方法 | 说明 |
|---|---|
| getHeight() | 获取总高度(状态栏 + 导航栏) |
| setScrollTop(n) | 设置滚动值,驱动沉浸渐变 |
| syncLayout() | 重新同步状态栏 / 胶囊布局 |
<script setup>
import { ref, onMounted } from 'vue'
const navRef = ref(null)
onMounted(() => {
console.log(navRef.value?.getHeight())
})
</script>
<template>
<kex-nav-bar ref="navRef" title="标题" />
</template>
注意事项
- 页面必须
"navigationStyle": "custom",否则会和系统导航栏叠两层 - 自定义左侧点击一定要
:auto-back="false",否则仍会返回 - 滚动沉浸务必
:placeholder="false"+ 传scrollTop - 毛玻璃受端能力限制,App nvue / 部分小程序可能无效果
- 本组件无
uni-icons依赖;复杂图标请用#left/#right插槽自行放入

收藏人数:
下载插件并导入HBuilderX
下载示例项目ZIP
赞赏(0)
下载 8
赞赏 0
下载 12428416
赞赏 1934
赞赏
京公网安备:11010802035340号