自定义tabbar 【恋人小清单开发总结】
发布于 5 年前 作者 ykang 3766 次浏览 来自 分享

看官方demo的小伙伴知道,自定义tabbar需要在小程序根目录底下建一个名叫custom-tab-bar的组件(我有试过,如果放在components目录里面小程序会识别不了),目前我自己实现的效果是:通过在配置可以切换tab,也可以点击tab后重定向到新页面,支持隐藏tabbar,同时也可以显示右上角文本和小红点。

官方demo里面用的是cover-view,我改成view,因为如果页面有弹窗的话我希望可以盖住tabbar

总结一下有以下注意点:

1、tabbar组件的目录命名需要是custom-tab-bar

2、app.json增加自定义tabbar配置

3、wx.navigateTo不允许跳转到tabb页面

4、进入tab页面时,需要调用tabbar.js手动切换tab


效果图:

可以扫码体验

代码目录如下:

代码如下:

app.json增加自定义tabbar配置

"tabBar": {
  "custom": true,
  "color": "#7A7E83",
  "selectedColor": "#3cc51f",
  "borderStyle": "black",
  "backgroundColor": "#ffffff",
  "list": [
    {
      "pagePath": "pages/love/love",
      "text": "首页"
    },
    {
      "pagePath": "pages/tabbar/empty",
      "text": "礼物说"
    },
    {
      "pagePath": "pages/tabbar/empty",
      "text": "恋人圈"
    },
    {
      "pagePath": "pages/me/me",
      "text": "我"
    }
  ]
},


自定义tabbar组件代码如下

index.js

//api.js是我自己对微信接口的一些封装
const api = require('../utils/api.js');
//获取应用实例
const app = getApp();
Component({
    data: {
        isPhoneX: false,
        selected: 0,
        hide: false,
        list: [{
            showRedDot: false,
            showBadge: false,
            badgeText: "",
            pagePath: "/pages/love/love",
            iconPath: "/images/tabbar/home.png",
            selectedIconPath: "/images/tabbar/home-select.png",
            text: "首页"
        }, {
            showRedDot: false,
            showBadge: false,
            badgeText: "",
            pagePath: "/pages/tabbar/empty",
            navigatePath: "/pages/gifts/giftList",
            iconPath: "/images/tabbar/gift.png",
            selectedIconPath: "/images/tabbar/gift-select.png",
            text: "礼物说",
            hideTabBar: true
        }, {
            showRedDot: false,
            showBadge: false,
            badgeText: "",
            pagePath: "/pages/tabbar/empty",
            navigatePath: "/pages/moments/moments",
            iconPath: "/images/tabbar/lover-circle.png",
            selectedIconPath: "/images/tabbar/lover-circle-select.png",
            text: "恋人圈",
            hideTabBar: true
        }, {
            showRedDot: false,
            showBadge: false,
            badgeText: "",
            pagePath: "/pages/me/me",
            iconPath: "/images/tabbar/me.png",
            selectedIconPath: "/images/tabbar/me-select.png",
            text: "我"
        }]
    },
    ready() {
        // console.error("custom-tab-bar ready");
        this.setData({
            isPhoneX: app.globalData.device.isPhoneX
        })
    },
    methods: {
        switchTab(e) {
            const data = e.currentTarget.dataset;
            console.log("tabBar参数:", data);
            api.vibrateShort();
            if (data.hideTabBar) {
                api.navigateTo(data.navigatePath);
            } else {
                /*this.setData({
                    selected: data.index
                }, function () {
                    wx.switchTab({url: data.path});
                });*/
                /**
                 * 改为直接跳转页面,
                 * 因为发现如果先设置selected的话,
                 * 对应tab图标会先选中,然后页面再跳转,
                 * 会出现图标变成未选中然后马上选中的过程
                 */
                wx.switchTab({url: data.path});
            }
        },

        /**
         * 显示tabbar
         * [@param](/user/param) e
         */
        showTab(e){
            this.setData({
                hide: false
            }, function () {
                console.log("showTab执行完毕");
            });
        },

        /**
         * 隐藏tabbar
         * [@param](/user/param) e
         */
        hideTab(e){
            this.setData({
                hide: true
            }, function () {
                console.log("hideTab执行完毕");
            });
        },

        /**
         * 显示小红点
         * [@param](/user/param) index
         */
        showRedDot(index, success, fail) {
            try {
                const list = this.data.list;
                list[index].showRedDot = true;
                this.setData({
                    list
                }, function () {
                    typeof success == 'function' && success();
                })
            } catch (e) {
                typeof fail == 'function' && fail();
            }
        },

        /**
         * 隐藏小红点
         * [@param](/user/param) index
         */
        hideRedDot(index, success, fail) {
            try {
                const list = this.data.list;
                list[index].showRedDot = false;
                this.setData({
                    list
                }, function () {
                    typeof success == 'function' && success();
                })
            } catch (e) {
                typeof fail == 'function' && fail();
            }
        },

        /**
         * 显示tab右上角文本
         * [@param](/user/param) index
         * [@param](/user/param) text
         */
        showBadge(index, text, success, fail) {
            try {
                const list = this.data.list;
                Object.assign(list[index], {showBadge: true, badgeText: text});
                this.setData({
                    list
                }, function () {
                    typeof success == 'function' && success();
                })
            } catch (e) {
                typeof fail == 'function' && fail();
            }
        },

        /**
         * 隐藏tab右上角文本
         * [@param](/user/param) index
         */
        hideBadge(index, success, fail) {
            try {
                const list = this.data.list;
                Object.assign(list[index], {showBadge: false, badgeText: ""});
                this.setData({
                    list
                }, function () {
                    typeof success == 'function' && success();
                })
            } catch (e) {
                typeof fail == 'function' && fail();
            }
        }
    }
});

