5,vue利用websocket,显示数据的实时改变

本文详细介绍了如何利用WebSocket、Vuex和Vue的watch实现数据的实时更新。通过建立WebSocket连接,监听数据库数据变化,当数据更新时,Vuex的action和mutation配合更新状态,最终通过Vue组件的DOM操作展示最新数据。同时,文章还提供了Python脚本从数据库获取数据并发送到WebSocket服务器的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现效果:

在线测试的系统(用户名:liu,密码:12345)

###默认显示:
在这里插入图片描述

我们可以看到数据8弹窗的数值为8,现在我们在数据管理里将是这个值改为88,
在这里插入图片描述
过几秒(现在时间间隔为5秒),并没有刷新页面,发现显示的值已经变为88了。
值改变后:

这一过程中,我们用到了用来发送数据的websocket(由客户端建立连接,服务器可以主动向客户端推送数据,只需要一次http请求),vuex和vue的watch监听属性,以及改变显示的DOM操作。

准备工作:

1,使用websocketd客户端来进行websocket连接。

(如果要使用我的在线后台api,请跳过此步,因为已经连好了)
官网下载地址
百度云盘地址 提取码:eptj
作用:运行这个客户端,使得每隔一段时间这个客户端从数据库获取数据,并发送到指定端口上。
怎么用:
以百度云盘上的文件为例(就是我用的)
在这里插入图片描述
cmd到当前目录下,运行命令websocketd --port=8088 python cout.py
在这里插入图片描述
这句命令的作用:执行pthon文件cout.py(我是用python写的获取数据代码,当然用其它的语言也可以,如果你要试用我的这个示例,那么需要安装python和pip,并通过pip安装pymysql包引入到python中),并发送到8088端口地址上(其实就是http://127.0.0.1:8088)。
下面打开cout.py文件看一下里面执行了什么:

import random
from sys import stdout
from time import sleep
from itertools import count
import pymysql

db=pymysql.connect(host='localhost',user='xxx',passwd='xxx',db='xxx',port=3306,charset='utf8')
for i in count():
  # 使用cursor()方法创建cursor游标对象
  cursor=db.cursor()
  sql="""select Id,Num  from data 
  """
  data={}
  try:
     # 执行SQL语句
     cursor.execute(sql)
     # 提交到数据库执行
     db.commit()
     # 获取符合条件的所有数据
     results = cursor.fetchall()
     for item in results:
         data[item[0]]=str(item[1])  #random.randint(0,9))
     # 将数据类型从字典转为bytes类型的字典(不这样websocket会报“Could not decode a text frame as UTF-8”的错误)
     print(bytes('{}'.format(data),'utf-8'))
     stdout.flush()
  except Exception as e:
      # 发生错误时回滚
      db.rollback()
      print(e)    
  sleep(5)

代码很简单,就是从数据库获取数据,每隔5秒运行一次。(如果要用这个,用到的python库要安好)
如果运行成功会这样:
在这里插入图片描述
每隔一秒,执行一次代码,从数据库获取数据。

2,显示默认的弹窗:

数据我们通过vuex(关于vuex前面有说明)来保存传递。
在store.js中,state里添加iotData: {},
mutataion里添加:

//iotData
    setIOTData (state, data) {
      state.iotData = data
    },
    updateIOTTagConfig (state, data) {
      //将字符串分割为数组
      data = data.replace(/'/g, "")
      var array = data.slice(2, -4).split(",")
      var DATA = []
      array.forEach((item) => {
        item = item.split(":")
        DATA.push({
          Id: item[0],
          Num: parseFloat(item[1])
        })
      })
      state.iotData = DATA
    },

actions里添加:

updateIOTTagConfig ({ commit, state }, data) {
      //let newData = Object.assign({}, state.iotData)
      commit('updateIOTTagConfig', data)
    },

其中:iotData: {},表示默认的初始状态。setIOTData 表示第一次请求时为iotData赋值。actions里的updateIOTTagConfig表示执行 commit('updateIOTTagConfig', data),这句代码的作用是调用mutation里的updateIOTTagConfig方法,
mutation里的updateIOTTagConfig方法表示更新iotData的值。
在Home.vue里,使用setIOTDataiotData赋值,

...mapMutations(['setIOTData']),
    iot_data_get () {
      getData().then((res) => {
        this.setIOTData(res.data.response.AllData);
      });
    },

此时iotData就不是空的了。
这个数据在Map.vue中使用:

computed: {
    ...mapState(['iotData']),
  },
var name = this.iotData[j].Name;  //this.dataList_rlt[i].Name
                      this.iotData[j].Note = (this.iotData[j].Note != null) ? this.iotData[j].Note : "--"
                      var html2 = "";
                      html2 =
                        '<div class="mapWindow_monitor" style=" width:250px;position: absolute;z-index: 200;left: 10px; top: -20px;opacity: 0.8;">' +
                        '<div style="background-image: url(' + arrow_png + ');background-repeat: no-repeat;background-position: center;float: left;width: 11px; height: 31px;z-index: 2;">' +
                        '</div>' +
                        '<div class="mapWindow_monitor_body" style=" float: left; background-color: #00457b;bottom: 10px;top: 0px;left: 0px;right: 0px;z-index: 2;border: 1px solid #7597ba;border-radius: 7%;box-shadow: 0px 2px 5px #888888;padding: 2px;">' +
                        '<div class="mapWindow_monitor_name" style=" height: 20px;line-height: 20px;text-align: center;background-color: #00457b;color: #fff;font-weight: bold;text-align: center;font-size: 13px; border-bottom: 1px solid #ccc;">' + name + '</div>' +
                        '<ul class="mapWindow_monitor_content" style="  list-style: none;padding: 0;margin: 0;">'
                        + ' <li class="mapWindow_monitor_normal" style=" line-height: 20px;text-align: left;color: #fff;font-size: 11px;background-color: #0147b1 !important;font-family: Microsoft YaHei;list-style: none;padding: 0; margin: 0;border-left: 1px solid #817f7f; border-right: 1px solid #817f7f;border-bottom: 1px solid #817f7f;">' +
                        ' <span>' + "数值:" + this.iotData[j].Num + '</span>' +
                        '</li>' +
                        ' <li style=" line-height: 20px;text-align: left;color: #fff;font-size: 11px;background-color: #0147b1 !important;font-family: Microsoft YaHei;list-style: none;padding: 0; margin: 0;border-left: 1px solid #817f7f; border-right: 1px solid #817f7f;border-bottom: 1px solid #817f7f;">' +
                        ' <span>' + "备注:" + this.iotData[j].Note + '</span>' +
                        '</li>' +
                        '</ul></div></div>'
                        ;

此时弹窗可以显示数据了,但我们改变数据库数据时,并不发生改变。

正式工作:

1,util文件夹中新建websoket.js文件:

let glSocket = null;
import store from "../src/store"
export const localSocket = () => {
  if ("WebSocket" in window) {
    // console.log("您的浏览器支持 WebSocket!");
    // location.host
    if (!glSocket) {
      //如果要使用我的后台那下面的地址应改为:
      //    glSocket = new WebSocket("ws://112.125.90.247:8088/");
      glSocket = new WebSocket("ws://127.0.0.1:8088");
      glSocket.binaryType = 'arraybuffer';
      glSocket.onopen = () => {
        console.log('websocket连接成功');
      };

      glSocket.onclose = () => {
        // 关闭 websocket
        console.log("连接已关闭...");
        //断线重新连接
        setTimeout(() => {
          localSocket();
        }, 2000);
      };
      glSocket.onmessage = (msg) => {
        let d = JSON.stringify(msg.data);
        store.dispatch("updateIOTTagConfig", d);
      };
      
    }

  } else {
    // 浏览器不支持 WebSocket
    self.$notify.error({
      title: '错误',
      message: '您的浏览器不支持websocket,请更换其它浏览器再尝试'
    });
  }
}

export default glSocket;

这里需要注意的是两部分:
glSocket = new WebSocket("ws://127.0.0.1:8088");这里面的地址就是准备工作里的http://127.0.0.1:8088

 glSocket.onmessage = (msg) => {
        let d = JSON.stringify(msg.data);
        store.dispatch("updateIOTTagConfig", d);
      };

glSocket.onmessage表示当收到来自服务器的消息时被调用的,这个服务器就是我们的websocketd客户端。因为websocketd客户端每隔1秒运行一次代码,相当于glSocket.onmessage也每隔1秒执行一次,里面的代码很明显store.dispatch("updateIOTTagConfig", d);,也就是执行actions里的updateIOTTagConfig方法。

2,连接websocket。其实就是执行localSocket方法,执行一次就够了,在前面Home.vue获取数据时执行就行,也就是:

...mapMutations(['setIOTData']),
    iot_data_get () {
      getData().then((res) => {
        this.setIOTData(res.data.response.AllData);
        localSocket();
      });
    },

当然,这个方法localSocket是要引入的:

import { localSocket } from '../../util/websoket';

3,改变显示

回到Map.vue,这里我们要用到的是watch属性。

//监听属性:监听变量值发生变化执行相应函数)
  watch: {
    iotData: {
      handler (newval, oldval) {
        
        let result = []
        if (!oldval.length) result = newval
        else {
          result = newval.filter(item => {
            let obj = oldval.find(a => a.Id == item.Id && a.Num != item.Num)
            // if(obj){
            //   obj.Num=isNaN(obj.Num)?0:obj.Num
            // }
            return obj
          })
        }
        result.map(item => {
          let labelid = item.Id && item.Id.trim()
          if (labelid) {
            let label = document.getElementById('mapWindow_' + labelid)
            let span = label ? label.getElementsByTagName("span")[0] : null
            span && (span.innerHTML = "数值:" + item.Num)
          }
        })
      },
      deep: true
    }
  },

监听iotData,当iotData有Num值变化时,通过操作dom改变显示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木卯彳亍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值