微信小程序自定义tarbar(转)

本文介绍了一种自定义微信小程序底部TabBar的方法,并提供了完整的实现步骤与代码示例,包括如何设置图标、文字和页面路径等。

最近在写微信小程序 , 需要自定义一下底部tarbar   发现一篇很好的博文,特此搬运过来留作备用。(如果侵权会马上删除)

 

先看一看目录 
这里写图片描述 
template文件夹里存放tabbar模板。 
template/template.wxml

<template name="tabBar">
<view class="tabBar">
  <block wx:for="{{tabBar}}" wx:for-item="item" wx:key="tabBar">
    <view class="tabBar-item">
      <navigator open-type="redirect" url="{{item.pagePath}}">
        <view><image class="icon" src='{{item.iconPath}}'></image></view>
        <view class="{{item.current== 1 ? 'tabBartext' :''}}">{{item.text}}</view>
      </navigator>  
    </view>
  </block>
</view>
</template>

template.css

.icon{
  width:54rpx;
  height: 54rpx;
}
.tabBar{
  width:100%;
  position: fixed;
  bottom:0;
  padding:10rpx;
  margin-left:-4rpx;
  background:#F7F7FA;
  font-size:20rpx;
  color:#8A8A8A;
  box-shadow: 6rpx 6rpx 6rpx 6rpx #aaa;
}

 .tabBar-item{
  float:left;
  width:25%;
  text-align: center;
  overflow: hidden;
}
/*当前字体颜色*/
.tabBartext{
  color:red;
}

template.js


//初始化数据
function tabbarinit() {
 return [
      { "current":0,
        "pagePath": "/pages/index/index",
        "iconPath": "/imgs/home.png",
        "selectedIconPath": "/imgs/home_on.png",
        "text": "主页"
      },
      {
        "current": 0,
        "pagePath": "/pages/news/news",
        "iconPath": "/imgs/message.png",
        "selectedIconPath": "/imgs/message_on.png",
        "text": "资讯"

      },
      {
        "current": 0,
        "pagePath": "/pages/category/category",
        "iconPath": "/imgs/category.png",
        "selectedIconPath": "/imgs/category_on.png",
        "text": "分类"
      },
      {
        "current": 0,
        "pagePath": "/pages/buy/buy",
        "iconPath": "/imgs/buy.png",
        "selectedIconPath": "/imgs/buy_on.png",
        "text": "购物"
      }
    ]

}
//tabbar 主入口
function tabbarmain(bindName = "tabdata", id, target) {
  var that = target;
  var bindData = {};
  var otabbar = tabbarinit();
  otabbar[id]['iconPath'] = otabbar[id]['selectedIconPath']//换当前的icon
  otabbar[id]['current'] = 1;
  bindData[bindName] = otabbar
  that.setData({ bindData });
}

module.exports = {
  tabbar: tabbarmain
}

到此改组件完成,然后讲解一下使用方法。 
我们先把样式载入到app.wxss

@import "/template/template.wxss";
  • 在index文件夹 

index.wxml

<import src="../../template/template.wxml"/>
<template is="tabBar" data="{{tabBar:bindData.tabBar}}"/>

index.js


const app = getApp()
var template = require('../../template/template.js');
Page({
  data: {

  },
  onLoad: function () {
    template.tabbar("tabBar", 0, this)//0表示第一个tabbar
  },
})

news.wxml与index.wxml一样 
news.js如下

const app = getApp()
var template = require('../../template/template.js');
Page({
  data: {  },

  onLoad: function () {
    template.tabbar("tabBar", 1, this)//1表示第二个tabbar
  },

})

效果如图 
这里写图片描述

