xinli/xinlidsj/custom-tab-bar/index.vue
2026-02-24 16:49:05 +08:00

168 lines
3.9 KiB
Vue

<template>
<view class="tabbar" :class="{ h5: isH5 }" :style="safeAreaStyle">
<view class="tabbar-item" :class="{ active: active === 'pages/index/index' }" @tap="switchTab('pages/index/index')">
<view class="tabbar-icon">
<uni-icons type="home" size="20" :color="active === 'pages/index/index' ? selectedColor : color"></uni-icons>
</view>
<view class="tabbar-text">面板</view>
</view>
<view class="tabbar-item" :class="{ active: active === 'pages/message/notice' }" @tap="switchTab('pages/message/notice')">
<view class="tabbar-icon">
<uni-icons type="notification" size="20" :color="active === 'pages/message/notice' ? selectedColor : color"></uni-icons>
</view>
<view class="tabbar-text">通知</view>
</view>
<view class="tabbar-item" :class="{ active: active === 'pages/settings/index' }" @tap="switchTab('pages/settings/index')">
<view class="tabbar-icon">
<uni-icons type="person" size="20" :color="active === 'pages/settings/index' ? selectedColor : color"></uni-icons>
</view>
<view class="tabbar-text">我的</view>
</view>
</view>
</template>
<script>
import UniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'
export default {
components: {
UniIcons
},
data() {
return {
active: 'pages/index/index',
isH5: false,
color: '#646a73',
selectedColor: '#1677ff'
}
},
computed: {
safeAreaStyle() {
try {
const info = uni.getSystemInfoSync()
const bottom = info && info.safeAreaInsets ? info.safeAreaInsets.bottom : 0
return bottom ? `padding-bottom:${bottom}px;` : ''
} catch (e) {
return ''
}
}
},
mounted() {
try {
const info = uni.getSystemInfoSync()
this.isH5 = info && info.uniPlatform === 'web'
} catch (e) {
this.isH5 = false
}
if (this.isH5) {
this.color = 'rgba(201, 242, 255, 0.85)'
this.selectedColor = '#74d8ff'
}
this.updateActive()
},
onShow() {
this.updateActive()
},
methods: {
updateActive() {
try {
const pages = getCurrentPages()
const current = pages && pages.length ? pages[pages.length - 1] : null
let route = current && current.route ? current.route : ''
if (route && route[0] === '/') route = route.slice(1)
this.active = route || this.active
} catch (e) {
// ignore
}
},
switchTab(url) {
this.updateActive()
if (this.active === url) return
this.active = url
uni.switchTab({ url: '/' + url })
setTimeout(() => {
this.updateActive()
}, 50)
}
}
}
</script>
<style>
.tabbar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 56px;
background: #ffffff;
border-top: 1px solid rgba(0, 0, 0, 0.08);
display: flex;
align-items: center;
justify-content: space-around;
box-sizing: content-box;
z-index: 999;
}
.tabbar.h5 {
background: linear-gradient(180deg, rgba(2, 8, 22, 0.92) 0%, rgba(2, 8, 22, 0.78) 100%);
border-top: 1px solid rgba(0, 188, 255, 0.22);
box-shadow: 0 -10px 18px rgba(0, 0, 0, 0.35), 0 0 22px rgba(0, 166, 255, 0.10);
}
.tabbar-item {
flex: 1;
height: 56px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #646a73;
}
.tabbar.h5 .tabbar-item {
color: rgba(201, 242, 255, 0.85);
}
.tabbar-item.active {
color: #1677ff;
}
.tabbar.h5 .tabbar-item.active {
color: #74d8ff;
}
.tabbar-icon {
width: 34px;
height: 28px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 120ms ease;
}
.tabbar-item.active .tabbar-icon {
background: rgba(22, 119, 255, 0.14);
}
.tabbar.h5 .tabbar-item.active .tabbar-icon {
background: rgba(116, 216, 255, 0.14);
box-shadow: 0 0 14px rgba(116, 216, 255, 0.22);
}
.tabbar-item.active .tabbar-text {
color: #1677ff;
}
.tabbar.h5 .tabbar-item.active .tabbar-text {
color: #74d8ff;
}
.tabbar-text {
margin-top: 2px;
font-size: 12px;
line-height: 16px;
}
</style>