前言

昨天写了这篇最细节的Flask+echarts+mysql+自动刷新升级版(websocket),前后端都是放到一起的,今天做一个分离版的,通过vue写前端。

一、vue2+websocket部署

基本部署就不多做赘述了,网上资料很多,新建一个vue项目,用pycharm打开,安装了jquery,先测试了一下,处理思路如下:

<template>
<div>
  <input type="text" placeholder="请输入消息" v-model="msg" />
  <button @click="handle">发送</button>
</div>
</template>

<script>
    const ws = new WebSocket('ws://127.0.0.1:8000/test');
    export default {
        name: "Home",
        data(){
          return{
            msg: '',
            username:'',
            msgList:[]
          }
        },
      mounted() {
          this.username = localStorage.getItem('username');
          if(!this.username){
            // this.$router.push('/');
          }
          // 绑定四个事件处理函数
          ws.addEventListener('open', this.handleWsOpen.bind(this), false);
          ws.addEventListener('close', this.handleWsClose.bind(this), false);
          ws.addEventListener('error', this.handleWsError.bind(this), false);
          ws.addEventListener('message', this.handleWsMessage.bind(this), false);

      },
      methods:{
          // 方法的预处理
          handle(){
            const msg = this.msg;
            if(!msg.trim().length){
            }
          },
        handleWsOpen(e){
          console.log('websocket Open!', e);
        },
        handleWsClose(e){
          console.log('websocket Close!', e);
        },
        handleWsError(e){
          console.log('websocket Error!', e);
        },
        handleWsMessage(e){
          console.log('websocket Message!', e);
        }
      }
    }
</script>

结果如下,由于没部署服务端,导致是这样。

python flask 页面 局部刷新_Vue

二、vue2+websocket+flask

由于我自己在测试的过程中遇到了很多问题,先讲一讲逻辑

现在的前后端分离页面和接口不是一个程序,例如本例中

前端页面为localhost:8080

后端接口为localhost:5000

如下图:当我启动前端程序的时候报错第二个,启动后端服务器的时候报错第一个。

1.第一个错误就是CORS跨域错误,我们知道协议,域名 ,端口 要一样才算一个站点,这两个端口号不同,因此会出现跨域错误。

2.第二个错误就是服务器没有和前端连接。

python flask 页面 局部刷新_python_02


因此在写服务端(flask)的时候要注意添加跨域请求处理:

socketio = SocketIO()
socketio.init_app(app, cors_allowed_origins='*')

以下为源码,细节部分写在注解中:
服务器app_vue.py:

from flask import Flask, render_template
from flask_cors import CORS
from flask_socketio import SocketIO, emit, send
from threading import Lock

async_mode = None
app = Flask(__name__)
CORS(app)  # 跨域问题
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO()
socketio.init_app(app, cors_allowed_origins='*')
thread = None
thread_lock = Lock()


# @app.route('/')
# def index():
#     return render_template('test.html')

@socketio.on('conn', namespace='/test')
def test_connect():
    print('connect')
    socketio.emit('server_response', {'data': 'I love u!'}, namespace='/test')



if __name__ == '__main__':
    socketio.run(app, host='127.0.0.1', port='5000', debug=True)

客户端vue部分:

  1. main.js引入socketio:
import VueSocketIO from 'vue-socket.io'
import socketIO from 'socket.io-client'

Vue.use(new VueSocketIO({
  debug: true,
  // "ws://域名:端口号/namespace"
	connection: socketIO.connect('ws://127.0.0.1:5000/test', {
	  autoConnect:false
    })
}))
  1. vue
<template>
  <div class="wrap">
    <button @click="socketEmit">连接Socket</button>
    <button @click="socketSendmsg">发送数据</button>
    </div>
</template>

