上两篇文章写完之后,实现了实时数据流的效果,但是最大的问题出现了,就是数据流太快,浏览器在接收了一千多条的数据之后就崩溃了,那只能优化了,前期查了很多资料以及解决方法,比如:分页处理,将数据推送进数组 进行切割分页,再渲染出来,这样是处理了大数据,但是不是我想要实现的数据流效果(如果想要用分页实现我的效果我的思路就是:设置两个盒子,布局是上下布局,一个盒子接收新数据,一个是旧数据,然后给盒子设置动画插入一条数据就向上 top移动相应的像素,个人觉得这样实现需要很强的逻辑处理能力,而且较麻烦),后面想了下,能不能用瀑布流的思路去解决呢? 然后就开始实现,结果真的就完美的解决了我的问题,这里我偷了个懒,用的是elementUi 的无限滚动去实现数据流的效果,
在这里插入图片描述
因为不知道怎么发动态效果,只能放张图片了,效果就是,这些预约消息会实时更新,向上移动。

<template>
	<div class="content-left">
				<div class="title">
					<p class="title-text">原始数据流</p>
					<i class="title-icon"></i>
				</div>
				<ul class="infinite-list content-left-data" v-infinite-scroll="load" style="overflow:auto">
					<li v-for="(i, index) in count" :key="index" id="content-left-data-text" class="content-left-data-text infinite-list-item">{{ i }}</li>
				</ul>
	</div>
</template>
<script>
	export default {
	data() {
		return {
			arr: [],//接收数据流的数组
			count: 0,//实现无限滚动的数组
			webSock: null,
			rawHtml: '<p class="data-text">{{msgData}}</p>',
			reconnectData: null,
			lockReconnect: false, //避免重复连接,因为onerror之后会立即触发 onclose
			timeout: 600000, //心跳时间参数  1小时一次心跳检测
			timeoutObj: null, //心跳检测函数执行后的参数 1代表执行成功
			serverTimeoutObj: null, //等待服务端响应函数执行后的参数 1代表执行成功
			textarea: '', //输入框 文字
			msgData: ''
		};
	},
	created() {
		if (typeof WebSocket === 'undefined') {
			console.log('您的浏览器不支持WebSocket');
		} else {
			// console.log('您的浏览器支持WebSocket')
			this.initWebSocket();
		}
	},
	mounted() {
		this.scrollToBottom();
	},
	updated() {
		this.scrollToBottom(); //每次页面渲染完之后滚动条在最底部
	},
	methods: {
		// WebSockets参数初始化
		initWebSocket() {
			console.log('WebSocket启动中......');
			//WebSocket服务器地址
			let wsurl = 'ws://192.168.0.228:10086/ws/';
			this.webSock = new WebSocket(wsurl);
			this.webSock.onopen = this.webSocketOpen; //连接成功
			this.webSock.onmessage = this.webSocketAcceptMessage; //广播成功
			this.webSock.onerror = this.webSocketError; //连接断开,失败
			this.webSock.onclose = this.webSocketClose; //连接关闭
		},
		//初始化WebSocket
		webSocketOpen() {
			console.log('连接成功');
			this.heartBeat();
		}, //连接成功
		webSocketError() {
			console.log('连接失败');
			this.reconnect();
		}, //连接失败
		webSocketClose() {
			console.log('断开连接');
			this.reconnect();
		},
		//接受webSocket消息
		webSocketAcceptMessage(res) {
			this.heartBeat(); //收到消息会刷新心跳检测,如果一直收到消息,就推迟心跳发送
			this.msgData = eval("'" + res.data + "'"); //ws请求返回的数据流
			this.arr.push(msgData);//将数据添加进数组
			
		},
		//发送数据到服务端
		webSocketSend(data) {
			this.webSock.send(JSON.stringify(data));
		},
		//重新连接 WebSocket服务
		reconnect() {
			if (this.lockReconnect) {
				//连接失败和关闭之后都会触发,通过lockReconnect控制只连接了一个webSocket
				return;
			}
			this.lockReconnect = true;
			//clearTimeout() 方法可取消由 setTimeout() 方法设置的定时操作。
			// clearTimeout() 方法的参数必须是由 setTimeout() 返回的 ID 值。
			this.reconnectData && clearTimeout(this.reconnectData);
			// setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式
			//5s后调用initWebSocket()
			//这个函数执行成功 reconnectData会变为1 也就是true
			this.reconnectData = setTimeout(() => {
				this.initWebSocket();
				this.lockReconnect = false;
			}, 5000);
		},
		//心跳检测
		heartBeat() {
			this.timeoutObj && clearTimeout(this.timeoutObj);
			this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
			this.timeoutObj = setTimeout(() => {
				this.webSocketSend({ type: '心跳检测' }); //根据后台要求发送
				this.serverTimeoutObj = setTimeout(() => {
					this.webSock.close(); //如果10秒之后我们没有收到 后台返回的心跳检测数据 断开socket,断开后会启动重连机制
				}, 10000);
			}, this.timeout);
		},
		//使滚动条固定在底部
		scrollToBottom: function() {
			this.$nextTick(() => {
				//Vue 在更新 DOM 时是异步执行的,为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。
				var container = this.$el.querySelector('.data'); //返回父元素的第一个匹配的子元素
				container.scrollTop = container.scrollHeight;
			});
		},
		load() {
			//数据流 element-ui无限滚动函数
			this.count = this.arr;
			// console.log(this.count)
		}
	},
	destroyed() {
		this.lockReconnect = true;
		this.webSock.close(); //离开路由之后断开websocket连接
		clearTimeout(this.reconnectData); //离开清除 timeout
		clearTimeout(this.timeoutObj); //离开清除 timeout
		clearTimeout(this.serverTimeoutObj); //离开清除 timeout
	}
};
</script>
<style>
.content-left {
	width: 375px;
	height: 625px;
	background: url(../../../static/leftpage.png) no-repeat;
	background-size: 100% 100%;
	box-shadow: 0 0 40px 0 rgba(98, 103, 211, 0.3);
}
.title {
	display: flex;
	justify-content: flex-start;
	align-items: center;
	width: 100%;
	margin-left: 32px;
	line-height: 65px;
}
.title-text {
	letter-spacing: 5px;
	color: #f1f1fe;
	font-size: 20px;
}
.title-icon {
	display: block;
	width: 54px;
	height: 17px;
	background: url(../../../static/titleicon.png) no-repeat;
	background-size: 100% 100%;
	margin-left: 12px;
}
.content-left-data {
	width: 86%;
	height: 535px;
	padding-bottom: 5px;
	box-sizing: border-box;
	margin: auto;
	background: #383195;
}
.content-left-data-text {
	width: 100%;
	padding-left: 10px;
	padding-right: 10px;
	box-sizing: border-box;
	font-size: 14px;
	margin-top: 5px;
	color: #ac7fff;
}
</style>
注意我这里使用了背景图片,记得取消,或者换成背景就好,不然会路径报错

好了,这样终于实现我想要的实时数据流效果了。还有就是具体情况具体分析,我这只是处理过大数据流的一种思路,如果有更好的实现方法可以告诉我,大家互相学习一下,如果有帮助到解决问题,麻烦给个赞,谢谢~

Logo

前往低代码交流专区

更多推荐