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

2023-11-08

概要

微信小程序自定义底部导航栏,原生实现,不包含其他任何第三方组件,比较干净,开箱即用
效果预览:
微信小程序底部导航栏

功能

  1. 可自定义底部导航栏列表样式
  2. 可自定义每个菜单的默认、激活后的图标和文字样式
  3. 可自定义是否添加中间的大图标菜单,当然也可自定义大图标的默认与激活样式
  4. 可自定义激活动画,默认这个心跳过渡动画
  5. 可获取到底部导航栏高度,存在app全局变量中,其他页面有特殊需求需要动态计算页面高度时可能需要用到此属性
  6. 解决点击导航菜单时,激活的菜单貌似并不同步的问题
  7. 底部根据是否有安全距离自动调整

源码

不废话,直接贴上完整源码

源码结构
js

const app = getApp()
Component({
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    selected: 0, // 激活的tab
    // tabber列表,与app.json一致
    color: "#666666",
    selectedColor: "#ff0000",
    backgroundColor: "#ffffff",
    // 注: list中的pagePath需要加'/'开头,否则在switchTab跳转url时会自带/src/pages开头导致路径错误
    list: [{
      "pagePath": "/src/pages/home/home",
      "icon": "./images/home.png",
      "iconActive": "./images/home-a.png",
      "text": "首页",
    }, {
      "pagePath": "/src/pages/monitor/monitor",
      "icon": "./images/relic.png",
      "iconActive": "./images/relic-a.png",
      "text": "文物监测"
    }, {
      "pagePath": "/src/pages/map/map",
      "icon": "./images/map.png",
      "iconActive": "./images/map.png",
      "center": true, // 中间大图标的参数,true时就会变大,默认非大图标
    }, {
      "pagePath": "/src/pages/news/news",
      "icon": "./images/hot.png",
      "iconActive": "./images/hot-a.png",
      "text": "文博资讯"
    }, {
      "pagePath": "/src/pages/mine/mine",
      "icon": "./images/mine.png",
      "iconActive": "./images/mine-a.png",
      "text": "我的"
    }],
    tabbarHeight: 0
  },

  lifetimes: {
    attached: function () {
      // 获取tab栏高度
      const query = wx.createSelectorQuery().in(this)
      query.select('#tabbar').boundingClientRect((res) => {
        // console.log('tab栏dom', res);
        this.setData({
          tabbarHeight: res.height
        })
        // 将tab栏高度设置进全局数据
        app.globalData.tabbarHeight = res.height
      }).exec()

      /**
       * 将初始化tabbar栏方法存入全局
       * @param {*} that 传入当前tab页面的this实例
       * @param {*} index 传入当前tab页面的索引
       * 若无该方法,会导致点击tab时激活的tab顺序错乱!
       * 例如在home首页onShow的生命周期钩子中,getApp().globalData.initTabbar(this, 0)
       */
      app.globalData.initTabbar = (that, index) => {
        if (typeof that.getTabBar === 'function' && that.getTabBar()) {
          that.getTabBar().setData({
            selected: index
          })
        }
      }
    }
  },

  /**
   * 组件的方法列表
   */
  methods: {
    switchTab(e) {
      // bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡
      const {
        index,
        url
      } = e.currentTarget.dataset
      if (this.data.selected !== index) {
        this.setData({
          selected: index
        })
        wx.switchTab({
          url: url,
        })
      }
    }
  }
})

wxml

<view class="tabbar" style="background-color: {{backgroundColor}};" id="tabbar">
  <view class="{{'tab'}} {{selected == index ? 'beat' : ''}}" wx:for="{{list}}" wx:key="item" catchtap="switchTab" data-index="{{index}}" data-url="{{item.pagePath}}">
    <view class="{{'tab-icon'}} {{item.center ? 'tab-icon-center' : ''}}" style="background-color: {{backgroundColor}};">
      <image style="width:100%;height:100%;" src="{{selected == index ? item.iconActive : item.icon}}" mode="" />
    </view>
    <view style="font-size:24rpx;color:{{selected == index ? selectedColor : color}}">
      {{item.text}}
    </view>
  </view>
</view>

wxss

.tabbar {
  position: fixed;
  bottom: 0;
  width: 100%;
  height: 120rpx;
  background: rgba(255, 255, 255, 1);
  box-shadow: 0 2px 16px rgba(184, 184, 210, 0.5);
  /* 利用ios新增的 env() 和 constant() 特性,自动计算底部安全距离 */
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);

  display: flex;
  justify-content: space-evenly;
}

.tab {
  width: 100%;
  height: 100%;
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  position: relative;
}

.tab-icon {
  width: 68rpx;
  height: 68rpx;
}

.tab-icon-center {
  width: 160rpx;
  height: 160rpx;
  position: absolute;
  top: -24rpx;
  padding: 12rpx;
  box-sizing: border-box;
  border-radius: 80rpx;
}

