【愚公系列】2022年09月 微信小程序-自定义tabBar的实现

2022-09-27 20:31:36 浏览数 (1)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

前言

一、自定义tabBar的实现

1.全局配置

2.主页面

3.CustomTabBar组件

4.效果

前言

小程序自带的tabBar可以参考这篇文章:https://cloud.tencent.com/developer/article/1945495

因为小程序自带的tabBar,比较单一,无法满足多样化需求,这样就需要自己自定义tabBar。

一、自定义tabBar的实现

1.全局配置

全局app.json配置文件禁用自带tabBa

代码语言:javascript复制
"tabBar": {
    "custom": false,
    "list": [
      {
        "pagePath": "pages/index",
        "iconPath": "components/custom-tab-bar/component.png",
        "selectedIconPath": "components/custom-tab-bar/component-on.png",
        "text": "首页"
      },
      {
        "pagePath": "pages/index2",
        "iconPath": "components/custom-tab-bar/component.png",
        "selectedIconPath": "components/custom-tab-bar/component-on.png",
        "text": "首页2"
      },
      {
        "pagePath": "pages/index3",
        "iconPath": "components/custom-tab-bar/component.png",
        "selectedIconPath": "components/custom-tab-bar/component-on.png",
        "text": "自定义"
      }
    ]
}

2.主页面

代码语言:javascript复制
<!--miniprogram/pages/3.10/custom/index.wxml-->
<text>我是自定义组件l</text>
<CustomTabBar index="0" bindpagenavigating="onPageNavigating"></CustomTabBar>

代码语言:javascript复制
// miniprogram/pages/3.12/index.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    initData:{}
  },

  async onPageNavigating(e){
    let res = await wx.wxp.request({
      url: 'http://localhost:3000/hi?name=index2',
    })
    e.detail.eventCallback({
      openType:"initData",
      openData:{
        a:res.data
      }
    })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    const eventChannel = this.getOpenerEventChannel()
    if (eventChannel.on){
      eventChannel.on('initData', (data)=> {
        console.log("data",data)
        this.setData({
          initData:data
        })
      })
    }
  },
})

3.CustomTabBar组件

iconfont.wxss

代码语言:javascript复制
@keyframes icon-spin {
    0% {
        -webkit-transform: rotate(0);
        transform: rotate(0);
    }
    100% {
        -webkit-transform: rotate(359deg);
        transform: rotate(359deg);
    }
}

.iconfont-spin {
    -webkit-animation: icon-spin 2s infinite linear;
    animation: icon-spin 2s infinite linear;
    display: inline-block;
}

.iconfont-pulse {
    -webkit-animation: icon-spin 1s infinite steps(8);
    animation: icon-spin 1s infinite steps(8);
    display: inline-block;
}

.cu-icon-font{
    font-family:"iconfont" !important;
    font-size:inherit;
    font-style:normal;
}

index.js

代码语言:javascript复制
Component({
  behaviors: [require('../../lib/event-behavior.js')],
    properties: {
        index: {
            type: Number,
            value: 0
        }
    },
    data: {
      selected: 0,
      list: [{
        pagePath: "/pages/3.12/index",
        iconPath: "/components/custom-tab-bar/component.png",
        selectedIconPath: "/components/custom-tab-bar/component-on.png",
        text: "index",
        iconClass:"icon-homefill",
        iconTopClass:""
      }, {
        pagePath: "/pages/3.12/index2/index",
        iconPath: "/components/custom-tab-bar/component.png",
        selectedIconPath: "/components/custom-tab-bar/component-on.png",
        text: "index",
        iconClass:"cu-btn icon-add bg-green shadow",
        iconTopClass:"add-action"
      },{
        pagePath: "/pages/3.12/index3/index",
        iconPath: "/components/custom-tab-bar/component.png",
        selectedIconPath: "/components/custom-tab-bar/component-on.png",
        text: "自定义",
        iconClass:"icon-my",
        iconTopClass:""
      }]
    },
    observers: {
      "index": function (id) {
        this.setData({ selected: id});
      }
    },
    methods: {
      async goToTab(e){
        let targetPageUrl = e.currentTarget.dataset.url 
        
        // 派发一个事件,让外部业务代码处理,待处理完了,再回到这里
        let pageData = await this.triggerWaitingEvent("pagenavigating", {
          targetPageUrl
        })
        let res = await wx.wxp.navigateTo({
          url:targetPageUrl
        })
        if (res.eventChannel){
          res.eventChannel.emit(pageData.openType, pageData.openData)
        }
      }
    }
})

event-behavior.js

代码语言:javascript复制
// 派发一个等待处理,需要有代码处理的事件
module.exports = Behavior({
  definitionFilter(defFields) {
    defFields.methods.triggerWaitingEvent = function (type, data = {}){
      return new Promise((resolve,reject)=>{
        let eventCallback = res => resolve(res)
        Object.assign(data, {
          eventCallback
        })
        this.triggerEvent(type, data)
      })
    }
  },
})

index.wxml

代码语言:javascript复制
<view class="tabBar">
  <view class="tabbg"></view>
  <view class="cu-bar tabbar">
      <view wx:for="{{list}}" wx:for-item="item" wx:key="index" class="action {{item.iconTopClass}} {{selected == index?'text-green':''}}" catchtap='goToTab' data-url="{{item.pagePath}}" data-path="{{item.pagePath}}" data-index="{{index}}">
        <view class='iconf {{item.iconClass}}'></view> 
        <view>{{item.text}}</view>
      </view>
  </view>
