实现思路:
先通过在APP.vue根组件中去全局创建websocket连接到服务器,通过服务器推送的那内容来区分在线或离线,拿到内容并判断出状态后,再通过provide和inject通信方式将状态值传送到需要显示在线或离线状态的页面组件中并显示即可。
效果图:
下图是个动态闪烁,截图看不出来效果
官方文档:provide / inject引用
提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
核心代码:
APP.vue根组件:
//APP.vue组件(根组件)
export default{
name: "App",
provide() {
return {
//这里需要以函数的方式返回,为了响应式的实现(默认是不可响应的,官方文档原话如上引用所示)
noticeMess: () => this.socketRecivesData,
};
},
data(){
socketRecivesData: 0, //接收的socket推送的信息内容,默认离线 0:离线 1:在线
wsUrl: "ws://xxx.xxx.xx.xx/xxx/xx",
ws: null,
},
created(){
this.initWebSocket();
},
methods: {
initWebSocket() {
this.ws = new WebSocket(this.wsUrl);
this.ws.onopen = this.websocketOnopen;
this.ws.onmessage = this.websocketOnmessage;
this.ws.onerror = this.websocketOnerror;
this.ws.onclose = this.websocketOnclose;
},
websocketOnopen() {
console.log("终端与本地服务连接成功");
},
websocketOnmessage(evd) {
//这里面代码可根据具体项目对接时的需求进行自定义书写
//这里只是我个人实际项目中用到的场景代码,可根据自己情况修改
let data = JSON.parse(evd.data);
if (data.msgType === 1) {
if (data.msg === "online") {
this.socketRecivesData = 1;
} else if (data.msg === "offline") {
this.socketRecivesData = 0;
}
}
},
websocketOnerror(e) {
console.log(e);
console.log("连接出现错误");
this.ws.close();
},
websocketOnclose() {
console.log("连接关闭");
this.initWebSocket(); //重新创建连接
},
},
}
需要展示的页面(子组件):
<template>
<div>
<span
class="pointCircle"
:class="onoffline === 0?'offlinePointCircle offlinePointCircleAnimate':'onlinePointCircle onlinePointCircleAnimate'"
></span>
<span
:class="onoffline === 0?'connectText offlineConnectText':'connectText onlineConnectText'"
>{{ onoffline === 0?'网络已断开':'网络已连接' }}</span>
</div>
</template>
export default{
inject: ["noticeMess"],
computed: {
onoffline() {
return this.noticeMess();
},
},
}
.offlinePointCircle {
background-color: #f42a1f;
}
.onlinePointCircle {
background-color: #36d236;
}
.pointCircle {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 4px;
position: relative;
}
.connectText {
padding-left: 6px;
font-size: 16px;
}
.offlineConnectText {
color: #f42a1f;
}
.onlineConnectText {
color: #36d236;
}
.offlinePointCircleAnimate::before {
background-color: rgba(250, 110, 110, 0.5);
}
.onlinePointCircleAnimate::before {
background-color: rgba(130, 250, 130, 0.5);
}
.offlinePointCircleAnimate::before,
.onlinePointCircleAnimate::before {
content: "";
width: 16px;
height: 16px;
border-radius: 8px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -8px;
margin-top: -8px;
animation: onoffframe 1.5s ease-out 0s infinite;
}
@keyframes onoffframe {
0% {
transform: scale(0.5);
opacity: 1;
}
30% {
opacity: 1;
}
100% {
transform: scale(1.5);
opacity: 0;
}
}