頂部導航欄是一個非常常見的組件,尤其是固定在頂部的 Tab 導航,既能方便用戶快速切換內容,又能保持頁面結構的清晰。本文將詳細介紹如何在 UniApp + Vue3 + TypeScript 項目中實現一個固定在頂部、且能根據滾動狀態改變樣式的 Tab 導航欄。
效果展示
我們要實現的導航欄具有以下特點:
- 固定在頁面頂部,不隨滾動消失
- 滾動超過一定距離時,導航欄背景色發生變化(帶動畫過渡)
- 支持 Tab 切換,并高亮顯示當前選中項
- 自適應不同設備的狀態欄高度
實現思路
- 使用?
sticky
?定位實現導航欄固定頂部效果 - 通過?
onPageScroll
?監聽頁面滾動事件,判斷滾動距離 - 根據滾動距離動態切換導航欄樣式
- 利用 UniApp 提供的 API 獲取系統狀態欄高度,實現適配
- 實現 Tab 切換的交互邏輯
代碼實現與解析
<template><view class="header-bar"><!-- Tab導航欄 --><view class="tab-navigation" :style="{ paddingTop: navHeight || '50px' }":class="{ scrolled: isScrolled }"><view class="tab-wrapper"><viewv-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)
<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)
<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>