index.html

{{item.badgeText}}

i__ndex.json__

{
  "component": true,
  "usingComponents": {}
}

index.wxss

[@import](/user/import) "/app.wxss";
.footer-tool-bar{
    background-color: #fff;
    height: 100rpx;
    width: 100%;
    position: fixed;
    bottom: 0;
    z-index: 100;
    text-align: center;
    font-size: 24rpx;
    transition: transform .3s;
    border-radius: 30rpx 30rpx 0 0;
    /*padding-bottom: env(safe-area-inset-bottom);*/
    box-shadow:0rpx 0rpx 18rpx 8rpx rgba(212, 210, 211, 0.35);
}
.footer-tool-bar .tab{
    color: #242424;
    height: 100%;
    line-height: 100rpx;
}
.footer-tool-bar .focus{
    color: #f96e49;
    font-weight: 500;
}
.footer-tool-bar .icon{
    width: 44rpx;
    height: 44rpx;
    margin: 18rpx auto;
}
.footer-tool-bar .text{
    line-height: 80rpx;
    height: 80rpx;
    position: relative;
    display: inline-block;
    padding: 0rpx 40rpx;
    box-sizing: border-box;
    margin: 10rpx auto;
}
.footer-tool-bar .dot{
    position: absolute;
    top: 16rpx;
    right: 16rpx;
    height: 16rpx;
    width: 16rpx;
    border-radius: 50%;
    background-color: #f45551;
}
.footer-tool-bar .badge{
    position: absolute;
    top: 8rpx;
    right: 8rpx;
    height: 30rpx;
    width: 30rpx;
    line-height: 30rpx;
    border-radius: 50%;
    background-color: #f45551;
    color: #fff;
    text-align: center;
    font-size: 20rpx;
    font-weight: 450;
}
.hide{
    transform: translateY(100%);
}

app.wxss(这里的样式文件是我用来存放一些公共样式)

/**app.wxss**/
page {
    background-color: #f5f5f5;
    height: 100%;
    -webkit-overflow-scrolling: touch;
}

.container {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    box-sizing: border-box;
}

.blur {
    filter: blur(80rpx);
    opacity: 0.65;
}