<think>我们正在处理用户关于微信小程序自定义tabbar中实现消息未读提示的问题。根据引用内容,用户已经了解如何自定义tabbar,现在需要增加消息未读提示功能。 思路: 1. 在自定义tabbar组件的data中定义一个变量(如unreadCount)来存储未读消息数量。 2. 在tabbar的wxml中,为需要显示未读消息的tab项添加一个显示未读数的元素(例如红点或数字)。 3. 通过setData方法动态更新未读数。 4. 考虑未读数的获取时机,可以在tabbar组件的生命周期中(如attached)或者通过全局事件监听来更新。 步骤: 步骤1:在自定义tabbar组件的js文件中定义未读消息数据 步骤2:在wxml中根据未读消息数量显示提示 步骤3:在页面中更新未读消息数量(通过调用tabbar组件的方法) 注意:由于自定义tabbar是一个自定义组件,我们需要在页面中获取到tabbar组件的实例,然后调用其方法来更新未读数。 根据引用[2]和[3],我们可以在页面中通过this.getTabBar()获取tabbar实例,然后调用setData更新。 具体实现: 1. 在自定义tabbar组件的data中增加未读消息数据,例如: data: { unreadCount: 0 // 可以是一个数字,也可以是一个数组,对应每个tab的未读数 } 2. 在tabbar的wxml中,为对应的tab项添加显示未读数的元素,例如: <view class="tab-bar-item" ...> ...其他内容... <!-- 未读消息提示 --> <view wx:if="{{unreadCount > 0}}" class="unread-badge">{{unreadCount}}</view> </view> 3. 在需要更新未读消息的地方(例如某个页面),获取tabbar实例并更新: const tabbar = this.getTabBar(); tabbar.setData({ unreadCount: 10 // 实际未读数 }); 但是,如果每个tab都需要独立的未读数,我们可以设计一个数组,例如unreadCounts,然后在data中初始化,在更新时更新对应索引的未读数。 例如,在tabbar组件的data中: data: { unreadCounts: [0, 0, 0, 0] // 根据tab数量初始化 } 在wxml中,遍历list时,根据当前索引index来显示对应的unreadCounts[index]。 更新时: const tabbar = this.getTabBar(); tabbar.setData({ [`unreadCounts[${index}]`]: count // 更新指定索引的未读数 }); 4. 样式:通过CSS设置未读提示的样式(红点、数字等)。 另外,未读消息的数据来源可能是从服务器获取,所以可以在页面onShow时请求未读消息数,然后更新tabbar。 注意:由于自定义tabbar是每个页面都引用的,所以更新操作可以在任意一个页面进行,但要注意不要重复更新。 引用[2]中提到了在页面的onShow方法中设置选中的tab,我们可以类似地在onShow中更新未读数。 示例代码: 在自定义tabbar组件的wxml中(以其中一个tab为例): <view class="tab-bar-item" ...> ...其他图标和文字... <view wx:if="{{unreadCounts[index] > 0}}" class="unread-badge"> {{unreadCounts[index] > 99 ? '99+' : unreadCounts[index]}} </view> </view> 在页面的js中(例如首页): Page({ onShow: function() { // 获取未读消息数,这里假设从全局数据或者接口获取 const unreadCount = ...; // 获取首页对应的未读数(或者每个tab的未读数) // 更新tabbar if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ // 假设首页在tabbar的索引是0 'unreadCounts[0]': unreadCount }); } } }); 但是,如果多个页面都需要更新未读数,可以在每个页面的onShow中都更新,但这样可能会造成多次请求。更好的做法是设计一个全局的未读状态管理,例如使用全局数据、事件监听或使用store。 另一种方案:在app.js中设置一个全局函数来更新tabbar的未读数,然后在各个页面需要的时候调用。 考虑到性能,我们可以将未读数的更新放在tabbar组件内部,通过监听全局数据的变化来更新。例如,使用getApp().globalData来存储未读数,然后在tabbar组件中使用watch或者observer来监听变化。 但是,小程序自定义组件中并没有提供监听全局数据变化的内置方法。因此,我们可以采用以下方法: 方法1:在tabbar组件的attached生命周期中,设置一个定时器轮询全局数据(不推荐,性能差)。 方法2:使用自定义事件(推荐),在app.js中定义一个事件监听,tabbar组件监听该事件,当其他页面需要更新未读数时触发事件。 这里我们采用方法2: 步骤: 1. 在app.js中创建一个事件监听器(EventEmitter),或者使用小程序的全局事件(如getApp().globalEvent)。 2. 在tabbar组件的attached中监听一个事件,比如'unreadCountChange'。 3. 当其他页面有未读数更新时,触发这个事件,并传递未读数数据。 由于小程序没有内置事件总线,我们可以自己实现一个简单的: 在app.js中: App({ globalData: { eventListeners: {} }, onLaunch: function() { // 可以初始化事件总线 }, // 注册事件 on: function(event, callback) { if (!this.globalData.eventListeners[event]) { this.globalData.eventListeners[event] = []; } this.globalData.eventListeners[event].push(callback); }, // 触发事件 emit: function(event, data) { const listeners = this.globalData.eventListeners[event]; if (listeners) { listeners.forEach(callback => { callback(data); }); } } }); 在tabbar组件的attached中: const app = getApp(); // 监听事件 app.on('unreadCountChange', (data) => { // data应该包含未读数的数组或者更新哪个tab的未读数 this.setData({ unreadCounts: data.unreadCounts // 或者根据索引更新部分 }); }); 在某个页面需要更新未读数时(例如收到推送或请求接口后): const app = getApp(); // 假设获取到未读数数组 const unreadCounts = [1, 0, 3, 0]; // 每个tab的未读数 app.emit('unreadCountChange', { unreadCounts }); 这样,tabbar组件就会更新。 考虑到性能,我们也可以只更新有变化的tab。 但是,为了简单,我们可以每次更新整个数组。 另外,我们还需要考虑在tabbar组件被卸载时移除事件监听(在detached中),但小程序自定义组件并没有提供直接移除事件的方法,我们可以扩展事件总线支持移除,或者使用一个标记来避免内存泄漏。由于tabbar是常驻的,所以可以不用移除。 总结步骤: 1. 在自定义tabbar组件的js文件中: - 在data中定义unreadCounts数组(初始化为0) - 在attached生命周期中,监听全局事件(如'unreadCountChange')来更新unreadCounts 2. 在app.js中实现事件总线(注册和触发事件的方法) 3. 在需要更新未读数的地方(如页面onShow,或接收到推送时)触发事件,传递新的未读数数组。 4. 在tabbar的wxml中,遍历list时,根据当前索引从unreadCounts中取出未读数,并显示。 5. 为未读提示设计样式(红点、位置等)。 样式示例(在tabbar组件的wxss中): .unread-badge { position: absolute; top: 0; right: 20rpx; min-width: 36rpx; height: 36rpx; border-radius: 18rpx; background-color: #ff0000; color: #ffffff; font-size: 24rpx; text-align: center; line-height: 36rpx; padding: 0 10rpx; box-sizing: border-box; } 注意:如果未读数为0,则不显示。 这样,我们就可以在自定义tabbar中实现消息未读提示功能了。 引用说明: 我们参考了引用[2]和[3]中关于自定义tabbar的实现方式,特别是通过页面中的getTabBar方法获取tabbar实例进行交互。同时,我们引入了事件总线的概念来解耦未读数更新,这是一种常见的设计模式。 根据用户需求,我们提供了详细的实现步骤,包括代码片段和样式设计。 相关问题: 1. 如何避免在多个页面重复请求未读消息数? 2. 自定义tabbar中如何实现类似原生tabbar的角标样式? 3. 微信小程序中还有哪些方式可以实现跨页面通信?</think>### 微信小程序自定义TabBar实现消息未读提示功能 在自定义TabBar中实现消息未读提示,需要结合数据绑定、样式控制和全局状态管理。以下是完整实现方案: #### 一、实现步骤 1. **修改自定义TabBar组件** ```javascript:custom-tab-bar/index.js Component({ data: { unreadCount: 0, // 全局未读数 list: [ { pagePath: "/pages/index/index", text: "首页", iconPath: "/images/home.png", unread: 0 // 单个tab未读数 }, { pagePath: "/pages/message/index", text: "消息", iconPath: "/images/msg.png", unread: 0 } ] }, methods: { // 更新未读数方法(供外部调用) updateUnread(counts) { this.setData({ 'list[1].unread': counts.message, // 更新消息tab未读数 unreadCount: counts.total // 全局未读数 }) } } }) ``` 2. **添加未读提示UI** ```html:custom-tab-bar/index.wxml <view class="tab-bar"> <view wx:for="{{list}}" wx:key="index" class="tab-bar-item" bindtap="switchTab" data-path="{{item.pagePath}}" > <!-- 图标容器 --> <view class="icon-wrapper"> <image src="{{selected === index ? item.selectedIconPath : item.iconPath}}"/> <!-- 未读红点 --> <view wx:if="{{item.unread > 0}}" class="unread-badge" > {{item.unread > 99 ? '99+' : item.unread}} </view> </view> <text>{{item.text}}</text> </view> </view> ``` 3. **添加样式** ```css:custom-tab-bar/index.wxss .unread-badge { position: absolute; top: -10rpx; right: -10rpx; min-width: 36rpx; height: 36rpx; border-radius: 50%; background: #ff4d4f; color: white; font-size: 20rpx; text-align: center; line-height: 36rpx; padding: 0 8rpx; box-sizing: border-box; } .icon-wrapper { position: relative; display: inline-block; } ``` 4. **在页面中更新未读数** ```javascript:pages/message/index.js Page({ onShow() { // 获取tabBar实例 const tabbar = this.getTabBar(); // 模拟获取未读数据 const unreadData = { message: 5, // 消息页未读 total: 8 // 全局未读总数 } // 更新tabbar状态 if (tabbar && tabbar.updateUnread) { tabbar.updateUnread(unreadData); } // 兼容低版本(可选) if (wx.canIUse('setTabBarBadge')) { wx.setTabBarBadge({ index: 1, text: unreadData.message.toString() }) } } }) ``` #### 二、关键实现原理 1. **数据驱动更新**:通过`setData`动态更新tabBar组件的未读计数数据 2. **组件通信**:使用`getTabBar()`获取组件实例后调用其更新方法 3. **视觉层级**: - 使用`position: absolute`定位红点到图标右上角 - 动态显示/隐藏:`wx:if="{{item.unread > 0}}"` - 超出显示:`{{item.unread > 99 ? '99+' : item.unread}}` 4. **多端兼容**: - 优先使用自定义组件实现 - 通过`wx.canIUse`检测并回退到原生API #### 三、优化建议 1. **性能优化**:使用`wx.setStorageSync`缓存未读数,避免频繁更新 2. **实时更新**:结合WebSocket实现消息实时推送更新 ```javascript // 建立WebSocket连接 wx.connectSocket({ url: 'wss://yourdomain.com' }) wx.onSocketMessage(res => { const tabbar = getApp().globalData.tabBarRef tabbar.updateUnread(JSON.parse(res.data)) }) ``` 3. **动画效果**:添加CSS动画增强提示效果 ```css @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } .unread-badge { animation: pulse 0.5s ease-in-out; } ``` #### 四、注意事项 1. **组件引用**:在`app.json`中启用自定义tabBar ```json:app.json { "tabBar": { "custom": true, "list": [...] // 保持与自定义组件一致 } } ``` 2. **版本兼容**:基础库需≥2.5.0才支持`getTabBar`方法 3. **全局访问**:可在App实例中缓存tabBar引用 ```javascript:app.js App({ globalData: { tabBarRef: null } }) // 在custom-tab-bar中 attached() { getApp().globalData.tabBarRef = this } ``` > 实现效果:当收到新消息时,tabBar会显示红色角标并更新计数,点击查看消息后角标自动消失。通过数据绑定机制,状态变化会自动同步到UI界面[^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值