微信小程序配置自定义TabBar不闪烁(组件版)

754 阅读4分钟

app.json中

  1. 创建tabbar对应的路由页面
  2. 配置tabbar配置项,指定custom字段为true,配置list等,这里的list要和自定义tabbar里面配置的完全一致
app.json
{
  "pages":[
    "pages/index/index",
    "pages/special/special",
    "pages/shopping/shopping",
    "pages/personal/personal"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle":"black"
  },
  "tabBar": {
    "custom": true,
    "color": "#7A7E83",
    "selectedColor": "#3cc51f",
    "borderStyle": "black",
    "backgroundColor": "#ffffff",
    "list": [{
        "pagePath": "pages/index/index",
        "iconPath": "/static/image/home.png",
        "selectedIconPath": "/static/image/home_select.png",
        "text": "组件"
      },
      {
        "pagePath": "pages/special/special",
        "iconPath": "/static/image/like.png",
        "selectedIconPath": "/static/image/like-active.png",
        "text": "我的特卖"
      },
      {
        "pagePath": "pages/shopping/shopping",
        "iconPath": "/static/image/shopping.png",
        "selectedIconPath": "/static/image/shopping-active.png",
        "text": "购物车"
      },
      {
        "pagePath": "pages/personal/personal",
        "iconPath": "/static/image/admin.png",
        "selectedIconPath": "/static/image/admin-active.png",
        "text": "个人"
      }
    ]
  },
  "usingComponents": {},
  "subpackages": [{
    "root": "orderDetails",
    "pages": [
      "orderDetails/orderDetails"
    ]
  },{
    "root": "complaint",
    "pages": [
      "complaint/complaint"
    ]
  },{
    "root": "changeDetail",
    "pages": [
      "changeDetail/changeDetail"
    ]
  }],
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

创建自定义tabbar

  1. 根目录下创建components文件夹
  2. components内新建bottom-tab-bar文件夹,右键新建components
  3. bottom-tab-bar.js中配置selected,color,selectedColor,list等字段。methods里面配置switchTab为点击tabbar切换的回调拿到跳转的地址,用wx.switchTab进行路由跳转。创建run方法,这个方法是跳转到目标地址的时候目标地址通过获取这个tabbar实例然后调用run方法进行改变tabbar的高亮效果。
bottom-tab-bar.js
Component({
  data: {
    selected: null,
    color: "#7A7E83",
    selectedColor: "#3cc51f",
    "list": [{
        "pagePath": "/pages/index/index",
        "iconPath": "https://chirse.oss-cn-beijing.aliyuncs.com/tabbar_img/home.png",
        "selectedIconPath": "https://chirse.oss-cn-beijing.aliyuncs.com/tabbar_img/home_active.png",
        "text": "首页"
      },
      {
        "pagePath": "/pages/special/special",
        "iconPath": "https://chirse.oss-cn-beijing.aliyuncs.com/tabbar_img/beer.png",
        "selectedIconPath": "https://chirse.oss-cn-beijing.aliyuncs.com/tabbar_img/beer_active.png",
        "text": "官网"
      },
      {
        "pagePath": "/pages/shopping/shopping",
        "iconPath": "https://chirse.oss-cn-beijing.aliyuncs.com/tabbar_img/shopping.png",
        "selectedIconPath": "https://chirse.oss-cn-beijing.aliyuncs.com/tabbar_img/shopping_active.png",
        "text": "购物车"
      },
      {
        "pagePath": "/pages/personal/personal",
        "iconPath": "https://chirse.oss-cn-beijing.aliyuncs.com/tabbar_img/me.png",
        "selectedIconPath": "https://chirse.oss-cn-beijing.aliyuncs.com/tabbar_img/me_active.png",
        "text": "购物车"
      },
    ]
  },
  attached() {},
  methods: {
    switchTab(e) {
      const data = e.currentTarget.dataset
      const url = data.path
      // this.setData({
      //   selected: data.index
      // })
      wx.switchTab({
        url
      })
    },
    run(index) {
      // console.log(this.data.active);
      // this.setData({
      //   // 通过this.data获取父组件里传过来的值
      //   selected: this.data.active
      // });
      // console.log(this.data.selected);
      console.log(this.data.active);
      this.setData({
        // 通过this.data获取父组件里传过来的值
        selected:index
      });
      console.log(this.data.selected);
    }
  }
})
bottom-tab-bar.json
{
  "component": true
}
bottom-tab-bar.wxml
<!--miniprogram/custom-tab-bar/index.wxml-->
<view class="tab-bar">
  <view class="tab-bar-border"></view>
  <view wx:for="{{list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab">
    <cover-image src="{{selected === index ? item.selectedIconPath : item.iconPath}}"></cover-image>
    <view style="color: {{selected === index ? selectedColor : color}};">{{item.text}}</view>
  </view>
  <view class="one" style="display: {{selected ===0?'block':'none'}};">
    <cover-image src="/static/image/home_select.png"></cover-image>
  </view>
</view>
bottom-tab-bar.wxss
.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  height: 48px;
  background: white;
  display: flex;
  padding-bottom: env(safe-area-inset-bottom);
  z-index: 50;
}

.tab-bar-border {
  background-color: rgba(0, 0, 0, 0.33);
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 1px;
  transform: scaleY(0.5);
}