</view>

index.wxss

代码语言:javascript复制
@import './iconfont.wxss';

.tabbg{
  background: rgba(255,255,255,1);
  width: 100%;
  height: 100rpx;
  position: absolute;
  bottom: 0;  
  box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1);
}

.iconf {
    font-family: "iconfont" !important;
    font-size: inherit;
    font-style: normal;
}

.tabBar{
  width:100%;
  position: fixed;
  bottom:0;
  font-size:20rpx;
  color:#8A8A8A;
}

.text-green{
  color: #39b54a;
}

.shadow {
  box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1);
}

.bg-red {
  background-color: #e54d42;
  color: #fff;
}

.bg-orange {
  background-color: #f37b1d;
  color: #fff;
}

.bg-yellow {
  background-color: #fbbd08;
  color: #333;
}

.bg-olive {
  background-color: #8dc63f;
  color: #fff;
}

.bg-green {
  background-color: #39b54a;
  color: #fff;
}

.bg-cyan {
  background-color: #1cbbb4;
  color: #fff;
}

.bg-blue {
  background-color: #0081ff;
  color: #fff;
}

.bg-purple {
  background-color: #6739b6;
  color: #fff;
}

.bg-mauve {
  background-color: #9c26b0;
  color: #fff;
}

.bg-pink {
  background-color: #e03997;
  color: #fff;
}

.bg-brown {
  background-color: #a5673f;
  color: #fff;
}

.bg-grey {
  background-color: #8799a3;
  color: #fff;
}

.bg-gray {
  background-color: #f0f0f0;
  color: #666;
}

.bg-black {
  background-color: #333;
  color: #fff;
}

.bg-white {
  background-color: #fff;
  color: #666;
}

.shadow .bg-green {
  box-shadow: 6rpx 6rpx 8rpx rgba(48, 156, 63, 0.2);
}

.cu-bar.tabbar .action.add-action .icon-add {
  position: absolute;
  width: 70rpx;
  z-index: 2;
  height: 70rpx;
  border-radius: 50%;
  line-height: 70rpx;
  font-size: 50rpx;
  top: -35rpx;
  left: 0;
  right: 0;
  margin: auto;
  padding: 0;
}

.cu-bar.tabbar .action.add-action::after {
  content: "";
  position: absolute;
  width: 100rpx;
  height: 100rpx;
  top: -50rpx;
  left: 0;
  right: 0;
  margin: auto;
  box-shadow: 0 -3rpx 8rpx rgba(0, 0, 0, 0.08);
  border-radius: 50rpx;
  background-color: rgba(255, 255, 255, 1);
  z-index: 0;
}

.cu-bar.tabbar .action.add-action::before {
  content: "";
  position: absolute;
  width: 100rpx;
  height: 30rpx;
  bottom: 30rpx;
  left: 0;
  right: 0;
  margin: auto;
  background-color: inherit;
  z-index: 1;
}

.cu-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 0 30rpx;
  font-size: 28rpx;
  height: 64rpx;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  overflow: visible;
  margin-left: initial;
  transform: translate(0rpx, 0rpx);
  margin-right: initial;
}

.cu-btn::after {
  display: none;
}

.cu-bar {
  display: flex;
  position: relative;
  align-items: center;
  min-height: 100rpx;
  justify-content: space-between;
  background: rgba(0,0,0,0);
}

.cu-bar .action {
  display: flex;
  align-items: center;
  height: 100%;
  justify-content: center;
  max-width: 100%;
}

.cu-bar.tabbar .action .icon-add {
  width: 100rpx;
  position: relative;
  display: block;
  height: auto;
  margin: 0 auto 10rpx;
  text-align: center;
  font-size: 40rpx;
}

/* safe-area-inset-*由四个定义了视口边缘内矩形的 top, right, bottom 和 left 的环境变量组成,这样可以安全地放入内容。 */
.cu-bar.tabbar {
  padding: 0;
  z-index: 0;
  height: calc(130rpx   env(safe-area-inset-bottom) / 2);
  padding-bottom: calc(env(safe-area-inset-bottom) / 2);
}

.cu-bar {
  margin-top: 20rpx; 
}

.cu-bar .action:first-child {
  margin-left: 30rpx;
  font-size: 30rpx;
}

.cu-bar.tabbar .action {
  font-size: 22rpx;
  position: relative;
  flex: 1;
  text-align: center;
  padding: 0;
  display: block;
  height: auto;
  line-height: 1;
  margin: 0;
  background-color: inherit;
  overflow: initial;
  padding-top: 30rpx;
}

.cu-bar.tabbar .action.add-action {
  position: relative;
  z-index: 2;
  padding-top: 0;
}

.icon-homefill {
  width: 100rpx;
  position: relative;
  display: block;
  height: auto;
  margin: 0 auto 10rpx;
  text-align: center;
  font-size: 40rpx;
}

.icon-add {
  width: 100rpx;
  position: relative;
  display: block;
  height: auto;
  margin: 0 auto 10rpx;
  text-align: center;
  font-size: 40rpx;
}

.icon-my {
  width: 100rpx;
  position: relative;
  display: block;
  height: auto;
  margin: 0 auto 10rpx;
  text-align: center;
  font-size: 40rpx;
}


.icon-homefill:before { content: "e6bb"; }

.icon-my:before { content: "e78b"; }

.icon-add:before { content: "e6da";

4.效果

0 人点赞