.beat {
  animation: beat 0.8s both;
}

@keyframes beat {
  0% {
    transform: scale3d(1, 1, 1);
  }
  30% {
    transform: scale3d(1.05, 0.95, 1);
  }
  40% {
    transform: scale3d(0.85, 1.15, 1);
  }
  50% {
    transform: scale3d(1.15, 0.85, 1);
  }
  65% {
    transform: scale3d(0.95, 1.05, 1);
  }
  75% {
    transform: scale3d(1.05, 0.95, 1);
  }
  100% {
    transform: scale3d(1, 1, 1);
  }
}

不要忘了在app.json文件中添加 tabBar 属性

"tabBar": {
    "custom": true,
    "color": "#666666",
    "selectedColor": "#ff0000",
    "backgroundColor": "#000000",
    "list": [
      {
        "pagePath": "src/pages/home/home",
        "text": "首页"
      },
      {
        "pagePath": "src/pages/monitor/monitor",
        "text": "监测"
      },
      {
        "pagePath": "src/pages/map/map",
        "text": "地图"
      },
      {
        "pagePath": "src/pages/news/news",
        "text": "资讯"
      },
      {
        "pagePath": "src/pages/mine/mine",
        "text": "我的"
      }
    ]
  }

细节

  • 注意上述js代码块中 initTabbar 方法,需要在每个tabbar页面使用
    例如首页是home,那么就在home.js中的onShow生命周期钩子中,写上getApp().globalData.initTabbar(this, 0)即可,参数中的0就是该tabbar的索引位置,第一个页面就是0,第二个就是1,以此类推
  • 注意页面路径问题,在代码块中有注释
  • 注意这个custom-tab-bar组件要放在根目录哦

改进

有问题和改进建议还请在评论区留言,觉得代码还不错的话,还望点个赞让更多人看到哦

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

微信小程序自定义底部导航栏 的相关文章

  • Spring Boot官方例子《Developing Your First Spring Boot Application》无法运行

    官方的第一个例子就卡住了 https docs spring io spring boot docs current reference htmlsingle getting started first application 按照要求 一
  • 【消息队列】kafka consumer demo

    package consumer import org apache kafka clients consumer ConsumerConfig import org apache kafka clients consumer Consum
  • git常用命令及免密登录

    常用命令 git config global user name 用户名 设置用户签名 git config global user email 邮箱 设置用户签名 git init 初始化本地库 git status 查看本地库状态 gi
  • 多线程写图像文件的一点小测试(Boost + Gual)

    转载自 http blog csdn net liminlu0314 article details 7420484 在处理遥感图像中 发现往往比较耗时的是在数据的IO中 尤其是在O 写入 的时候更加耗时 GDAL可以支持图像的多线程写入
  • 蓝桥杯——修改数组

    问题描述 给定一个长度为N的数组A A1 A2 AN 数组中有可能有重复出现的整数 在小明要按以下方法将其修改为没有重复整数的数组 小明会依次修改A2 A3 AN 当修改Ai时 小明会检查Ai是否在A1 Ai 1中出现过 如果出现过 则小明
  • C#中的事件和委托_札记1

    C 中的事件和委托 札记1 委托 自定义委托 静态方法 被委托 委托是一种类型 所以任何定义类的地方都可以定义委托类型 自定义委托的基本格式示例如下