.tab-bar-item {
  flex: 1;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

.tab-bar-item cover-image {
  width: 27px;
  height: 27px;
}

.tab-bar-item view {
  font-size: 10px;
}

.one {
  width: 70rpx;
  height: 70rpx;
  position: absolute;
  left: 40rpx;
  top: 7rpx;
  z-index: 10;
}

.one>cover-image {
  display: none;
  width: 70rpx;
  height: 70rpx;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.two {
  width: 70rpx;
  height: 70rpx;
  position: absolute;
  left: 40rpx;
  top: 67rpx;
  z-index: 5;
  background-color: #fff;
}

页面组件部分(以index页面为例)

  1. 首先在index.json里面指定usingComponents配置项引入自定义tabbar组件
  2. 然后在index.wxml里面书写自定义tabbar组件,然后指定id为tabbar
  3. index.js里面配置data配置项tabBarIndex为当前路由组件对应的索引
  4. 然后再onLoad钩子中利用selectComponent获取自定义tabbar的实例,调用它的run方法,传递保存在当前组件里的tabBarIndex,然后由run改变自定义tabbar的高亮状态
index.json
{
  "usingComponents": {
    "TabBar": "/components/bottom-tab-bar/bottom-tab-bar"
  }
}
index.wxml
<!--index.wxml-->
<view class="container">
  <TabBar id="tabbar"></TabBar>
  <view class="userinfo">
    <block wx:if="{{canIUseOpenData}}">
      <view class="userinfo-avatar" bindtap="bindViewTap">
        <open-data type="userAvatarUrl"></open-data>
      </view>
      <open-data type="userNickName"></open-data>
    </block>
    <block wx:elif="{{!hasUserInfo}}">
      <button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
      <button wx:elif="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
      <view wx:else> 请使用1.4.4及以上版本基础库 </view>
    </block>
    <block wx:else>
      <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    </block>
  </view>
  <view class="usermotto">
    <text class="user-motto">{{motto}}</text>
  </view>
</view>
index.js
// index.js
// 获取应用实例
const app = getApp()

Page({
  data: {
    tabBarIndex: 0,
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo'),
    canIUseGetUserProfile: false,
    canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false
  },
  // 事件处理函数
  bindViewTap() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad() {
    //设置当前选中下标,tab栏部分
    let tabbar = this.selectComponent('#tabbar')
    tabbar.run(this.data.tabBarIndex)
    if (wx.getUserProfile) {
      this.setData({
        canIUseGetUserProfile: true
      })
    }
  },
  onShow() {
    if (typeof this.getTabBar === 'function' &&
      this.getTabBar()) {
      this.getTabBar().setData({
        selected: null //标亮的导航按钮的下标,如果是其他子页面,可以赋值为null
      })
    }
  },
  getUserProfile(e) {
    // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
    wx.getUserProfile({
      desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
      success: (res) => {
        console.log(res)
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    })
  },
  getUserInfo(e) {
    // 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
    console.log(e)
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
  }
})
index.wxss
/* pages/index/index.wxss */
.banners {
  width: 100%;
  height: 300rpx;

}

.banners image {
  width: 100%;
  height: 100%;
}

/* 五个图标导航区域 */
.navContainer {
  display: flex;

}

.navItem {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 20%;
}


.navItem .iconfont {
  width: 100rpx;
  height: 100rpx;
  border-radius: 50%;
  text-align: center;
  line-height: 100rpx;
  background: rgb(240, 19, 19);
  font-size: 50rpx;
  color: #fff;
  margin: 20rpx 0;
}


.navItem text {
  font-size: 26rpx;
}


/* 推荐歌曲 */
.recommendContainer {
  padding: 20rpx;
}



/* 推荐内容区*/
.recommendScroll {
  display: flex;
  height: 300rpx;
}
.scrollItem {
  width: 200rpx;
  margin-right: 20rpx;

}

.scrollItem image {
  width: 200rpx;
  height: 200rpx;
  border-radius: 10rpx;

}

.scrollItem text {
  font-size: 26rpx;
  /* 单行文本溢出隐藏 省略号代替 */
  /*display: block;*/
  /*white-space: nowrap;*/
  /*overflow: hidden;*/
  /*text-overflow: ellipsis;*/

  /* 多行文本溢出隐藏 省略号代替*/
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical; /*设置对其模式*/
  -webkit-line-clamp: 2; /*设置多行的行数*/
}


/* 排行榜  */
.topList {
  padding: 20rpx;
}

.topListSwiper {
  height: 400rpx;
}

.swiperItem {
  width: 96%;
  background: #fbfbfb;
}
.swiperItem .title {
  font-size: 30rpx;
  line-height: 80rpx;

}

.musicItem {
  /* 当一个元素设置为flex,其子元素会自动成为block元素*/
  display: flex;
  margin-bottom: 20rpx;
}

.musicItem image{
  width: 100rpx;
  height: 100rpx;
  border-radius: 6rpx;
}

.musicItem .count {
  width: 100rpx;
  height: 100rpx;
  text-align: center;
  line-height: 100rpx;
}

.musicItem .musicName {
  height: 100rpx;
  line-height: 100rpx;
  max-width: 400rpx;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}