推大数据平台echarts等图表动态数据展示(用websocket实现实时数据刷新),首屏的数据加载是用的post从后台请求。
"axios": "^0.19.0", //用来封装自己的请求类API
"countup.js": "^2.0.4", //数据大屏上的数字滚动
"echarts": "^4.5.0", // 可视化图表
"sweetalert2": "^9.10.0", // 一款弹框插件
"vue": "^2.6.10",
"vue-router": "^3.1.3",
"vuex": "^3.1.2" // 状态管理
我的整体模块如图:
数据定位推送问题:
如果按照大类->小类->小板块->板块123来定位推送指定的数据,则前端在数据定位的过程中比较繁重(至少3级或更多的层级判断,且不考虑需求、页面布局改变造成的影响)
我的思路:
比较暴力,我与后端的方案是约定好每一个需要实时刷新的小模块(蓝色框[可结合你自己的业务划分来再细分])以及它的唯一id。举个例子,D模块的两个小板块,type为1,2,数字为约定的唯一值,websocket推给我的数据type为1我就把数据更新到D模块1去。
整体思路:
需要登录获取服务端的token,然后在socket请求时后缀带上?token="****"
,监听socket的onmessage事件,成功返回数据后用vuex的action来提交具体mutation,实现数据的更新,然后每个模块只需要监听自己模块的getter,在触发你需要的操作(这里还待优化,看如何直接触发页面更新,因为echarts全都封装了一遍init,setOption,clear等)
// liveData.js
export default {
state: {
data1: {
}, //每一个 data* 属性对应着页面的一个数据块,
data2: {
},
},
getters: {
getData1: state => state.data1,
getData2: state => state.data2,
},
mutations: {
setData1(state, data) {
state.data1 = data;
},
setData2(state, data) {
state.data2 = data;
},
},
actions: {
},
};
// index.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './module/user';
import liveData from './module/liveData';
import center from './module/center';
import statistic from './module/statistic';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
//
},
mutations: {
//
},
actions: {
// 根据type commit不同mutation ,这里是重点,从websocket派发到vuex对应模块的对应state属性中
patchData({
commit }, data) {
commit(`setData${
data.type}`, data);
},
},
modules: {
user,
liveData,
center,
statistic,
},
});
最后将store封装完在main.js里引入使用,到这基本上就差不多了。
首屏的数据加载封装在每个组件里的,这里是websocket的连接和状态处理(未做心跳包,未用二进制数据流),
created() {
this.handleSubmit(); //开局先模拟登录
},
beforeDestroy() {
// 服务器端将断开连接
this.webSocketObj.close();
console.log('断开ws');
},
methods: {
...mapActions(['handleLogin', 'patchData']),
handleData(data) {
const da = JSON.parse(data);
if (da.type) {
if (da.type !== 0) {
this.patchData(da);
} else {
// 服务器端将断开连接
this.webSocketObj.close();
}
}
},
handleSubmit() {
console.log('模拟登录!');
const _self = this;
this.handleLogin({
userName: 'admin', pwd: '123456' })
.then((res) => {
if (res.data.success) {
if ('WebSocket' in window) {
_self.webSocketObj = _self.MyApi.MySocket(); // 这是我封装的socket方法
console.log('[readyState]:', _self.webSocketObj.readyState); // 0
_self.webSocketObj.onopen = () => {
// Web Socket 已连接上,使用 send() 方法发送数据
_self.webSocketObj.send('{data:"连接中"}');
console.log('数据发送中...', _self.webSocketObj.readyState);
};
_self.webSocketObj.onmessage = (evt) => {
const received_msg = evt.data;
console.log('数据已接收数据', _self.webSocketObj.readyState);
_self.handleData(received_msg);
};
_self.webSocketObj.onclose = () => {
// 关闭 websocket
console.log('连接已关闭...');
};
_self.webSocketObj.onerror = () => {
console.log('connect error, [readyState]:', _self.webSocketObj.readyState); // 3
};
} else {
// 浏览器不支持 WebSocket
alert('您的浏览器不支持 WebSocket,请换用谷歌浏览器');
}
}
}).catch((e) => {
console.log(e);
});
},
patchData({
commit }, data) {
//根据type commit不同mutation ,这里是重点,从websocket派发到vuex对应模块的对应state属性中
commit(`setData${
data.type}`, data);
},
监听到数据更新后触发页面数字的更新函数(数字滚动我用的countUp)
over,如果对你有一定启发,点个赞就nice了