随机推荐

  • RobotFramework 安装教程

    动化测试框架 具盘点 安装步骤 页面介绍 标准库 不需要安装 直接 RF 带 扩展库 快捷键 实战 RobotFramework 安装教程 动化测试框架 具盘点 java junit和testng 具 postmen newman git
  • html动态爱心代码【二】(附源码)

    目录 前言 效果演示 内容修改 完整代码 总结 前言 七夕马上就要到了 为了帮助大家高效表白 下面再给大家带来了实用的HTML浪漫表白代码 附源码 背景音乐 可用于520 情人节 生日 表白等场景 可直接使用 效果演示 内容修改 文案 di
  • go - flag包(处理命令行参数小能手)

    前言 在golang中有很多方法来处理命令行参数 简单情况下可以不使用任何库 直接使用os Args 但是golang标准库提供了flag包来专门处理命令行参数 当然还有第三方提供的处理命令行参数的库cobra cli可以参考 flag包绑
  • qt没有mysql驱动的解决办法

    qt没有mysql驱动的解决办法 第一部分 qtcreator上没有mysql驱动的解决办法 第一步 找到你的qt的版本的源码src 第二步 点击mysql pro 电脑会自动打开qtcreater 然后就是进行编译器的选择 我选择的是 在
  • BootStrap的使用

    是别人帮我们已经写好的css样式 我们如果想要使用这个BootStrap 下载BootStrap 使用 在页面上引入BootStrap 自定置 先在网上下载好BootStrap 并导入到Pycharm 引入BootStrap 注意引入的是
  • 【react】文本内容超过一行,显示为单行省略,并且出现icon图标;点击此图标,可以进行展开或收起文本功能实现

    需求 多条数据展示 每条数据的文本内容不超过一行 文本内容为一行时 不显示 展开收起icon图标 文本超过一行时 内容单行省略 并且显示 点击图标 图标切换为收起按钮 后端返回数据 const data name 测试测试测试 time 2
  • BinaryViewer(二进制查看器)使用教程(附下载)

    1 BinaryViewer操作界面 2 面板功能 1 数据面板 此面板占据了屏幕的最中央部分 其目的是顺序显示打开的文件或物理驱动器中的所有数据 此面板通常以两列显示数据 每列都可以按用户选择的格式显示数据 请转到数据显示模式 查看如何更
  • 对indexedDB的一些使用方法

    indexedDB的使用 1 打开数据库和创建数据仓库 createDB function dbName version tableName key cursor callBack 参数为 dbName数据库名 version版本号 tab
  • Python运维开发工程师养成记(while循环语句)

    图示 案例 contine和break用法 无限循环 while else语句 今天分享到这里 喜欢的盆友可以关注一下博主 链接 https ke qq com course 4300856 tuin d8aedf68
  • android 环信集成,Android 环信集成使用总结

    最近因为项目需要 需要集成环信 对于一些账号的注册 配置的添加官方文档上写的都有 就不在记录 就记录一下集成过程中遇到的问题 环信demo中的代码太乱 而且一些功能用不到 我们就移值些自己有用的放到自己的项目中 1 消息监听 环信在收到消息
  • mysql如何查询成绩前5名_sql 语句查询 前5名后5名的成绩

    蝴蝶不菲 两种办法 分别求最大和最小 然后union allselect from select from table order by 成绩 where rownum lt 5union allselect from select fro
  • 每隔5分钟输出最近一小时内点击量最多的前N个商品(SQL实现版)

    代码 package com zjc flow analysis hotitems analysis import org apache flink api common serialization SimpleStringSchema i
  • 智能合约调试指南

    不像你在其他地方看到的纸质合约 以太坊的智能合约是代码组成的 需要你以非常谨慎的态度去对待它 这是一件好事 想象下如果现实世界的合同需要编译的话会更清晰么 如果我们的合同没有被正确的编码出来 我们的交易可能会失败 导致以太币的损失 以 ga
  • 真题详解(Flynn分类)-软件设计(四十六)

    真题详解 计算机总线 软件设计 四十五 https blog csdn net ke1ying article details 130046829 Flynn分类将计算机分为四类 单指令流单数据流机器 SISD 早期的机器 在某个时钟周期
  • C++ 读取结束的判断

    cin 可以用来从键盘输入数据 将标准输入重定向为文件后 cin 也可以用来从文件中读入数据 在输入数据的多少不确定 且没有结束标志的情况下 该如何判断输入数据已经读完了呢 从文件中读取数据很好办 到达文件末尾就读取结束了 从控制台读取数据
  • shell脚本系列:6、shell扩展

    shell脚本系列 6 shell扩展 文章目录 shell脚本系列 6 shell扩展 1 花括号扩展 2 波浪号扩展 3 shell参数扩展 4 命令替换 5 算术扩展 6 进程替换 7 分词 8 文件名扩展 8 1 模式匹配 9 引号
  • 【upload-labs】————8、Pass-07

    闯关界面 前后端检测判断 查看源代码 文件后缀大小写 去除 DATA 关键词过滤 在这里可以发现所有的都考虑到了 但是却没有考虑后缀为 的情况 在windows中PHP会自动去除后缀名中最后的 我们可以通过这种方式来绕过 加 来绕过
  • 探索多线程使用同一个数据库connection的后果

    在项目中看到有用到数据库的连接池 心里就思考着为什么需要数据库连接池 只用一个连接会造成什么影响 只用一个connection 1 猜想 jdbc的事务是基于connection的 如果多线程共用一个connection 会造成多线程之间的
  • C++安装Dlib库教程(保姆级别)以及踩坑指南

    在网上搜索了一圈 发现大家好像都很喜欢使用Python来开发AI 后来我也用了一下Python 发现 emmm 真香 但是我知道一定也有人再使用C 进行开发 那么我就先来说说几种安装Dlib库的方法趴 除了使用vcpkg 我们这次从官网的角
  • 微信小程序自定义底部导航栏

    文章目录 概要 功能 源码 细节 改进 概要 微信小程序自定义底部导航栏 原生实现 不包含其他任何第三方组件 比较干净 开箱即用 效果预览 功能 可自定义底部导航栏列表样式 可自定义每个菜单的默认 激活后的图标和文字样式 可自定义是否添加中