微信小程序自定义tabbar底部导航栏

news/2024/7/19 14:46:24 标签: 微信小程序, 前端, 小程序, js, css

最近开始在写一个零基础从0写一个失物招领小程序的系列视频,涉及到了自定义tabBar,也就是底部导航栏的内容。看了下我的博客似乎之前没更新过,所以给大家写一篇。

首先我们先去看下官方文档:

在这里插入图片描述
其实大致来说,可以总结为三点。

  1. 即便是自定义tabBar,也需要去app.json里进行配置文件的声明,也就是iconPathpagePathselectedIconPathtext这些。
  2. 需要自己写一个组件,来渲染tabBar
  3. 在更新选中态的时候,需要借助getTabBar来拿到tabBar实例

一步一步来。

配置tabBar

app.json

js">{
  "pages": [
    "pages/index/index",
    "pages/classify/classify",
    "pages/collection/collection",
    "pages/me/me"
  ],
  "window": {
    "backgroundColor": "#F6F6F6",
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#ff70b4",
    "navigationBarTitleText": "失物招领",
    "navigationBarTextStyle": "white"
  },
  "tabBar": {
      "custom": true,
      "list": [
          {
             "iconPath": "images/index.png",
             "pagePath": "pages/index/index",
             "selectedIconPath": "images/index_fill.png",
             "text": "首页" 
          },
          {
            "iconPath": "images/classify.png",
            "pagePath": "pages/classify/classify",
            "selectedIconPath": "images/classify_fill.png",
            "text": "分类" 
         },
         {
            "iconPath": "images/collection.png",
            "pagePath": "pages/collection/collection",
            "selectedIconPath": "images/collection_fill.png",
            "text": "收藏夹" 
         },
         {
            "iconPath": "images/me.png",
            "pagePath": "pages/me/me",
            "selectedIconPath": "images/me_fill.png",
            "text": "我的" 
         }
      ]
  },
  "sitemapLocation": "sitemap.json",
  "style": "v2"
}

像使用原生tabBar一样,进行配置项的编写,但是额外注意的一点是,需要写一个custom属性,设置为true,这个是关键,表明自己需要自定义。

然后就进行第二步,自己写这个tabBar组件。

编写tabBar组件的内容

在写的时候要注意一点,不要写在pages里,也不要写在components里。

虽然自定义的tabBar是一个组件,但是比较特别,要独立新建一个文件夹,与pagescomponents同级。
在这里插入图片描述

这个文件夹的名字也比较讲究,根据官方文件的提示,文件夹的名字要命名为custom-tab-bar,如果不写这个名字,还要去改配置。

在这里插入图片描述

然后就可以去写这个组件的内容了,按照你自己的需求,进行jswxmlwxss的内容编写,和普通组件就没什么区别了。

custom-tab-bar/index.js

js">Component({
    data: {
        select: 0,
        list: [
            {
               iconPath: "/images/index.png",
               pagePath: "/pages/index/index",
               selectedIconPath: "/images/index_fill.png",
               text: "首页",
               type: 0
            },
            {
               iconPath: "/images/classify.png",
               pagePath: "/pages/classify/classify",
               selectedIconPath: "/images/classify_fill.png",
               text: "分类",
               type: 0
           },
           {
               type: 1,
           },
           {
              iconPath: "/images/collection.png",
              pagePath: "/pages/collection/collection",
              selectedIconPath: "/images/collection_fill.png",
              text: "收藏夹",
              type: 0,
           },
           {
              iconPath: "/images/me.png",
              pagePath: "/pages/me/me",
              selectedIconPath: "/images/me_fill.png",
              text: "我的",
              type: 0
           }
        ]
    },

    methods: {
        selectPage(e) {
            const { index, page, type } = e.currentTarget.dataset;
            if (index !== this.data.select && type === 0) {
                wx.switchTab({
                  url: page,
                })
            }
        }
    }
})

custom-tab-bar/index.json

js">{
    "component": true
}

custom-tab-bar/index.wxml

