微信小程序自定义tabBar

news/2024/11/15 3:35:29/

1.app.json中tabBar里设置 "custom":true

设置好后就可使用自定义tabBar。

注意:list中的页面必须保存,且必须和自定义的tabBar页面数据一致

"tabBar": {"custom": true,"list": [{"pagePath": "pages/home/home","text": "首页","iconPath": "/images/tabs/home.png","selectedIconPath": "/images/tabs/home-active.png"},{"pagePath": "pages/message/message","text": "消息","iconPath": "/images/tabs/message.png","selectedIconPath": "/images/tabs/message-active.png"},{"pagePath": "pages/contact/contact","text": "联系我们","iconPath": "/images/tabs/contact.png","selectedIconPath": "/images/tabs/contact-active.png"}]},

2.创建tabBar代码文件

在根目录下创建custom-tab-bar文件夹,并创建名为index的component组件。

注意以下三点,否则自定义tabBar不会生效:

  • 必须是根目录下
  • 且文件夹必须名为custom-tab-bar
  • 文件夹下的component组件名必须为index

3.npm下载vant weapp包,并在app.json中引入以下组件

  "usingComponents": {"van-button": "@vant/weapp/button/index","van-tabbar": "@vant/weapp/tabbar/index","van-tabbar-item": "@vant/weapp/tabbar-item/index"}

 4.自定义tabBar文件 index.wxml文件中,使用<van-tabBar>生成tabBar结构

image 标签中,slot中icon代表非选中图标,icon-active代表选中图标

<van-tabbar active="{{ active }}" bind:change="onChange"
active-color="#07c160"><van-tabbar-item info="{{item.info>0?item.info:''}}" wx:for="{{list}}" wx:key="name"><imageslot="icon"src="{{ item.icon.normal }}"mode="aspectFit"style="width: 30px; height: 18px;"/><imageslot="icon-active"src="{{ item.icon.active }}"mode="aspectFit"style="width: 30px; height: 18px;"/>{{item.name}}</van-tabbar-item>
</van-tabbar>

5.在index.ts中,创建tabBar页面数据

info表示徽标;pagePath表示tab对象页面路径;icon表示选中和非选中图标存放路径

