一、功能需求
1.這是我在后臺(tái)管理項(xiàng)目中使用到的,主要的作用是搞一個(gè)消息提醒的功能。
2.主要有右上角的提示和有下角的消息彈框。
3.主要實(shí)現(xiàn)的功能是如果用戶有未讀的消息,那么首次登錄就彈框,如果用戶關(guān)閉了頁面,那么再次刷新頁面的時(shí)候,也不再彈框,意思就是一個(gè)賬戶沒有退出之前,也沒有實(shí)時(shí)消息推送的時(shí)候,只彈一次框。
4.如果用戶點(diǎn)擊了未讀消息,那么就會(huì)將此條消息置位歷史(已讀)。
頁面展示:文章來源:http://www.zghlxwxcb.cn/news/detail-677104.html
二、頁面代碼
備注:我的是后臺(tái)管理系統(tǒng)(用的是vue-element-admin),第一次寫websocket,所以我寫在了src->layout->AppMain.vue文件下面:文章來源地址http://www.zghlxwxcb.cn/news/detail-677104.html
<template>
<section class="app-main">
<Message-remind :message-list="messageList" />
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<router-view :key="key" />
</keep-alive>
</transition>
</section>
</template>
<script>
import MessageRemind from '@/components/MessageRemind/index.vue'
import { getToken, getSid } from "@/utils/auth"; // get token from cookie
export default {
name: 'AppMain',
components: {
MessageRemind
},
watch: {
'$store.state.user': {
handler: function (newValue, oldValue) {
// 如果沒有token,則表明退出了登錄
if (!newValue.token) {
this.closeWebSocket();
}
},
immediate: true,
deep: true
}
},
data() {
return {
// socket參數(shù)
socket: null,
timeout: 60 * 1000, // 45秒一次心跳
timeoutObj: null, // 心跳心跳倒計(jì)時(shí)
serverTimeoutObj: null, // 心跳倒計(jì)時(shí)
timeoutnum: null, // 斷開 重連倒計(jì)時(shí)
lockReconnect: false, // 防止
websocket: null,
messageList: {}
};
},
created() {
const hasToken = getToken();
const sid = getSid();
if (hasToken) {
this.initWebSocket(hasToken, sid)
}
},
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews
},
key() {
return this.$route.path
}
},
mounted() {
// console.log(this.$store.state.tagsView.cachedViews)
},
methods: {
initWebSocket(token, sid) {
// WebSocket與普通的請(qǐng)求所用協(xié)議有所不同,ws等同于http,wss等同于https
this.websocket = new WebSocket(process.env.VUE_APP_WEB_SOCKET_BASE_API + '?uiticket=' + token + '&sid=' + sid);
this.websocket.onopen = this.websocketonopen;
this.websocket.onerror = this.websocketonerror;
this.websocket.onmessage = this.setOnmessageMessage;
this.websocket.onclose = this.websocketclose;
// 監(jiān)聽窗口關(guān)閉事件,當(dāng)窗口關(guān)閉時(shí),主動(dòng)去關(guān)閉websocket連接,防止連接還沒斷開就關(guān)閉窗口,server端會(huì)拋異常。
// window.onbeforeunload = that.onbeforeunload
},
start() {
//清除延時(shí)器
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(() => {
if (this.websocket && this.websocket.readyState == 1) {
this.websocket.send('{"messageType": 99}');//發(fā)送消息,服務(wù)端返回信息,即表示連接良好,可以在socket的onmessage事件重置心跳機(jī)制函數(shù)
} else {
this.reconnect();
}
//定義一個(gè)延時(shí)器等待服務(wù)器響應(yīng),若超時(shí),則關(guān)閉連接,重新請(qǐng)求server建立socket連接
this.serverTimeoutObj = setTimeout(() => {
this.websocket.close();
}, this.timeout)
}, this.timeout)
},
reset() { // 重置心跳
// 清除時(shí)間
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
// 重啟心跳
this.start();
},
// 重新連接
reconnect() {
if (this.lockReconnect) return
this.lockReconnect = true;
//沒連接上會(huì)一直重連,設(shè)置延遲避免請(qǐng)求過多
this.timeoutnum && clearTimeout(this.timeoutnum);
this.timeoutnum = setTimeout(() => {
this.initWebSocket();
this.lockReconnect = false;
}, 5000)
},
async setOnmessageMessage(event) {
this.messageList = JSON.parse(event.data)
if (this.messageList.data.messageType === 999) {
this.websocket.send('{"messageType": 99}');
}
this.$store.dispatch('user/steMessageMenu', this.messageList)
this.reset();
// 自定義全局監(jiān)聽事件
window.dispatchEvent(new CustomEvent('onmessageWS', {
detail: {
data: event.data
}
}))
//發(fā)現(xiàn)消息進(jìn)入 開始處理前端觸發(fā)邏輯
// if (event.data === 'success' || event.data === 'heartBath') return
},
websocketonopen(e) {
// console.log('onopen', {e});
//開啟心跳
this.start();
console.log("WebSocket連接成功!!!" + new Date() + "----" + this.websocket.readyState);
},
websocketonerror(e) {
// console.log('websocketonerror', {e});
console.log("WebSocket連接發(fā)生錯(cuò)誤" + e);
},
websocketclose(e) {
this.websocket.close();
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
console.log("WebSocket連接關(guān)閉");
},
websocketsend(messsage) {
this.websocket.send(messsage)
},
closeWebSocket() { // 關(guān)閉websocket
this.websocket.close()
},
},
}
</script>
<style lang="scss" scoped>
@import "~@/styles/global-height.scss";
.app-main {
/* 50= navbar 50 */
// min-height: calc(100vh - #{$navbar+'px'});
width: 100%;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
flex: 1;
}
.fixed-header+.app-main {
padding-top: #{$navbar+'px'};
}
.hasTagsView {
.app-main {
// min-height: calc(100vh - #{$appMain+'px'});
}
.fixed-header+.app-main {
padding-top: 90px;
}
}
.copy {
text-align: center;
height: 30px;
line-height: 30px;
font-size: 13px;
color: #666;
background: #fff;
width: 100%;
box-shadow: 0 0 10px #dfe4ed;
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 15px;
}
}
</style>
到了這里,關(guān)于Vue 項(xiàng)目中使用WebSocket 消息推送的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!