前言:
我最初在网上翻阅查找了很多方法,发现大家都是说在page.json中tabbar中添加:"custom": true,即可解决首次闪烁的问题,可是添加了我这边还是会闪烁,因此我这边改变了思路,使用了虚拟页面来解决此问题。
效果图:
一:编写
1. 在page.json中写一个初始页面,pages中的第一个对象是默认展示第一个页面,所以一定要在写一个。
"pages": [{"name": "index","path": "pages/index/index","style":{"navigationStyle":"custom"}},
2.新建index文件
3.编写index文件,因为我有三个页面,底部会有三个选项,每一个组件对应一个页面,Tabbr是我自定义的底部导航栏
<view><view><view v-if="pageStatus[0]" class="page__container" :style="pageContainerStyle(0)"><scroll-view class="scroll-view" scroll-y><BasicPage /></scroll-view></view><view v-if="pageStatus[1]" class="page__container" :style="pageContainerStyle(1)"><scroll-view class="scroll-view" scroll-y><InquiriesPage /></scroll-view></view><view v-if="pageStatus[2]" class="page__container" :style="pageContainerStyle(2)"><scroll-view class="scroll-view" scroll-y><user /></scroll-view></view></view>//自定义底部组件,后面会讲怎么写<Tabbr :current-page="0" @change="change"></Tabbr></view>
4.编写自定义导航栏,可以直接复制,修改路径为自己文件路径
<template><view class="tabbar-home"><!-- 拱形区域 --><view class="arched"></view><view class="arched-bg"></view><!-- 盒子 --><view class="tabbar-container"><view class="tabbar-item" v-for="(item, index) in tabbarList" :class="[item.centerItem ? ' center-item' : '']" @click="changeItem(item)"><view class="item-top"><image :src="currentItem == item.id ? item.selectIcon : item.icon"></image></view><view class="item-bottom" :class="[currentItem == item.id ? 'item-active' : '']"><text>{{ item.text }}</text></view></view></view></view>
</template>
<script setup>
import { defineProps, onMounted, ref } from 'vue'
const props = defineProps({currentPage: {type: Number,default: 0,},
})
const currentItem = ref(0)
const tabbarList = ref([{id: 0,path: '/pages/home/index',icon: '/static/images/tabBar/unhome.png',selectIcon: '/static/images/tabBar/homeSelect.png',text: '首页',centerItem: false,},{id: 1,path: '/pages/detail/index',icon: '/static/images/tabBar/unInquiries.png',selectIcon: '/static/images/tabBar/Inquiries.png',text: '问询',centerItem: true,},{id: 2,path: '/pages/user/index',icon: '/static/images/tabBar/unhome.png',selectIcon: '/static/images/tabBar/homeSelect.png',text: '我的',centerItem: false,},
])
const emit = defineEmits(['change'])
function changeItem(item) {currentItem.value = item.idemit('change', item)// uni.switchTab({// url: item.path,// })
}onMounted(() => {currentItem.value = props.currentPage// 非微信小程序需隐藏原生tabBar(微信小程序已通过"custom": true配置项隐藏原生tabbar)if (process.env.VUE_APP_PLATFORM != 'mp-weixin') {uni.hideTabBar()}
})
</script><style lang="scss" scoped>
.tabbar-home {z-index: 20090;height: 100rpx;position: fixed;left: 0;bottom: 0;box-shadow: 0rpx 0rpx 30rpx 0rpx rgba(0, 0, 0, 0.07);width: 100%;box-sizing: content-box;padding-bottom: env(safe-area-inset-bottom) !important;
}
view {padding: 0;margin: 0;box-sizing: border-box;
}.tabbar-container {position: absolute;bottom: 0rpx;left: 50%;transform: translateX(-50%);width: 100%;/* box-shadow: 0 0 5px #8d6c36; */display: flex;align-items: center;justify-content: space-around;padding: 5rpx 0;color: #8d6c36;height: 100%;padding-bottom: env(safe-area-inset-bottom) !important;box-shadow: 0rpx 0rpx 30rpx 0rpx rgba(0, 0, 0, 0.07);background-color: rgba(255, 255, 255, 1);z-index: inherit;
}.tabbar-container .tabbar-item {width: 20%;height: 80rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;text-align: center;
}.tabbar-container .item-active {color: #01beff;
}.tabbar-container .center-item {display: block;position: relative;margin-top: 20rpx;
}.tabbar-container .tabbar-item .item-top {width: 70rpx;height: 70rpx;padding: 10rpx;background: #ffffff;
}.tabbar-container .center-item .item-top {flex-shrink: 0;width: 100%;height: 140rpx;padding: 20rpx;position: absolute;top: -70rpx;/* left: calc(50% - 50rpx); */border-radius: 50%;/* box-shadow: 0 0 5px #999; */// background-color: #f3d9a6;
}.tabbar-container .tabbar-item .item-top image {width: 40rpx;height: 40rpx;
}.tabbar-container .center-item .item-top image {width: 70rpx;height: 70rpx;
}.tabbar-container .tabbar-item .item-bottom {font-size: 28rpx;width: 100%;
}.tabbar-container .center-item .item-bottom {position: absolute;bottom: 0;
}
.arched {width: 120rpx;height: 120rpx;left: 50%;top: -42rpx;position: absolute;transform: translateX(-50%);border-radius: 50%;box-shadow: 0rpx 0rpx 30rpx 0rpx rgba(0, 0, 0, 0.07);background-color: rgba(255, 255, 255, 1);// border: 2rpx solid rgba(0, 0, 0, 0.1);z-index: 20089;
}
.arched-bg {position: absolute;left: 0;top: 0;width: 100%;height: 100%;z-index: 20089;background-color: rgba(255, 255, 255, 1);
}
</style>
5.在index文件中引入了自定义导航栏组件和各页面组件
<script setup lang="ts">
import Tabbr from '../Tabbar/index.vue'
import BasicPage from './sub-page/BasicPage/index.vue'
import InquiriesPage from './sub-page/Inquiries/index.vue'
import user from './sub-page/user/index.vue'
import { useOrderedChildren } from './sub-page/hooks'
const { children: items, addChild: addItem, removeChild: removeItem } = useOrderedChildren<any>()
const tabbarData = ref([{id: 0,path: '/pages/home/index',icon: '/static/images/tabBar/unhome.png',selectIcon: '/static/images/tabBar/homeSelect.png',text: '首页',centerItem: false,},{id: 1,path: '/pages/detail/index',icon: '/static/images/tabBar/unhome.png',selectIcon: '/static/images/tabBar/homeSelect.png',text: '问询',centerItem: true,},{id: 2,path: '/pages/user/index',icon: '/static/images/tabBar/unhome.png',selectIcon: '/static/images/tabBar/homeSelect.png',text: '我的',centerItem: false,},
])// 记录每个子页面的状态
const pageStatus = ref(Array.from({ length: tabbarData.value.length }, () => false))
const currentIndex = ref(0)
const change = (item: any) => {pageStatus.value = pageStatus.value.map(() => false)if (!pageStatus.value?.[item.id as number]) {pageStatus.value[item.id as number] = truecurrentIndex.value = item.idnextTick(() => {items.value?.[item.id as number]?.onLoad?.()})}
}
const pageContainerStyle = computed<(index: number) => any>(() => {console.log('currentIndex', currentIndex.value)return (index: number) => {const style: any = {}if (index !== currentIndex.value) {style.display = 'none'}return style}
})
onLoad((options) => {const index = Number(options?.index || 0)pageStatus.value[index] = truenextTick(() => {currentIndex.value = index})
})
</script>
6.对了提个醒,自定义导航栏组件要写在page文件中~