data: {// active: 0,// list的pagePath: "/pages/home/home"必须再app.json中有对应数据list:[{info:3,name:"首页",pagePath: "/pages/home/home",icon: {normal: '/images/tabs/home.png',active: '/images/tabs/home-active.png',},},{name:"消息",pagePath: "/pages/message/message",icon: {normal: 'https://img.yzcdn.cn/vant/user-inactive.png',active: 'https://img.yzcdn.cn/vant/user-active.png',},},{name:"联系我们",pagePath: "/pages/contact/contact",icon: {normal: 'https://img.yzcdn.cn/vant/user-inactive.png',active: 'https://img.yzcdn.cn/vant/user-active.png',},}],},

6.渲染徽标

通过info属性控制徽标显示,为 '' 时自动不显示,info="{{item.info>0?item.info:''}}"表示按需加载,此处具体情况需要具体分析

<van-tabbar-item info="{{item.info>0?item.info:''}}" wx:for="{{list}}" wx:key="name">

7.如果徽标显示溢出tabBar容器

在index.scss中设置以下: 将margin-bottom设置为0

.van-tabbar-item{// scss中变量使用$开头$tabbar-item-margin-bottom: 0
}

注意:index.ts中需要设置以下才会生效

  options:{"styleIsolation":"shared"},

 

8.使用mobx 将徽标的值设置为 动态可变

测试案例:将numA,numB,sum放在store中,numA或者numB改变时,sum计算属性对应改变,然后将sum值和info做同步。

store.ts:

import { observable, action} from 'mobx-miniprogram'export const store = observable({numA: 1,numB: 2,active: 0,get sum(){return this.numA + this.numB;},updateActive:action(function(this: any, active:number){this.active = active;}),updateNumA: action(function(this: any, step:number){this.numA += step;}),updateNumB: action(function(this: any, step:number){this.numB += step;})});

home页面展示对应值和两个改变值按钮,改变后,同步index中的徽标属性info

home.wxml:

<view>
<view>{{numA}} + {{numB}}  = {{sum}}
</view><van-button type="primary" bindtap="handleNumA" data-step="1"> numA + 1 </van-button><van-button type="info" bindtap="handleNumA" data-step="-1"> numA - 1 </van-button>
</view>
// pages/home/home.ts
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'Page({/*** 页面的初始数据*/data: {},handleNumA(this:any, e: any){this.updateNumA(e.target.dataset.step-0);},/*** 生命周期函数--监听页面加载*/onLoad(this: any) {this.storeBindings = createStoreBindings(this,{store,fields:['numA','numB','sum'],actions:['updateNumA']});},/*** 生命周期函数--监听页面卸载*/onUnload(this: any) {this.storeBindings.destroyStoreBindings();},})

 然后再index.ts中监听sum变化,并同步info值

observers:{'sum':function(val){this.setData({ 'list[0].info': val });}},

9.实现tabBar页面可切换

<van-tabBar>标签中设置onChange事件通过e.detail回去当前tabBar索引,并调用wx.switchTab()切换到对应页面

<van-tabbar active="{{ active }}" bind:change="onChange"
active-color="#07c160">
  methods: {onChange(this:any,e: any){// 切换tab页面// 将active保存到store中,否则点中项会错乱// this.setData({ active: e.detail });this.updateActive(e.detail);wx.switchTab( {url: this.data.list[e.detail].pagePath} );}}
})

 11.选中项索引active直接赋值e.detail会混乱,将索引存到store中

store.ts:

export const store = observable({
...active: 0,...updateActive:action(function(this: any, active:number){this.active = active;}),
})

index.ts中再调用updateActive()方法改变active的值 

  methods: {onChange(this:any,e: any){// 将active保存到store中,否则点中项会错乱// this.setData({ active: e.detail });this.updateActive(e.detail);wx.switchTab( {url: this.data.list[e.detail].pagePath} );}}
})

12.改变选中项文字颜色

 <van-tabbar>中设置active-color="#07c160"为想要的颜色即可

13.注意:app.json中list中的页面及路径等必须和自定义tabBar自定义组件中的数据相同

data: {// active: 0,// list的pagePath: "/pages/home/home"必须再app.json中有对应数据list:[{info:3,name:"首页",pagePath: "/pages/home/home",icon: {normal: '/images/tabs/home.png',active: '/images/tabs/home-active.png',},},{name:"消息",pagePath: "/pages/message/message",icon: {normal: 'https://img.yzcdn.cn/vant/user-inactive.png',active: 'https://img.yzcdn.cn/vant/user-active.png',},},{name:"联系我们",pagePath: "/pages/contact/contact",icon: {normal: 'https://img.yzcdn.cn/vant/user-inactive.png',active: 'https://img.yzcdn.cn/vant/user-active.png',},}],},

14.完整代码

代码结构:

 

app.json

{"pages": ["pages/home/home","pages/message/message","pages/contact/contact"],"subpackages": [{"root": "packageA","pages": ["pages/basic/basic","pages/logs/logs"]},{"root": "packageB","pages": ["pages/test1/test1","pages/test2/test2"],"independent": true}
],
"preloadRule": {"packageA/pages/basic/basic":{"network": "wifi","packages": ["packageA"]}
},"tabBar": {"custom": true,"list": [{"pagePath": "pages/home/home","text": "首页","iconPath": "/images/tabs/home.png","selectedIconPath": "/images/tabs/home-active.png"},{"pagePath": "pages/message/message","text": "消息","iconPath": "/images/tabs/message.png","selectedIconPath": "/images/tabs/message-active.png"},{"pagePath": "pages/contact/contact","text": "联系我们","iconPath": "/images/tabs/contact.png","selectedIconPath": "/images/tabs/contact-active.png"}]},"window": {"backgroundTextStyle": "light","navigationBarBackgroundColor": "#fff","navigationBarTitleText": "Weixin","navigationBarTextStyle": "black"},"sitemapLocation": "sitemap.json","usingComponents": {"van-button": "@vant/weapp/button/index","store-test": "/components/store-test/store-test","van-tabbar": "@vant/weapp/tabbar/index","van-tabbar-item": "@vant/weapp/tabbar-item/index"}
}

store.ts:

import { observable, action} from 'mobx-miniprogram'export const store = observable({numA: 1,numB: 2,active: 0,get sum(){return this.numA + this.numB;},updateActive:action(function(this: any, active:number){this.active = active;}),updateNumA: action(function(this: any, step:number){this.numA += step;}),updateNumB: action(function(this: any, step:number){this.numB += step;})});

home.wxml:

<!--pages/home/home.wxml-->
<text>pages/home/home.wxml</text>
<view>
<view>{{numA}} + {{numB}}  = {{sum}}
</view><van-button type="primary" bindtap="handleNumA" data-step="1"> numA + 1 </van-button><van-button type="info" bindtap="handleNumA" data-step="-1"> numA - 1 </van-button>
</view>

home.ts:

// pages/home/home.ts
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'Page({/*** 页面的初始数据*/data: {},handleNumA(this:any, e: any){this.updateNumA(e.target.dataset.step-0);},/*** 生命周期函数--监听页面加载*/onLoad(this: any) {this.storeBindings = createStoreBindings(this,{store,fields:['numA','numB','sum'],actions:['updateNumA']});},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload(this: any) {this.storeBindings.destroyStoreBindings();},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
})

index.wxml:

<van-tabbar active="{{ active }}" bind:change="onChange"
active-color="#07c160"><van-tabbar-item info="{{item.info>0?item.info:''}}" wx:for="{{list}}" wx:key="name"><imageslot="icon"src="{{ item.icon.normal }}"mode="aspectFit"style="width: 30px; height: 18px;"/><imageslot="icon-active"src="{{ item.icon.active }}"mode="aspectFit"style="width: 30px; height: 18px;"/>{{item.name}}</van-tabbar-item>
</van-tabbar>