js"><view class="tabbar">
    <view 
        class="tabbar-item {{ select === index ? 'tabbar-select' : '' }}" wx:for="{{ list }}" 
        wx:key="index"
        data-page="{{ item.pagePath }}"
        data-index="{{ item.index }}"
        data-type="{{ item.type }}"
        bindtap="selectPage"
    >
        <block wx:if="{{ item.type === 0 }}">
            <image src="{{ select === index ?  item.selectedIconPath : item.iconPath }}"></image>
            <text>{{ item.text }}</text>
        </block>
        <block wx:else>
            <view class="publish">
            <image src="../images/add.png"></image>
            </view>
        </block>
    </view>
</view>

custom-tab-bar/index.wxss

css">.tabbar {
    width: 100%;
    display: flex;
    background-color: #fff;
    position: fixed;
    bottom: 0;
    padding-bottom: env(safe-area-inset-bottom);
    padding-top: 10rpx;
    z-index: 9999;
}

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

.tabbar-item image {
    width: 50rpx;
    height: 50rpx;
}

.tabbar-item text {
    font-size: 26rpx;
    margin-top: 10rpx;
}

.tabbar-item .publish {
    width: 65rpx;
    height: 65rpx;
    background-color: #ff90ba;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: auto;
}

.tabbar-select {
    color: #ff90ba;
}

需要注意几点就是:

  1. index.json里要设置componenttrue
  2. index.js里的内容格式与常规的组件一样
  3. 因为是自定义组件,要注意的是,在写组件最外层的标签样式时,如果不写padding-bottomtabBar的大部分内容会被手机的底部遮挡住。
    在这里插入图片描述
    那么问题就来了,这个padding-bottom写多少合适呢,因为不同手机、不同终端这个底部遮挡区域都是不一样的。小程序>微信小程序为我们内置了这个值,env(safe-area-inset-bottom),将padding-bottom设置为这个值,它就会根据终端动态的计算一个合理的值。
    在这里插入图片描述
    这样就很好了。

切换tabBar的选中态

然后还剩最后一个步骤,就是在跳转其它tabBar页面的时候,选中态的切换,因为我们在组件内声明了select变量,其实动态的改这个值就可以。

但是不能直接在组件内进行更改,要在跳转页面的过程中进行更改。

比如select默认是0,代表A页面,当我们从A页面跳转到B页面的时候,我们就需要将select赋值为1,当然这也不是绝对的,这要取决于你组件内选中态的切换逻辑是怎么样的。

比如我的:

js">       list: [
            {
               iconPath: "/images/index.png",
               pagePath: "/pages/index/index",
               selectedIconPath: "/images/index_fill.png",
               text: "首页",
               type: 0
            },
            {
               iconPath: "/images/classify.png",
               pagePath: "/pages/classify/classify",
               selectedIconPath: "/images/classify_fill.png",
               text: "分类",
               type: 0
           },
           {
               type: 1,
           },
           {
              iconPath: "/images/collection.png",
              pagePath: "/pages/collection/collection",
              selectedIconPath: "/images/collection_fill.png",
              text: "收藏夹",
              type: 0,
           },
           {
              iconPath: "/images/me.png",
              pagePath: "/pages/me/me",
              selectedIconPath: "/images/me_fill.png",
              text: "我的",
              type: 0
           }
        ]

我这样来声明的话,select和页面的对应关系就是:

select: 0 = index页面
select: 1 = classify页面
select: 3 = collection页面
select: 4 = me页面

那么问题就来了,我如何在页面切换的时候,改自己这个自定义tabBar内的值呢。

系统为我们提供了getTabBar方法,你输出一下this,就可以看到这个方法,这个方法会返回给我们自定义tabBar的组件实例,也就是说,可以这样写:

js">	this.getTabBar().setData({
		select: xxx
	})

有了这个方法之后,我们在所有tabBar涉及到的页面的onShow方法里,进行执行上述代码即可。

比如在首页的index.js里:

