记一次微信小程序自定义tabbar大作战

2,278 阅读3分钟

前言:实现一个头部的tab,如图:

类似这样的头部tab,我一共尝试了三种方法来实现,只有最后一种是最完美的

一、使用template微信小程序模板

1、在根目录下新建template文件:

2、在需要使用tabbar的wxml文件里面引入模板:

<import src="/templates/tabBar/tabBar.wxml" />
<template is="tabBar" data="{{marginLefts:132,activeIndex:2}}"></template>

此处的data是传入模板中的变量,可在模板中直接使用,注意:模板没有单独的js和json文件 3、在对应wxml页面的wxss文件里面引入模板样式文件:

@import "../../template/tabBar/tabBar.wxss";

模板的应用弊端是页面在跳转的时候都会重新加载,导致在跳转的过程中会有闪动,不美观

二、使用微信小程序自定义tabBar

1、配置app.json文件,在app.json中添加如下代码:

"tabBar": {
    "custom": true,
    "color": "#7A7E83",
    "selectedColor": "#3cc51f",
    "borderStyle": "black",
    "backgroundColor": "#ffffff",
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "页面1"
      },
      {
        "pagePath": "pages/second/second",
        "text": "页面2"
      },
      {
        "pagePath": "pages/third/third",
        "text": "页面3"
      },
      {
        "pagePath": "pages/fouth/fouth",
        "text": "页面4"
      }
    ]
  },

注意:这里的页面1234是以组件Component的形式而不是Page 2、新建自定义tabBar的默认文件夹:

注意:必须要用此文件名才能识别到

3、编写custom-tab-bar文件中的index.js

const app = getApp()
Component({
  data: {
    selected: 0,//当前选中的第几个tab
    color: "#23292f",
    selectedColor: "#ffffff",
    list: [
      {
        "pagePath": "pages/index/index",
        "text": "页面1"
      },
      {
        "pagePath": "pages/second/second",
        "text": "页面2"
      },
      {
        "pagePath": "pages/third/third",
        "text": "页面3"
      },
      {
        "pagePath": "pages/fouth/fouth",
        "text": "页面4"
      }
    ],
    marginLefts:0,
    styleLeft: '0rpx',
    titleBarHeight: app.globalData.titleBarHeight,
    statusBarHeight: app.globalData.statusBarHeight
  },
  /**
   * 数据监听
   */
  observers:{
     'marginLefts':function(val) {//此处我做了tab切换时的一些动画效果,可略过
       let lefts = val + 'rpx'
       this.setData({
         styleLeft: app.globalData.styleLeft
       })
       setTimeout(() => {
         this.setData({
           styleLeft: lefts
         })
         app.globalData.styleLeft = lefts
       }, 100)
       app.globalData.styleLeft = lefts
     }
  },

  methods: {
    switchTab(e) {//点击tab切换页面
      const data = e.currentTarget.dataset
      const url = data.path
      wx.switchTab({url})
    }
  }
})

4、custom-tab-bar文件中除了js以外的其他json、wxml、wxss就自己写需要的style把,其中wxml中的标签要使用以及,其原因时这对标签可以使其布局在最上方。如果是需要tabbar浮动在顶部还需要再wxss文件中设置外层盒子的样式:

.tab-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  width: 750rpx;
  height: 170rpx;
  z-index: 99999999;
}

相反如果是需要tabbar再底部就将其top改为bottom,如果是bottom还需要加上刘海屏的安全距离css样式

padding-bottom: 0px;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);

5、页面1234中的配置

  // pageLifetimes: {
  //   show() {
  //     if (typeof this.getTabBar === 'function' && this.getTabBar()) {
  //         try {
  //           this.getTabBar().setData({
  //             selected: 1,
  //             marginLefts: 132
  //           })
  //         } catch (e) { }
  //     }
  //   },
  // }

注意:必须要加上此段code,不然不会有选中的效果

6、弊端

再页面跳转的过程中虽说tabbar不会变,但是再大部分机型上面是会出现闪动的效果,并且会再次执行其生命周期以及data初始化,就如同再页面加入组件的效果,因为这样,所以在做切换页面是tabbar上的滑块这个效果的时候就没有平滑过渡的效果,以至于使用css3中的transition和使用小程序自带的wx.createAnimation也没有平滑过渡的效果。当然也有解决的办法,就是把相关的变量存在全局变量中,但是最后的效果还是不尽人意,代码如下:

/**
   * 数据监听
   */
  observers:{
     'marginLefts':function(val) {//监听页面跳转时在show生命周期里面定义的marginLefts的变化来做响应的数据更新
       let lefts = val + 'rpx'
       this.setData({
         styleLeft: app.globalData.styleLeft
       })
       setTimeout(() => {
         this.setData({
           styleLeft: lefts
         })
         app.globalData.styleLeft = lefts
       }, 100)
       app.globalData.styleLeft = lefts
     }
  },

三、最完美的实现方案

只写一个页面,其中引入其他四个页面的组件,在切换的时候显示不同的组件即可