uni-app(vue3)封装自定义底部导航栏组件

hi,小伙伴们,我们在使用不同app或者小程序的时候发现底部导航栏各式各样,每个都有自己的特点,我们今天也自定义一版底部导航栏,废话不多说,直接上代码!

template模块

<template>
  <view class="tab-bar">
    <view class="tabbar-container">
      <view class="tabbar-item" v-for="(item, index) in tabBarList"
        :class="[item.isCenter ? 'center' : '']"
        @click="handleChange(item)">
        <view class="item-top">
          <image :src="currentPath == item.path ? item.selectIcon : item.icon"></image>
        </view>
        <view class="item-bottom" :class="[currentPath == item.path ? 'item-active' : '']">
          <text>{{ item.text }}</text>
        </view>
      </view>
    </view>
  </view>
</template>

js模块

<script setup>
import { onLoad } from '@dcloudio/uni-app';
import { ref } from 'vue'
import { tabBarList } from './data' //看下面data模块

/**
 * 参数名               类型              描述
 * currentPath        String          当前页面路径
*/

const props = defineProps({
  currentPath: {
	type: String,
    default: () => '/pages/index/index'
  },
})

const emit = defineEmits(["scroll-height"])

const currentPath = ref(`/${props.currentPath}`)

const scrollHeight = ref(0)

const handleChange = (item) => {
  uni.switchTab({ url: item.path })
}

onLoad(() => {
  //隐藏原生tabbar
  uni.hideTabBar();
  //以下代码为了列表触底加载使用,按照个人需求(可删除/可自定义)
  uni.getSystemInfo({
  success: (res)=>{
     let info = uni.createSelectorQuery().select(".tab-bar");
      info.boundingClientRect((data)=>{
        scrollHeight.value = res.screenHeight - data.height - res.statusBarHeight - 100;
            emit("scroll-height", scrollHeight.value)
      }).exec()
    }
  });
});
</script>

style模块

<style lang="scss">
view {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  z-index: 999;
}

.tabbar-container {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 120rpx;
  display: flex;
  align-items: center;
  padding: 5rpx 0;
  color: #999999;
  background-color: #ffffff;
  .tabbar-item {
    height: 100rpx;
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    align-items: center;
    text-align: center;
    margin-bottom: 30rpx;
    .item-top {
      width: 70rpx;
      height: 70rpx;
      padding: 10rpx;
      image {
        width: 100%;
        height: 100%;
      }
    }
    .item-bottom {
      font-size: 24rpx;
      width: 100%;
    }
  }
  .item-active {
    color: $uni-bg-color;
  }
  .center {
    display: block;
    position: relative;
    .item-top {
      flex-shrink: 0;
      width: 100rpx;
      height: 100rpx;
      position: absolute;
      top: -40rpx;
      left: calc(50% - 50rpx);
      border-radius: 50%;
      box-shadow: 0 0 5px #999;
      background-color: #ffffff;
    }
    .item-bottom {
      position: absolute;
      bottom: 5rpx;
    }
  }
}
</style>

data模块

export const tabBarList = [
  {
    index: 0,
    path: '/pages/index/index',
    icon: '/static/c1.png',
    selectIcon: '/static/c2.png',
    text: '首页',
    isCenter: false
  },
  {
    index: 1,
    path: '/pages/order/index',
    icon: '/static/c3.png',
    selectIcon: '/static/c4.png',
    text: '订单',
    isCenter: false
  },
  {
    index: 2,
    path: '/pages/mine/index',
    icon: '/static/c5.png',
    selectIcon: '/static/c6.png',
    text: '我的',
    isCenter: false
  },
]

tabBar父组件使用(顺带封装一个页面公共容器组件 scroll-view.vue)

<template>
	<view class="container">
    <!-- 页面内容 -->
    <view class="content">
      <slot name="content"/>
    </view>
    <!-- 自定义底部导航栏 -->
    <view class="tab-bar">
      <slot name="footer"/>
      <my-tab-bar
        v-if="props.showBar"
        :current-path="currentPath"
        @scroll-height="getScrollHeight"
      ></my-tab-bar>
    </view>
  </view>
</template>

<script setup>
import { reactive, ref, computed } from 'vue'
import myTabBar from 'tabbar组件存放路径'

/**
 * 参数名称            类型               描述
 * showBar          Boolean          是否展示底部导航栏
 */
const props = defineProps({
  showBar: {
    type: Boolean,
    default: () => true
  }
})

const emit = defineEmits(['scroll-height'])

const routes = getCurrentPages()
const currentPath = routes[routes.length - 1].route

const getScrollHeight = (val) => {
  emit('scroll-height', val)
}

</script>

<style lang="scss">
.container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: $uni-bg-color;
  .content {
    flex: 1;
  }
}
</style>

具体页面使用

<template>
   <my-scroll-view>
	 <template slot="content">
	   <view class="nav"> {{ title }} </view>
	 </template>
	 <template slot="footer">
	   <!-- 自定义底部导航栏 -->
       <!-- 类名需要和tabbar组件uni.createSelectorQuery().select(".tab-bar")这步保持一致 -->
	   <view class="tab-bar"></view>
	 </template>
   </my-scroll-view>
</template>

<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app';
import myScrollView from 'scroll-view组件存放位置'
const title = ref('订单')

</script>

<style lang="scss"></style>

data模块 isCenter 设置为true效果如下:

data模块 isCenter 设置为false效果如下:

以上就是简单实现了一版自定义导航效果,具体看个人需求修改。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值