记录一下小程序自定义导航栏消息未读已读小红点,以及分组件的消息数量数据实时读取

文章讲述了在Vue项目中,由于Message组件不能使用生命周期方法获取props,作者通过发送全局事件的方式,在父组件onShow时触发子组件刷新消息列表,以实现实时更新。同时提到Tabbar组件的实现和数据传输的考虑。
摘要由CSDN通过智能技术生成

本案例,Message 身为组件,使用不了任何钩子来重新获取 this.getMessageList() 消息列表
使用 props 父子传参,因为 Message 组件使用不了页面生命周期从而无法拿到传递过来的数据
使用 watch 监听不到 props
更不建议使用本地存储,那样和 props 结果差不多

案例中采用的是发送全局事件的形式,在父组件onShow后,因为子组件是父组件的一部分,所以在消息详情中返回子组件后,其实就是在父组件的onShow中调用了 refreshMessageList 方法重新获取子组件 Message 的消息列表
从而实现了实时获取

若不做自定义 tabbar 的话, 没有这么麻烦的去试探数据传输

父组件 Tabbar

<template>
	<uni-transition mode-class="fade" :duration="200" :show="true">
		<view class="main_box">
			<index v-if="currentIndex === 0"></index>
			<myDoctor v-if="currentIndex === 1"></myDoctor>
			<message v-if="currentIndex === 2"></message>
			<prescript v-if="currentIndex === 3"></prescript>
			<my v-if="currentIndex === 4"></my>
		</view>
		<view class="foot_box">
			<!-- 其实一开始是想把这个作为一个组件来使用的,不过数据传输特麻烦,这时候硬要使用组件化完全不太明智,如果是网页端Vue数据传输绝对简单... -->
			<!-- <custom-tab-bar ref='tabbar' :currentIndex="currentIndex" @update:currentIndex="updateCurrentIndex">
			</custom-tab-bar> -->
			<uni-transition mode-class="fade" :duration="200" :show="true">
				<view>
					<view class="tab-content">
						<slot />
					</view>
					<view class="tabbar">
						<view class="navigator">
							<view ref='warpper' class="warpper">
								<view ref="navItem" class="navigator-item" v-for="(item,index) in tabBar.list"
									:key="item.pagePath" @click="switchTab(item,index)" :data-index='index'>
									<img :src="item.iconPath" class="icon" v-if="selectedIndex !== index">
									<img :src="item.selectedIconPath" :class="[item.selectIconStyle ? 'icon-select' : 'icon']" v-else>
									<text :class="['item-text',{'text-active':selectedIndex === index}]">{{item.text}}</text>
									<!-- 未读状态 -->
									<view v-if="item.hasUnreadMessage && presentReadState" class="unread-dot">
										{{presentReadState < 99 ? presentReadState : ''}}
									</view>
								</view>
							</view>
						</view>
					</view>
				</view>
			</uni-transition>
		</view>
	</uni-transition>
</template>

