记录一下小程序自定义导航栏消息未读已读小红点,以及分组件的消息数量数据实时读取
本案例,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" class="unread-dot"></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';
import {
store
} from '../../store/modules/index.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')
},
},
onShow() {
this.tabBar.list[2].hasUnreadMessage = uni.getStorageSync("inline-msg")
// 父子传参方法也不好用,message组件中没有onShow方法,而且watch监听不到props
// message为组件,其他方法不太好用,使用事件总线发送全局事件 refreshMessageList
uni.$emit('refreshMessageList');
},
mounted() {
this.loadsocket()
},
}
</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>