Appearance
底部导航栏
一、组件
vue
<template>
<view class="tab_bar_wrap">
<view class="items">
<view :class="{
'item':true,
'bright':nTabbarIndex === 0
}" @click="goTabBar" data-url="" data-index="0">
<image v-if="nTabbarIndex === 0" class="icon" src="@/static/image/tabbar/fun2.png"
mode=""></image>
<image v-else class="icon" src="@/static/image/tabbar/fun.png" mode=""></image>
示例
</view>
<view :class="{
'item':true,
'bright':nTabbarIndex === 1
}" @click="goTabBar" data-url="" data-index="1">
<image v-if="nTabbarIndex === 1" class="icon" src="@/static/image/tabbar/flow2.png" mode=""></image>
<image v-else class="icon" src="@/static/image/tabbar/flow.png" mode=""></image>
瀑布流
</view>
<view :class="{
'item':true,
'bright':nTabbarIndex === 2
}" @click="goTabBar" data-url="" data-index="2">
<image v-if="nTabbarIndex === 2" class="icon" src="@/static/image/tabbar/my2.png" mode=""></image>
<image v-else class="icon" src="@/static/image/tabbar/my.png" mode=""></image>
我的
</view>
</view>
</view>
</template>
<script>
export default {
props: {
nTabbarIndex: {
type: Number,
default: 0
}
},
data() {
return {}
},
methods: {
goTabBar(e) {
const i = parseInt(e.currentTarget.dataset.index);
if (this.nTabbarIndex === i) return;
this.$emit('goTabBar', i);
}
}
}
</script>
<style lang="scss" scoped>
.tab_bar_wrap {
width: 100vw;
background: $uni-bg-color;
position: fixed;
left: 0;
bottom: 0;
z-index: 99999;
border-top: 1px solid $uni-bg-color-grey;
.items {
width: 100%;
height: 100 rpx;
padding-bottom: env(safe-area-inset-bottom);
display: flex;
.item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
text-align: center;
color: $uni-text-color-grey;
font-size: 20 rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
line-height: 24 rpx;
}
.index_icon {
width: 68 rpx;
height: 68 rpx;
}
.bright {
color: $uni-color-primary;
}
.icon {
width: 52 rpx;
height: 52 rpx;
}
}
}
</style>
二、使用
index.vue
vue
<template>
<!-- 布局 -->
<view class="tabbar_wrap">
<nav-bar v-show="objNavData.show" :title="objNavData.title || ''" :isBack="false"></nav-bar>
<view :class="[sAnimation,{'silder2':!isShowTabBar}]"
:style="'height: calc(100% - '+(objNavData.show?navHeight:0)+'px);'">
<el-home ref="home" v-show="nTabbarIndex === 0"></el-home>
<el-flow ref="flow" v-show="nTabbarIndex === 1"></el-flow>
<el-my ref="my" v-show="nTabbarIndex === 2"></el-my>
</view>
<tab-bar v-show="isShowTabBar" :nTabbarIndex="nTabbarIndex" @goTabBar="goTabBar"></tab-bar>
<user-info-auth ref="user-info-auth"/>
</view>
</template>
<script>
import oShareMixin from '/src/mixin/share.js';
import tabBar from '/src/components/tabbar.vue';
import navBar from '/src/components/navbar.vue';
import elHome from '/src/pages/demo/home/index.vue';
import elFlow from '/src/pages/demo/flow/index.vue';
import elMy from '/src/pages/demo/my/index.vue';
import userInfoAuth from "/src/components/userinfoauth/index.2.0.vue";
export default {
mixins: [oShareMixin],
components: {
tabBar,
navBar,
elHome,
elFlow,
elMy,
userInfoAuth
},
computed: {
isShowTabBar() {
return this.$store.state.isShowTabBar
}
},
data() {
return {
objNavData: {
show: true,
title: '前端规范'
},
navHeight: 80,
option: {},
nTabbarIndex: -1,
sAnimation: 'slide', //默认动画
isCutover: true
}
},
onLoad(option) {
//获取页面元素
this.home = this.$refs.home;
this.flow = this.$refs.flow;
this.my = this.$refs.my;
this.option = option;
const wxInfo = this.$getWxInfo();
this.navHeight = wxInfo.navHeight;
this.pageInit(0);
},
onShow() {
this.$store.commit('showTabBer', true)
if(this.nTabbarIndex == 2){
this.currentEl.upDate();
}
},
methods: {
//初始化
pageInit(index = 0) {
this.goTabBar(index);
},
goTabBar(i) {
if (this.isCutover) {
this.isCutover = false;
this.nTabbarIndex = i;
this.currentEl = null;
let objNavData = {
show: true,
title: '前端示例',
};
switch (i) {
case 0:
this.currentEl = this.home;
objNavData = {
show: true,
title: '前端示例',
};
break;
case 1:
this.currentEl = this.flow;
objNavData = {
show: true,
title: '瀑布流',
};
break;
case 2:
this.currentEl = this.my;
objNavData = {
show: true,
title: '我的',
};
break;
}
this.objNavData = objNavData;
/* 切换动画 */
this.sAnimation = "slide slide_animation";
setTimeout(() => {
this.isCutover = true;
this.sAnimation = "slide";
}, 200)
//调用当前组件的upData方法
if (this.currentEl && this.currentEl.upDate) {
this.$init(() => {
this.currentEl.upDate();
})
}
}
},
}
}
</script>
<style lang="scss" scoped>
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all 0.5s;
}
.fade-transform-enter {
opacity: 0;
transform: translateY(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateY(-30px);
}
.tabbar_wrap {
width: 100vw;
height: 100vh;
}
.slide {
width: 100%;
box-sizing: border-box;
//底部安全距离 + tabbar高度
padding-bottom: calc(env(safe-area-inset-bottom) + 100rpx);
position: relative;
left: 0;
}
.slide_animation {
animation: slide 0.2s 1;
}
@keyframes slide {
from {
left: 100vw;
}
to {
left: 0;
}
}
</style>
三、注意事项
- 上述方式中,每个tebbar页是以组件的形式引入;
- 上述方式中,每个tebbar页都需要有一个
upDate
方法,切换tabbar时会调用; - 如果现在页面返回时更新tabbar页的数据,需要在index.vue里的onShow判并调用
this.currentEl.upDate()
; - tebbar页中,可通过
this.$parent.goTabBar(1)
,切换到索引为1的tabbar页;