顶部导航栏是一个非常常见的组件,尤其是固定在顶部的 Tab 导航,既能方便用户快速切换内容,又能保持页面结构的清晰。本文将详细介绍如何在 UniApp + Vue3 + TypeScript 项目中实现一个固定在顶部、且能根据滚动状态改变样式的 Tab 导航栏。
效果展示
我们要实现的导航栏具有以下特点:
- 固定在页面顶部,不随滚动消失
- 滚动超过一定距离时,导航栏背景色发生变化(带动画过渡)
- 支持 Tab 切换,并高亮显示当前选中项
- 自适应不同设备的状态栏高度
实现思路
- 使用
sticky
定位实现导航栏固定顶部效果 - 通过
onPageScroll
监听页面滚动事件,判断滚动距离 - 根据滚动距离动态切换导航栏样式
- 利用 UniApp 提供的 API 获取系统状态栏高度,实现适配
- 实现 Tab 切换的交互逻辑
代码实现与解析
html
<template>
<view class="header-bar">
<!-- Tab导航栏 -->
<view
class="tab-navigation"
:style="{ paddingTop: navHeight || '50px' }"
:class="{ scrolled: isScrolled }"
>
<view class="tab-wrapper">
<view
v-for="(tab, index) in tabs"
:key="index"
class="tab-item"
:class="{ active: currentIndex === index }"
@click="changeTab(index)"
>
{{ tab }}
</view>
</view>
</view>
</view>
</template>
关键解析:
:style="{ paddingTop: navHeight || '50px' }"
:动态设置导航栏顶部内边距,用于适配不同设备的状态栏高度:class="{ scrolled: isScrolled }"
:根据滚动状态动态添加scrolled
类,实现样式切换v-for="(tab, index) in tabs"
:循环渲染 Tab 选项:class="{ active: currentIndex === index }"
:根据当前选中的索引值,为 Tab 项添加激活样式@click="changeTab(index)"
:绑定 Tab 切换事件
脚本逻辑(Script)
javascript
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { onPageScroll } from '@dcloudio/uni-app'
// 导航栏高度相关
const navHeight = ref('')
const isScrolled = ref(false) // 滚动状态标记
// 获取状态栏高度并设置导航高度
const setNavHeight = () => {
// 获取系统信息
const systemInfo = uni.getSystemInfoSync()
// 使用状态栏高度,确保内容不被状态栏遮挡
navHeight.value = systemInfo.statusBarHeight + 'px'
}
// 监听页面滚动
onPageScroll((e: { scrollTop: number }) => {
console.log(e.scrollTop)
// 当滚动距离大于等于50px时,切换导航栏样式
isScrolled.value = e.scrollTop >= 50
})
// Tab相关数据
const tabs = ['推荐', '黄金', '白银', 'K金', '铂金']
const currentIndex = ref(0)
// 切换Tab
const changeTab = (index: number) => {
currentIndex.value = index
}
// 组件挂载时设置导航高度
onMounted(() => {
setNavHeight()
})
</script>
关键解析:
状态栏高度适配:
setNavHeight
函数通过uni.getSystemInfoSync()
获取系统信息,特别是状态栏高度- 在组件挂载时调用
setNavHeight
,确保导航栏正确适配不同设备滚动监听与状态切换:
- 使用 UniApp 提供的
onPageScroll
钩子监听页面滚动事件- 当滚动距离
scrollTop
大于等于 50px 时,将isScrolled
设置为true
,触发样式变化Tab 切换逻辑:
- 定义
tabs
数组存储导航项文本currentIndex
记录当前选中的 Tab 索引changeTab
方法用于切换选中的 Tab
样式设计(Style)
html
<style scoped>
.header-bar {
display: flex;
flex-direction: column;
padding: 10rpx 20rpx;
position: relative;
width: 100vw;
box-sizing: border-box;
height: 2000rpx; /* 仅为演示设置的高度 */
background-color: #d86868;
transition: background-color 0.3s ease; /* 添加过渡动画 */
}
/* 滚动后的导航栏样式 */
.scrolled {
background-color: orange;
z-index: 1000;
}
/* Tab导航样式 */
.tab-navigation {
display: flex;
justify-content: center;
padding: 10px 0;
margin-top: 10rpx;
position: sticky; /* 关键:sticky定位实现固定顶部效果 */
top: 0; /* 固定在顶部 */
z-index: 1000; /* 确保在其他元素之上 */
}
.tab-wrapper {
display: flex;
justify-content: center;
width: auto;
}
.tab-item {
color: #ffffff;
font-size: 16px;
padding: 5px 1px;
margin: 0 21px;
cursor: pointer;
white-space: nowrap; /* 防止文本换行 */
}
/* 激活状态的Tab样式 */
.tab-item.active {
border-bottom: 2px solid #ffffff;
color: #ffffff;
}
</style>