js">  onShow: function () {
    if (typeof this.getTabBar === 'function' && this.getTabBar()) {
        this.getTabBar().setData({
            select: 0
        })
    }
  },

进行if判断的原因是进行兼容,避免报错。在getTabBar这个方法存在的前提下,再进行操作。

在分类页的index.js里:

js">  onShow: function () {
    if (typeof this.getTabBar === 'function' && this.getTabBar()) {
        this.getTabBar().setData({
            select: 1
        })
    }
  },

至此,我们就完成了,自定义tabBar底部导航栏的全部内容,大致分为三步:在app.json里进行tabBar的配置、编写组件内容、通过getTabBar方法切换选中态。

工种号:Code程序人生


http://www.niftyadmin.cn/n/1576325.html

相关文章

《Hadoop与大数据挖掘》一2.4.2 MapReduce原理

本节书摘来华章计算机《Hadoop与大数据挖掘》一书中的第2章 &#xff0c;第2.4.2节&#xff0c;张良均 樊 哲 位文超 刘名军 许国杰 周 龙 焦正升 著 更多章节内容可以访问云栖社区“华章计算机”公众号查看。 2.4.2 MapReduce原理 1.通俗理解MapReduce原理现在你接到…

将luarocks整合进openresty

缘由 随着功能需求的深入, openresty领域的包已经不够用了, 需要lua领域本身累积的库, 也就是luarocks. 本文讲解了windows 10桌面和ubuntu server两套系统的方法 Ubuntu Server 比较简单, 无脑敲命令即可 $ wget https://luarocks.org/releases/luarocks-2.4.1.tar.gz $ tar z…

用 Docker Machine 创建 Azure 虚拟主机

搭建环境向来是一个重复造轮子的过程&#xff0c;Docker Machine 则把用户搭建 Docker 环境的各种方案汇集在了一起。笔者在《Docker Machine 简介》一文中演示了使用 Docker Machine 在本地的 vSphere 主机中安装 Docker 环境。但是在云计算大爆炸的今天&#xff0c;真正让我们…

阿里云大数据利器Maxcompute学习之--窗口函数实现分组TopN

看到很多用户经常会问如何对分组内进行排序。官方文档&#xff1a;https://help.aliyun.com/document_detail/34994.html?spm5176.doc27891.6.611.Q1bk3j例如需求&#xff1a; odps 里面能否做排名操作&#xff0c;比如一个表里面有 用户ID 和 金额 两个字段&#xff0c;用金额…

redis集群cluster搭建,扩容缩容

为什么80%的码农都做不了架构师&#xff1f;>>> 1. 概要说明 1.1. 概述 本文旨在说明平台部署环境搭建的过程和详细步骤说明&#xff0c;为后面系统部署提供清晰的参考依照。 以下搭建部署的环境&#xff0c;为一个小型的分布式集群环境。满足负载均衡和单点…

epel安装第三方扩展源后,运行yum报错的解决方案

yum安装报错&#xff1a;Cannot retrieve metalink for repository: epel. Please verify its path and try again 解决方法&#xff1a; 一句话&#xff1a;把/etc/yum.repos.d/epel.repo&#xff0c;文件baseurl的注释放开&#xff0c;mirrorlist注释掉。 具体如下&#xff1…

标准C++中的String类的使用

要使用标准C中的String类&#xff0c;必须包含#include<string>&#xff08;注意不是<string.h>带.h的是C语言中的头文件&#xff09; 作者&#xff1a;耑新新&#xff0c;发布于 博客园 转载请注明出处&#xff0c;欢迎邮件交流&#xff1a;zhuanxinxinfoxmail…

Netty学习之旅------高仿Dubbo服务调用模型、私有协议实现、编码解码器使用实践

request.setContentLength(contentLength); //这里&#xff0c;其实上层应用不需要知道请求包的长度&#xff0c;这里属于多于的操作 LogUtils.log(“RequestFrameDecoder 成功从服务端响应中解析出业务包,requestId:%d”, requestId); } else if (requestType 2) { // 此处…