<script>
	import {
		FILE_URL
	} from '../../api/base_api.js';
	import {
		GET_MESSAGE
	} from '../../api/user.js';
	var Hub = require('../../utils/signalR.js')
	import index from '@/pages/index/index.vue'
	import myDoctor from '@/pages/my-doctor/my-doctor.vue'
	import message from '@/pages/message/message.vue'
	import prescript from '@/pages/prescript/prescript.vue'
	import my from '@/pages/person/person.vue'
	export default {
		components: {
			index,
			my,
			message,
			prescript,
			myDoctor
		},

		data() {
			return {
				// 定义一个目前的 unRead 状态,若是集合起来大于 0,那么就作为标记 unRead 数量
				presentReadState: 0,
				messageList: [],
				pageIndex: 1,
				pageSize: 10,
				currentIndex: uni.getStorageSync('selectedIndex') || 0,
				selectedIndex: uni.getStorageSync('selectedIndex') || 0, // 标记
				tabBar: {
					list: [{
							pagePath: "pages/index/index",
							text: "首页",
							iconPath: "../../static/images/tabbar/home.png",
							selectedIconPath: "../../static/images/tabbar/home1.png"
						},
						{
							pagePath: "pages/my-doctor/my-doctor",
							text: "我的医生",
							iconPath: "../../static/images/tabbar/doctor.png",
							selectedIconPath: "../../static/images/tabbar/doctor1.png"
						},
						{
							pagePath: "pages/message/message",
							text: "消息",
							iconPath: "../../static/images/tabbar/message.png",
							selectedIconPath: "../../static/images/tabbar/message1.png",
							hasUnreadMessage: uni.getStorageSync("inline-msg") // 记录 未读 | 已读
						},
						{
							pagePath: "pages/prescript/prescript",
							text: "药膳商城",
							iconPath: "../../static/images/tabbar/mingyao2.png",
							selectedIconPath: "../../static/images/tabbar/mingyao3.png",
							selectIconStyle: true
						},
						{
							pagePath: "pages/person/person",
							text: "我的",
							iconPath: "../../static/images/tabbar/my2=.png",
							selectedIconPath: "../../static/images/tabbar/my1.png"
						}
					]
				},
			}
		},

		methods: {
			loadsocket() {
				var _this = this;
				if (_this.timeout)
					clearTimeout(_this.timeout);
				_this.hubConnect = new Hub.HubConnection();
				_this.hubConnect.token = uni.getStorageSync('WX_TOKEN')
				_this.hubConnect.start(FILE_URL + "/api/chathub");
				_this.hubConnect.onOpen = res => {}

				_this.hubConnect.on("Receive", function(res) {
					console.log("有数据了", res);
					uni.setStorageSync("inline-msg", true)
				})

				_this.hubConnect.on("UsingCode", res => {})
				_this.hubConnect.on("UsedCode", res => {})
			},

			switchTab(item, index) {
				this.currentIndex = index;
				this.tabBar.list.forEach((v, i) => {
					if (item.pagePath === v.pagePath) {
						uni.setStorageSync('selectedIndex', index);
					}
				})
				this.selectedIndex = uni.getStorageSync('selectedIndex')
			},
			// 因为 message 为组件  onShow 不可使用,所以这里想使用父子传参的方式解决消息页的未读消息处理
			// 此处更改为记录未读数量
			getMessageList() {
				GET_MESSAGE({
					page: this.pageIndex,
					limit: this.pageSize
				}).then(res => {
					if (res.data) {
						this.messageList = res.data
						let readNumberList = this.messageList.map(item => item.unRead)
						this.presentReadState = readNumberList.reduce((accumulator, currentValue) =>
							accumulator + currentValue, 0);
						if (this.presentReadState > 0) { // 若是消息数量大于0的话,初始化一下inline-msg状态
							uni.setStorageSync("inline-msg", true)
						}
					}
				})
			},
		},

		onShow() {
			this.loadsocket()
			this.getMessageList()
			// 父子传参方法也不好用,message组件中没有onShow方法,而且watch监听不到props
			// message为组件,其他方法不太好用,使用事件总线发送全局事件 refreshMessageList
			uni.$emit('refreshMessageList');
			this.tabBar.list[2].hasUnreadMessage = uni.getStorageSync("inline-msg")
		},

		mounted() {
			this.tabBar.list[2].hasUnreadMessage = uni.getStorageSync("inline-msg")
		},
	}
</script>

其中一个子组件 Message

