uniapp自定义封装tabbar

uniapp自定义封装tabbar

开发原因: 有很多时候 小程序并没有其类目 需要通过配置发布审核,
ps:需要去掉项目pages.json tabbar配置,不然重进会显示默认,跳转页面不能uni.switchTab。
在这里插入图片描述

  1. 组件tabbar

    <template>
      <view
        class="myTabBar"
        style="box-sizing: content-box"
        :style="{
          height: height,
          background: backgroundColor,
          'border-top-color': borderStyle,
          'padding-bottom': isIPhoneXX && iOSBottomBarHeight
        }"
      >
        <view
          class="tabBar-item"
          v-for="(item, index) in list"
          :key="index"
          @click="onClickItem(index,item)"
        >
          <view class="tabTag"  :class="{
            'ischose': tacurrent != index,
          }" v-if="item.num && item.num>0">
            <u-badge size="small" :count="item.num" type="error"></u-badge>
          </view>
          <!-- <view class="tabTag" v-if="item.num===-1">
            <u-badge size="small" :count="item.num" is-dot type="error"></u-badge>
          </view> -->
          <view class="tabBar-img">
            <image
                class="tabBar-img"
                :src="item.iconPath"
                mode="widthFix"
                v-if="tacurrent !== index"
                :style="{
              width: iconWidth
            }"
            ></image>
            <image
                class="tabBar-img"
                :src="item.selectedIconPath"
                mode="widthFix"
                v-if="tacurrent === index"
                :style="{
              width: iconWidth
            }"
            ></image>
          </view>
          <view
            class="tabBar-text"
            :style="{
              color: color,
              color: tacurrent === index && selectedColor,
              'font-size': fontSize,
              'font-family':'Microsoft YaHei',
              'padding-top': spacing
            }"
            >{{ item.text }}</view
          >
        </view>
      </view>
    </template>
    <script>
    export default {
      components: {},
      data() {
        return {
          iOSBottomBarHeight: '34px',
          isIPhoneXX: false
        }
      },
      props: {
        tacurrent: Number, // 当前选中的值
        color: {
          // tab 上的文字默认颜色
          type: String,
          default: '#100405'
        },
        selectedColor: {
          // tab 上的文字选中时的颜色
          type: String,
          default: '#C31107'
        },
        backgroundColor: {
          // tab 的背景色
          type: String,
          default: '#ffffff'
        },
        borderStyle: {
          // tabbar 上边框的颜色
          type: String,
          default: '#dddddd'
        },
        fontSize: {
          // 文字默认大小
          type: String,
          default: '13px'
        },
        iconWidth: {
          // 图标默认宽度
          type: String,
          default: '20px'
        },
        spacing: {
          // 图标和文字的间距
          type: String,
          default: '0px'
        },
        height: {
          // tabBar 默认高度
          type: String,
          default: '50px'
        },
        list: {
          type: Array
          /**
    				[
    					{
    						pagePath: '', // 页面路径
    						text: '', // tab 上按钮文字
    						iconPath: '', // 图片路径 图片请使用base64
    						selectedIconPath: '', // 选中时的图片路径 图片请使用base64
    						num: '', // 红色数字角标
    					}
    				]
    			 */
        }
      },
      onLoad() {},
      onShow() {},
      onHide() {},
      created() {
        try {
          const { isIPhoneXX } = getApp().globalData
          this.isIPhoneXX = isIPhoneXX
        } catch (e) {}
        // try {
        //   const res = wx.getSystemInfoSync()
        //   console.log('getSystemInfoSync', res)
        //   if (
        //     res.model.search('iPhone X') != -1 ||
        //     res.model.search('iPhone 12 mini') != -1 ||
        //     res.model.search('iPhone 11') != -1 ||
        //     res.model.search('iPhone 12') != -1 ||
        //     res.model.search('iPhone 13') != -1 ||
        //     res.model.search('iPhone 14') != -1
        //   ) {
        //     this.isIPhoneXX = true
        //   }
        // } catch (e) {
        //   // Do something when catch error
        // }
      },
      methods: {
        onClickItem(index,item) {
          this.$emit('update:value', index)
          this.$emit('callback', index,item)
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .myTabBar {
      // display: flex;
      // justify-content: space-between;
      // align-items: center;
      // border-top: 1px solid #eee;
      // width: 100%;
      // padding-top: 10rpx;
        display: flex;
        flex-direction: row;
        align-items: center;
        position: relative;
        position: fixed;
        bottom: 0;
        left: 0;
        width: 100%;
        z-index: 998;
        padding-bottom:15px;
        padding-top:5px;
        box-sizing: initial;
      .tabBar-item {
        position: relative;
        // flex: 1;
        // text-align: center;
        // line-height: 1;
        flex: 1;
        justify-content: center;
        height: 100%;
        padding: 6px 0;
        display: flex;
        flex-direction: row;
        flex-direction: column;
        align-items: center;
      }
      .tabBar-text {
        line-height: 1;
      }
      .tabBar-img {
        display: inline-block;
        width: 40rpx;
        height: 48rpx;
      }
      .tabTag {
        position: absolute;
        top: 0;
        left: 50%;
        // margin: 0 auto;
        z-index: 9;
      }
      .ischose{
        top: -16% !important;
        left: 83% !important;
      }
    }
    </style>
    
    

    2.使用页面

    ​ .使用组件

    <!--底部菜单-->
    <template>
    		 <view class="btn-bar">
    			<tabbar :tacurrent="tacurrent" :list="tabList" @callback="tabbarCallback" />
    		 </view>
    </template>
    

    ​ . 定义变量

    tacurrent:0,//当前显示
    tabList:[ {
        iconPath: "/static/img/Navigation1.png",
        selectedIconPath: "/static/img/Navigation1_1.png",
        text: "比赛",
       
        pagePath: "/pages/index/index",
        midButton: true,
      },
      
     {
        iconPath: "/static/img/Navigation3.png",
        selectedIconPath: "/static/img/Navigation3_3.png",
        text: "俱乐部",
        pagePath: "/pages/club/index",
        midButton: false,
      },
      {
        iconPath: "/static/img/Navigation4.png",
        selectedIconPath: "/static/img/Navigation4_4.png",
        text: "裁判工作台",
        customIcon: false,
        pagePath: "/pages/referee/index",
      },
      {
        iconPath: "/static/img/Navigation5.png",
        selectedIconPath: "/static/img/Navigation5_5.png",
        text: "我的",
        customIcon: false,
        pagePath: "/pages/center/center",
      },]
    

    .悬浮底部样式

    .btn-bar {
    	position: fixed;
    	bottom: 0;
    	left: 0;
    	width: 100%;
    	height: 130rpx;
    	background-color: #ffffff;
    	box-shadow: 0 0 36rpx 0 rgba(0, 0, 0, 0.08);
    	display: flex;
    	justify-content: space-between;
    	align-items: center;
    	padding: 0 24rpx;
    	z-index: 9999;
    }
    
### 创建和配置自定义样式的底部TabBar导航栏 #### 组件结构设计 为了实现自定义样式的底部 `TabBar` 导航栏,在 UniApp 中通常会创建一个新的 Vue 组件来封装这个功能。该组件可以放置于项目的 `/components/Tabbar/Tabbar.vue` 路径下。 ```html <template> <view class="custom-tab-bar"> <!-- 左侧按钮 --> <block v-for="(item, index) in tabList" :key="index"> <view @click="handleClick(index)" :class="{ 'active': currentIndex === index }">{{ item.text }}</view> </block> <!-- 中间凸起按钮 --> <view class="center-button" @click.stop="onCenterButtonClick">+</view> <!-- 右侧按钮 --> <block v-for="(item, index) in tabList.slice(2)" :key="index + 2"> <view @click="handleClick(index + 2)" :class="{ 'active': currentIndex === (index + 2) }">{{ item.text }}</view> </block> </view> </template> <script> export default { data() { return { currentIndex: 0, tabList: [ { text: '首页', pagePath: '/pages/index/index' }, { text: '发现', pagePath: '/pages/discover/discover' }, null, // 占位符,用于中间位置留白 { text: '消息', pagePath: '/pages/message/message' }, { text: '我的', pagePath: '/pages/mine/mine' } ] }; }, methods: { handleClick(index) { if(this.tabList[index]) this.$emit('change', this.tabList[index].pagePath); this.currentIndex = index; }, onCenterButtonClick() { console.log('中心按钮被点击'); // 这里处理特殊逻辑,比如弹窗发布内容等操作 } } }; </script> <style scoped> .custom-tab-bar { display: flex; justify-content: space-around; align-items: center; } .center-button { position: absolute; bottom: 48px; width: 70px; height: 70px; border-radius: 50%; background-color: #ffcc00; } .active { color: red; } </style> ``` 此代码片段展示了如何构建一个带有五个选项卡的自定义 `TabBar`,其中第三个位置为空以便插入特殊的圆形按钮[^1]。 #### 页面集成 当完成了上述组件之后,则可以在任何页面中通过如下方式引入并使用: ```html <template> <view> 我的内容... <TabBar /> </view> </template> <script> import TabBar from '@/components/Tabbar/Tabbar.vue' export default { components: { TabBar } } </script> ``` 这里假设已经按照前面提到的方式实现了 `TabBar` 组件,并将其注册到了当前页面中。 #### 功能扩展与优化建议 对于更复杂的需求,还可以考虑增加更多交互效果或动画支持;另外也可以利用 Vuex 来管理全局状态从而更好地同步不同页面之间的选中状态变化情况[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值