<script>
  export default {
    data() {
      return {
        data:{},
      }
    },
    methods:{
      socketEmit(){
        // 开始连接socket
        this.$socket.open();
      },
      // 发送消息
      socketSendmsg(){
        console.log('现在开始发送消息')
        // conn 是与后端约定好的名称
        this.$socket.emit('conn');
        // server_response 是前端传过来的信息说明
        this.sockets.subscribe('server_response', (res) => {
          console.log(res.data);
        })
        }

    },
    sockets:{
      connect: function () {
          console.log('连接成功')
      },
      disconnect: function () {
          console.log('断开连接')
      },
      reconnect: function () {
          console.log('重新连接')
      },
    },
    beforeDestroy() {
      // 关闭socket
      // this.sockets.unsubscribe('conn');
      this.$socket.close();
    }
  }
</script>

需要注意的是前后端启动不分顺序,但flask启动必须通过命令行终端启动,不要通过pycharm编译器启动,在这里先启动服务器:python app_vue.py,再启动客户端:npm run dev,结果如下:

python flask 页面 局部刷新_python_03

三、加入线程传值画图

第一步:测试服务器不断读取数据库传输数据给客户端,代码在这篇Flask+echarts+mysql+自动刷新升级版(websocket),这里展示结果:

python flask 页面 局部刷新_Vue_04


有个问题,python在命令行运行的时候模板会出现找不到的情况,在这里我说明下:

1.如果是非自定义的包,请直接”pip install 包“ 下载。

2.如果是自定义的包,如下

import sys
//  sys.path.append("想要引入包的绝对路径")
sys.path.append("E:\pycharm2020\projects\WebsocketTest\db")

服务器部分:
app_create_vue.py和db_create.py在前言文献中找。
命令行分别运行python app_create_vue.pypython db_create.py

前端部分:

  1. 在main.js中引入echarts,没有这个包的请下载4版本的,5版本有很多兼容性问题,npm install echarts@4.8.0 --save
import echarts from "echarts";
Vue.prototype.$echarts = echarts;
  1. vue部分,直接上代码
<template>
  <div class="wrap">
    <button @click="socketEmit">连接Socket</button>
    <button @click="socketSendmsg">发送数据</button>
    <div id="main" style="height:500px;border:1px solid #ccc;padding:10px;"></div>
    </div>
</template>

<script>
  import echarts from "echarts";

  export default {
    data() {
      return {
        data:{},
      }
    },
    methods:{
      socketEmit(){
        // 开始连接socket
        this.$socket.open();
      },
      // 发送消息
      socketSendmsg(){
        console.log('现在开始发送消息')
        // conn 是与后端约定好的名称
        this.$socket.emit('conn');
        // 先画好图,然后以下读取的数据不断push进图中
        var myChart = echarts.init(document.getElementById('main')) // 拿到一个实例
        var record_t = ["","","","","","","","","",""], temperature = [0,0,0,0,0,0,0,0,0,0]
        myChart.setOption({
              title: {
                  text: 'websocket温度测试'
              },
              tooltip: {},
              legend: {
                  data:['temperature']
              },
              xAxis: {
                  data: []
              },
              yAxis: {},
              series: [{
                  name: 'temperature',
                  type: 'line',
                  data: []
              }]
          });
        // server_response 是前端传过来的信息说明
        this.sockets.subscribe('server_response', (res) => {
          
          // 测试打印
          console.log(res.data[0]);
          console.log(res.data[1]);
          // 每次获取到最新数据之后应该是做出对图标的插入操作
          record_t.push(res.data[0]);
          console.log(record_t);

          temperature.push(parseFloat(res.data[1]));
          console.log(temperature);
          if(record_t.length >= 10){
            record_t.shift();
            temperature.shift();
          }
          myChart.setOption({
            xAxis: {
                        data: record_t
                    },
                    series: [{
                        name: 'temperature', // 根据名字对应到相应的系列
                        data: temperature
                    }]
          })

        })
        }

    },
    sockets:{
      connect: function () {
          console.log('连接成功')
      },
      disconnect: function () {
          console.log('断开连接')
      },
      reconnect: function () {
          console.log('重新连接')
      },
    },
    beforeDestroy() {
      // 关闭socket
      // this.sockets.unsubscribe('conn');
      this.$socket.close();
    }
  }
</script>

结果如图,前后端分离完成:

python flask 页面 局部刷新_mysql_05

结语

前后端分离有关数据处理的demo就已经结束了,后期将会把这三篇后续更新完,并且优化,应用到养殖实体。