.flex-center {   
    display: flex;
    align-items: center;
    justify-content: center;
}

.flex-column {
    display: flex;
    /*垂直居中*/
    align-items: center;
    /*水平居中*/
    justify-content: center;
    flex-direction: column;
}

.flex-start-horizontal{
    display: flex;
    justify-content: flex-start;
}
.flex-end-horizontal{
    display: flex;
    justify-content: flex-end;
}

.flex-start-vertical{
    display: flex;
    align-items: flex-start;
}
.flex-end-vertical{
    display: flex;
    align-items: flex-end;
}

.flex-wrap {
    display: flex;
    flex-wrap: wrap;
}

.flex-full {
    flex: 1;
}

.reset-btn:after {
    border: none;
}

.reset-btn {
    background-color: #ffffff;
    border-radius: 0;
    margin: 0;
    padding: 0;
    overflow: auto;
}

.loading{
    opacity: 0;
    transition: opacity 1s;
}

.load-over{
    opacity: 1;
}

.phx_68{
    padding-bottom: 68rpx;
}

.phx_34{
    padding-bottom: 34rpx;
}

另外我还对tabbar的操作做了简单的封装:

tabbar.js

const api = require('/api.js');

/**
 * 切换tab
 * [@param](/user/param) me
 * [@param](/user/param) index
 */
const switchTab = function (me, index) {
    if (typeof me.getTabBar === 'function' && me.getTabBar()) {
        console.log("切换tab:", index);
        me.getTabBar().setData({
            selected: index
        })
    }
};

/**
 * 显示 tabBar 某一项的右上角的红点
 * [@param](/user/param) me
 * [@param](/user/param) index
 */
const showRedDot = function (me, index, success, fail) {
    if (typeof me.getTabBar === 'function' && me.getTabBar()) {
        me.getTabBar().showRedDot(index, success, fail);
    }
};

/**
 * 隐藏 tabBar 某一项的右上角的红点
 * [@param](/user/param) me
 * [@param](/user/param) index
 */
const hideRedDot = function (me, index, success, fail) {
    if (typeof me.getTabBar === 'function' && me.getTabBar()) {
        me.getTabBar().hideRedDot(index, success, fail);
    }
};

/**
 * 显示tab右上角文本
 * [@param](/user/param) me
 * [@param](/user/param) index
 * [@param](/user/param) text
 */
const showBadge = function (me, index, text, success, fail) {
    if (typeof me.getTabBar === 'function' && me.getTabBar()) {
        me.getTabBar().showBadge(index, text, success, fail);
    }
};

/**
 * 隐藏tab右上角文本
 * [@param](/user/param) me
 * [@param](/user/param) index
 */
const hideBadge = function (me, index, success, fail) {
    if (typeof me.getTabBar === 'function' && me.getTabBar()) {
        me.getTabBar().hideBadge(index, success, fail);
    }
};

/**
 * 显示tabbar
 * [@param](/user/param) me
 * [@param](/user/param) success
 */
const showTab = function(me, success){
    if (typeof me.getTabBar === 'function' && me.getTabBar()) {
        me.getTabBar().showTab(success);
    }
};

/**
 * 隐藏tabbar
 * [@param](/user/param) me
 * [@param](/user/param) success
 */
const hideTab = function(me, success){
    if (typeof me.getTabBar === 'function' && me.getTabBar()) {
        me.getTabBar().hideTab(success);
    }
};

module.exports = {
    switchTab, showRedDot, hideRedDot, showBadge, hideBadge, showTab, hideTab
};

最后,进入到tab对应页面的时候要手动调用一下swichTab接口,然tabbar聚焦到当前tab

/**
 * 生命周期函数--监听页面显示
 */
onShow: function () {
    tabbar.switchTab(this, this.data.tabIndex);//tabIndex是当前tab的索引
}
2 回复

我奉上天之命, 拯救世道人心。 我出生草堂内, 我使命为人类。 我一人来田间, 我正在等你们。

建议结尾放个代码片段。方便直接查看效果。

https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html

回到顶部