<template>
	<view class="message">
		<!-- 页面头 -->
		<view class="header">
			<image src="../../static/images/index/index-topbar-back.png" mode="" class="back-img"></image>
			<view class="top-bar">
				<view class="name">消息</view>
			</view>
		</view>
		<!-- 没有消息 -->
		<view class="none" style="padding-top: 200rpx;" v-if="!messageList.length">
			<u-empty mode='list' text='暂无消息'></u-empty>
		</view>
		<!-- 消息列表 -->
		<view class="list" v-else>
			<view class="item" v-for="(item,index) in messageList" :key="index" @click="handleToChat(item)">
				<view class="avatar">
					<image :src="item.groupImage" mode=""></image>
				</view>
				<view class="msg-info">
					<view class="left">
						<view class="name">{{item.groupName}}</view>
						<view class="msg">{{item.lastMessage}}</view>
					</view>
					<view class="right">
						<view class="date">{{item.changeTime.slice(5,16)}}</view>
						<view class="no-read-count" v-if="item.unRead">{{item.unRead}}</view>
					</view>
				</view>
			</view>
		</view>
		<!-- <custom-tab-bar ref='tabbar'></custom-tab-bar> -->
		<!-- 登录弹窗 -->
		<!-- <u-popup v-model="isShowLogin" mode="center" border-radius="14" :closeable='true'>
			<AuthLogin @setData='getLoginData'></AuthLogin>
		</u-popup> -->
	</view>
</template>

<script>
	import {
		APP_BASE_URL,
		FILE_URL
	} from '../../api/base_api.js';
	import {
		GET_MESSAGE
	} from '../../api/user.js';
	// import AuthLogin from '../common/auth-login.vue'
	var Hub = require('../../utils/signalR.js')
	export default {
		data() {
			return {
				messageList: [],
				pageIndex: 1,
				pageSize: 10,
				// isShowLogin: false, //登录弹窗
			}
		},

		watch: {
			presentReadState(newValue, oldValue) {

			}
		},

		components: {
			// AuthLogin
		},

		onHide() {
			console.log('断开')
			this.hubConnect.close();
		},

		mounted() {
			if (uni.getStorageSync('WX_TOKEN')) {
				this.messageList = []
				this.getMessageList()
				// 当回到 message 组件中(其实就是在父组件的onShow中),调用全局事件refreshMessageList,来重置消息列表
				uni.$on('refreshMessageList', this.getMessageList);
			}
			if (this.hubConnect) {
				if (this.hubConnect.connection == null || !this.hubConnect.openStatus) {
					this.loadsocket();
				}
			} else {
				this.loadsocket();
			}
		},

		beforeDestroy() {
			// 销毁
			uni.$off('refreshMessageList', this.getMessageList);
		},

		methods: {
			// 获取弹窗传值
			// getLoginData(status) {
			// 	this.isShowLogin = status
			// },
			// 获取消息列表
			getMessageList() {
				GET_MESSAGE({
					page: this.pageIndex,
					limit: this.pageSize
				}).then(res => {
					if (res.data) {
						this.messageList = res.data
					}
				})
			},
			// 获取
			getcode() {
				if (this.hubConnect && this.hubConnect.connection != null && this.hubConnect.openStatus) {
					this.hubConnect.send("GetCode", 3);
					this.xunhuan();
				}
			},
			// 链接
			loadsocket() {
				var _this = this;
				if (_this.timeout)
					clearTimeout(_this.timeout);
				// connection
				_this.hubConnect = new Hub.HubConnection();
				_this.hubConnect.token = uni.getStorageSync('WX_TOKEN')
				_this.hubConnect.start(FILE_URL + "/api/chathub");
				_this.hubConnect.onOpen = res => {

				}
				_this.hubConnect.on("Receive", res => {
					uni.setStorageSync("inline-msg", true)
					_this.messageList = []
					_this.getMessageList()
				})
				_this.hubConnect.on("UsingCode", res => {
					_this.show = true;
				})
				_this.hubConnect.on("UsedCode", res => {

				})
			},
			// 跳转聊天
			handleToChat(item) {
				if (!uni.getStorageSync('WX_TOKEN')) {
					// this.isShowLogin = true
					return false
				}
				uni.navigateTo({
					url: '/pages/tools/chat/sys-message?item=' + JSON.stringify(item)
				})
			}
		},
	}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星光菌子Official

你真是个富哥

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值