index.ts:

import { ComponentWithStore } from 'mobx-miniprogram-bindings'
import { store } from '../store/store'ComponentWithStore({options:{"styleIsolation":"shared"},observers:{'sum':function(val){this.setData({ 'list[0].info': val });}},storeBindings:{store,// 只需要监听sum所以只引入sumfields:['sum','active'],actions:['updateActive']},/*** 组件的属性列表*/properties: {},/*** 组件的初始数据*/data: {// active: 0,// list的pagePath: "/pages/home/home"必须再app.json中有对应数据list:[{info:3,name:"首页",pagePath: "/pages/home/home",icon: {normal: '/images/tabs/home.png',active: '/images/tabs/home-active.png',},},{name:"消息",pagePath: "/pages/message/message",icon: {normal: 'https://img.yzcdn.cn/vant/user-inactive.png',active: 'https://img.yzcdn.cn/vant/user-active.png',},},{name:"联系我们",pagePath: "/pages/contact/contact",icon: {normal: 'https://img.yzcdn.cn/vant/user-inactive.png',active: 'https://img.yzcdn.cn/vant/user-active.png',},}],},/*** 组件的方法列表*/methods: {onChange(this:any,e: any){// 切换tab页面// 将active保存到store中,否则点中项会错乱// this.setData({ active: e.detail });this.updateActive(e.detail);wx.switchTab( {url: this.data.list[e.detail].pagePath} );}}
})

index.scss:

/* custom-tab-bar/index.wxss */
.van-tabbar-item{// scss中变量使用$开头$tabbar-item-margin-bottom: 0
}

15.效果实现 

 


http://www.ppmy.cn/news/76335.html

相关文章

无距离障碍:远程桌面Ubuntu实现全球办公

目录 前言 视频教程 1. ubuntu安装XRDP 2.局域网测试连接 3. Ubuntu安装cpolar内网穿透 4.cpolar公网地址测试访问 5.固定域名公网地址 [TOC] 转载自远程穿透文章&#xff1a;Windows通过RDP异地远程桌面Ubuntu【内网穿透】 前言 XRDP是一种开源工具&#xff0c;它允许…

leetcode 数据库题 196,197,262,511,550,570

leetcode 数据库题第二弹 196. 删除重复的电子邮箱197. 上升的温度262. 行程和用户511. 游戏玩法分析 I550. 游戏玩法分析 IV570. 至少有5名直接下属的经理577. 员工奖金小结 196. 删除重复的电子邮箱 题目地址&#xff1a;https://leetcode.cn/problems/delete-duplicate-emai…

基于大模型GPT,如何提炼出优质的Prompt

基于大模型实现优质Prompt开发 1. 引言1.1 大规模预训练模型 2. Prompt开发2.1 Prompt基本定义&#xff1a;2.2 为什么优质Prompt才能生成优质的内容2.3 如何定义优质的Prompt 3. Prompt优化技巧3.1 迭代法3.1.1 创作评估3.1.2 基础创作3.1.3 多轮次交互 3.2 Trick法3.2.1 戴高…

实战演练 | Navicat 数据生成功能

数据生成的目的是依据某个数据模型&#xff0c;从原始数据通过计算得到目标系统所需要的符合该模型的数据。数据生成与数据模型是分不开的&#xff0c;数据生成的结果应该符合某个数据模型对于数据的具体要求。所以&#xff0c;随着数据模型的发展&#xff0c;数据生成的方法相…

java设计模式之适配器设计模式的前世今生

适配器设计模式是什么&#xff1f; 适配器设计模式是一种结构型设计模式&#xff0c;它允许将不兼容的类的接口转换为可相互之间进行协同工作的适配器。 适配器设计模式的主要作用是实现两个不兼容接口之间的数据转换&#xff0c;使得客户端可以独立于被适配者的接口&#x…

Win 10配置VPN代理时遇到的问题:500 Internal Privoxy Error

在启动某VPN客户端后&#xff0c;打开chrome浏览器时&#xff0c;页面提示以下错误&#xff1a; 500 Internal Privoxy Error Privoxy encountered an error while processing your request: Could not load template file no-server-data or one of its included components.…

@Retention @Target 自定义注解

Target注解常用参数含义&#xff1a; ElementType.TYPE&#xff1a;可以用于类、接口和枚举类型。 ElementType.FIELD&#xff1a;可以用于字段。 ElementType.METHOD&#xff1a;可以用于方法。 ElementType.PARAMETER&#xff1a;可以用于方法的参数。 ElementType.CONST…

推荐一个AI导航网站 - 收录的都是热门AI工具

AI导航 | AI工具 | AI之旅导航是只收录最新最实用AI工具的人工智能导航网站 最近半年使用了大量的AI人工智能工具&#xff0c;收藏夹已经收藏不过来了。 所以搭建这个导航网站&#xff0c;管理所有收藏的热门AI网站&#xff0c;同时像大家分享&#xff0c; 网站没有任何广告…