websocket使用
一、服务端:
1、koa2中使用websocket
1、安装ws
npm i ws -S
2、使用
- 创建对象
- 监听连接事件
- 监听数据接收事件
- 发送数据
在app.js中添加如下代码:
//4、websocket的使用
//引入websocket
const WebSocket=require('ws')
//4-1、创建对象,绑定端口
const wss=new WebSocket.Server({
port:9998
});
//4-2、监听连接事件
wss.on('connection',(client)=>{
console.log("客户端连接成功。。。");
//4-3、监听接收消息事件
client.on('message',(msg)=>{
console.log("接收到来着客户端的信息:"+msg);
//模拟客户端往服务端发送数据
client.send("hello websocket!i am app.js")
})
})
3、测试
- websocket是window对象提供了的,不用下载依赖可以直接使用
- 创建对象
- 监听事件(连接成功事件
ws.onopen
、接收数据事件ws.onmessage
、关闭连接事件ws.onclose
) - 发送数据到服务端
ws.send
测试 一下,新建文件demo.html放在app.js同一级,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="connId">连接</button>
<button id="sendId" disabled="true">发送</button></br>
接收到的信息:<span id="msgId"></span>
</body>
<script>
var conn=document.getElementById('connId')
var send=document.getElementById('sendId')
var msgId=document.getElementById('msgId')
var ws=null
conn.onclick=function(){
ws=new WebSocket("ws://localhost:9998")
ws.onopen=()=>{
console.log("连接成功");
send.disabled=false//修改发送按钮可用状态
}
ws.onmessage=(msg)=>{
console.log(msg);
msgId.innerHTML=msg.data
}
ws.onclose=()=>{
console.log("关闭连接");
send.disabled=true
}
}
send.onclick=function(){
console.log("开始发送");
ws.send("hello i am demo.html")
}
</script>
</html>
4、在上面的基础上改造完善代码
将app.js里面关于websocket的代码提出到websocket_utils.js并导出
//4、websocket的使用
//引入websocket
const WebSocket=require('ws')
//4-1、创建对象,绑定端口
const wss=new WebSocket.Server({
port:9998
});
//服务端开启了监听
//4-2、监听连接事件
module.exports.listen=()=>{
wss.on('connection',(client)=>{
console.log("客户端连接成功。。。");
//4-3、监听接收消息事件
client.on('message',(msg)=>{
console.log("接收到来着客户端的信息:"+msg);
//模拟客户端往服务端发送数据
client.send("hello websocket!i am app.js")
})
})
}
在app.js里将websocket_utils.js导入并监听
//4、websocket的使用
//引入websocket_utils.js
const webSocketService=require('./utils/websocket_utils')
//开启服务端的监听
webSocketService.listen()
2、springboot中使用websocket
案例一
1、引入依赖
<!--websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2、添加配置类
package com.furenqiang.system.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 开启WebSocket支持
* @author EricFRQ
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3、添加工具类
package com.furenqiang.system.utils;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 前后端交互的类实现消息的接收推送(自己发送给自己)
*
* @ServerEndpoint(value = "/test/one") 前端通过此URI和后端交互,建立连接
*/
@ServerEndpoint(value = "/test/one")
@Component
public class WebSocketUtil {
/** 记录当前在线连接数 */
private static AtomicInteger onlineCount = new AtomicInteger(0);
private static final Logger logger=LoggerFactory.getLogger(WebSocketUtil.class);
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
onlineCount.incrementAndGet(); // 在线数加1
logger.info("有新连接加入:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
onlineCount.decrementAndGet(); // 在线数减1
logger.info("有一连接关闭:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
/**
* 收到客户端消息后调用的方法
*
* @param message
* 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
logger.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
this.sendMessage("Hello, " + message, session);
}
@OnError
public void onError(Session session, Throwable error) {
logger.error("发生错误");
error.printStackTrace();
}
/**
* 服务端发送消息给客户端
*/
private void sendMessage(String message, Session toSession) {
try {
logger.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getBasicRemote().sendText(message);
} catch (Exception e) {
logger.error("服务端发送消息给客户端失败:{}", e);
}
}
}
4、新建前端测试页面
resources下新建static文件夹,static下新建index.html
<!DOCTYPE HTML>
<html>
<head>
<title>My WebSocket</title>
</head>
<body>
<input id="text" type="text" />
<button onclick="send()">Send</button>
<button onclick="closeWebSocket()">Close</button>
<div id="message"></div>
</body>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket, 主要此处要更换为自己的地址
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:10012/test/one");
} else {
alert('Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function() {
setMessageInnerHTML("error");
};
//连接成功建立的回调方法
websocket.onopen = function(event) {
//setMessageInnerHTML("open");
}
//接收到消息的回调方法
websocket.onmessage = function(event) {
setMessageInnerHTML(event.data);
}
//连接关闭的回调方法
websocket.onclose = function() {
setMessageInnerHTML("close");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
websocket.close();
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
//关闭连接
function closeWebSocket() {
websocket.close();
}
//发送消息
function send() {
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</html>
5、测试
访问地址http://localhost:10012/index.html
浏览器输入内容 点击发送send按钮
服务端
案例二
1、和上面一二步骤一样,引入依赖,添加配置类
2、添加工具类
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 前后端交互的类实现消息的接收推送(自己发送给自己)
*
* @ServerEndpoint(value = "/test/one") 前端通过此URI和后端交互,建立连接
*/
@ServerEndpoint(value = "/websocket/one")
@Component
public class WebSocketUtil {
/** 记录当前在线连接数 */
private static AtomicInteger onlineCount = new AtomicInteger(0);
private static final Logger logger = LoggerFactory.getLogger(WebSocketUtil.class);
/** 存放所有在线的客户端 */
private static Map<String, Session> clients = new ConcurrentHashMap<>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
onlineCount.incrementAndGet(); // 在线数加1
clients.put(session.getId(), session);
logger.info("有新连接加入:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
onlineCount.decrementAndGet(); // 在线数减1
clients.remove(session.getId());
logger.info("有一连接关闭:{},当前在线人数为:{}", session.getId(), onlineCount.get());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
logger.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
this.sendMessage(message, session);
}
@OnError
public void onError(Session session, Throwable error) {
logger.error("发生错误");
error.printStackTrace();
}
/**
* 服务端发送消息给客户端
*/
public void sendMessage(String message, Session fromSession) {
if (fromSession == null) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
fromSession = sessionEntry.getValue();
logger.info("服务端给客户端[{}]发送消息{}", fromSession.getId(), message);
fromSession.getAsyncRemote().sendText(message);
}
} else {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
Session toSession = sessionEntry.getValue();
// 排除掉自己
if (!fromSession.getId().equals(toSession.getId())) {
logger.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getAsyncRemote().sendText(message);
}
}
}
}
}
3、使用
WebSocketUtil webSocketUtil = new WebSocketUtil();
//websocket推送给前端
webSocketUtil.sendMessage(jobInfo.toString(), null);
二、浏览器端:vue中使用websocket
1、ws协议连接,地址比如ws://localhost:9998
1、封装websocket到socket_service.js
导出一个类WebSocketService,实现如下几步:
- 定义类并设计成单例模式
- 定义连接方法connect
- 连接方法connect里监听onxxx所有事件
- 存储回调函数
- 接收数据的处理
- 定义发送数据的方法
- 挂载类的实例对象到Vue的原型对象上
export default class WebSocketService{
/*
* 单例模式
*/
static instance=null
static get Instance(){
if(!this.instance){
this.instance= new WebSocketService()
}
return this.instance
}
ws=null
//连接服务器的方法
connect(){
if(!window.WebSocket){
return "您的浏览器不支持websocket"
}
this.ws=new WebSocket("ws://localhost:9998")
this.ws.onopen=()=>{
console.log("连接成功");
}
this.ws.onclose=()=>{
console.log("关闭连接");
}
this.ws.onmessage=(msg)=>{
console.log(msg);
}
}
}
2、在main.js中全局引用
在main.js里引入并调用
import WebSocketService from './utils/websocket_utils'
//websocket的连接并监听
WebSocketService.Instance.connect()
//websocket注册全局组件,可在其他页面使用this.$socket来获取到WebSocketService对象
Vue.prototype.$socket = WebSocketService.Instance
此时启动项目后,就可自动连接
2、使用http协议连接比如http://localhost:8040
资源包:node写的websocket引擎使用http协议连接的
1、下载依赖:npm install vue-socket.io@3.0.7 --s
2、使用:main.js里面引入
import VueSocketIO from "vue-socket.io";
Vue.use(
new VueSocketIO({
debug: true,
connection: "http://localhost:8040?userid=" + sessionStorage.getItem("inieToken"),
}))
3、使用页面中使用相应方法
<!-- 消息中心滚动消息 -->
<template>
<div class="msgDivClass">
<span class="msgSpanClass">{{ text }}</span>
</div>
</template>
<script>
export default {
data() {
return {
timerId: null,
msg: "滚动1234567890开始1234567890过程1234567890结束1234567890",
text: "",
socket: null,
};
},
components: {},
computed: {},
mounted() {
this.connSocket();
this.autoRoll();
},
created() {},
methods: {
connSocket() {
this.sockets.subscribe("notification", (data) => {//notification为服务端发送的方法名
data = JSON.parse(data);
this.msg = data.content + ":" + data.description + "。";
this.autoRoll();
});
},
autoRoll() {
let that = this;
that.text = that.msg;
this.timerId = setInterval(() => {
that.text =
that.text.substring(1, that.text.length) + that.text.substring(0, 1);
}, 500);
},
},
destroyed() {
clearInterval(this.timerId);
this.timerId = null;
},
};
</script>
<style scoped>
.msgDivClass {
width: 22%;
height: 5%;
border: 1px solid #809ca3;
position: absolute;
top: 3%;
left: 0.5%;
}
.msgSpanClass {
white-space: nowrap; /*强制span不换行*/
display: inline-block; /*将span当做块级元素对待*/
width: 100%; /*限制宽度*/
overflow: hidden; /*超出宽度部分隐藏*/
text-overflow: ellipsis; /*超出部分以点号代替*/
margin-top: 9%;
font-size: 25px;
color: #ffffff;
}
</style>
4、服务端代码如下:
var fs = require('fs');
var url = require("url");
var nicknames = {};
var app = require('http').createServer(function (request, response) {
var pathname = url.parse(request.url).pathname;
var responseJSON = {
statusCode: 200, message: "", data: null
};
response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"});
if (pathname == "/sendMsg") //处理post方式请求
{
request.addListener("data", function (postdata) {
var msgInfo = decodeURIComponent(postdata);
var msgJSON = JSON.parse(msgInfo);
var arruser = msgJSON.receiveId.split(",");
var users = "";
for (var item in nicknames) {
for (var i=0;i<arruser.length;i++) {
var userId = item.toString().split("_")[0];
if (userId == arruser[i]) {
msgJSON.receiveId = userId;
nicknames[item].emit('notification', JSON.stringify(msgJSON));
users += userId+",";
}
}
}
responseJSON.data = users;
});
request.addListener("end", function () {
response.write(JSON.stringify(responseJSON));
response.end();
});
} else if (pathname == "/getuserbyid") {
var item = url.parse(request.url).query;
if (nicknames[item]) {
responseJSON.data = {
userid: item,
referer: nicknames[item].handshake.headers.referer,
address: nicknames[item].handshake.address
};
} else {
responseJSON.statusCode = 500;
responseJSON.message = "用户不存在或未登录";
}
response.write(JSON.stringify(responseJSON));
response.end();
} else if (pathname == "/getuserlist") {
var userlist = [];
for (var item in nicknames) {
userlist.push({
userid: item,
referer: nicknames[item].handshake.headers.referer,
address: nicknames[item].handshake.address
});
}
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(JSON.stringify(userlist));
response.end();
} else {
response.writeHead(200, {"Content-Type": "text/plain"});
//消息发送状态 0:成功 1:失败
response.write("200");
response.end();
}
});
var io = require('socket.io').listen(app);
app.listen(8040);
io.sockets.on('connection', function (socket) {
var query = socket.handshake.query;
if (query.userid) {
if (!nicknames[query.userid + "_" + query.t]) {
nicknames[query.userid + "_" + query.t] = socket;
console.log("登录:" + query.userid + "_" + query.t);
console.log(socket.handshake.address);
console.log(socket.handshake.headers.referer);
}
}
//监听用户退出
socket.on('disconnect', function () {
//将退出的用户从在线列表中删除
if (nicknames.hasOwnProperty(query.userid + "_" + query.t)) {
//删除
delete nicknames[query.userid + "_" + query.t];
console.log("退出:" + query.userid + "_" + query.t);
}
});
});
三、其他项目中(我自己用的,可以不看)
1. 封装websocket的Api
/* eslint-disable no-mixed-spaces-and-tabs */
/*------------------------- web socket方法封装 -------------------------*/
/*连接websocket*/
var ws;
var port = '0'; //前一次端口号,断线重连时用到
var seq=0;//第几次请求握手
export const websocketFun = (parmas) => {
var WebSocketsExist = true;
try {
ws = new WebSocket("ws://" + parmas.websocketip + ":" + parmas.websocketport);
}
catch (ex) {
try {
ws = new WebSocket("ws://" + this.$store.state.websocketip + ":" + this.$store.state.websocketport);
}
catch (ex) {
WebSocketsExist = false;
}
}
if (!WebSocketsExist) {
return;
}
ws.onopen = WSonOpen;
//ws.onmessage = WSonMessage;
ws.onclose = WSonClose;
ws.onerror = WSonError;
return ws;
}
function WSonOpen() {
var json={};
json.userid=sessionStorage.getItem("userId");
json.username=sessionStorage.getItem("username");
json.FSNo="01";
json.svrtype="8";
json.msgType="msg_HandShake";
json.port=port;
json.reportflag="1";
json.format="0";
json.seq=seq;
seq++;
let str = JSON.stringify(json);
let length=str.length;
let len=length.toString(16);
len=len.padStart(4, "0");
str=len+str;
ws.send(str);
}
function WSonClose() {
}
function WSonError() {
}
2. 使用(我自己的案例)
<template>
<div class="meterSwitch">
<div class="header">
<div class="search">
<el-form size="mini" :inline="true" :model="search" class="demo-form-inline">
<el-form-item label="户号">
<el-input v-model="search.customerNum"></el-input>
</el-form-item>
<el-form-item label="户名">
<el-input v-model="search.customerName"></el-input>
</el-form-item>
<el-form-item label="电表地址">
<el-input v-model="search.meterAddress"></el-input>
</el-form-item>
<el-form-item>
<el-button icon="el-icon-search" size="mini" type="primary" @click="getMeterSwitchList">查询</el-button>
</el-form-item>
</el-form>
</div>
<div class="Newly">
<el-button icon="el-icon-connection" size="mini" type="primary" @click="readingSelect">透抄</el-button>
</div>
</div>
<div class="content">
<el-table
:data="tableData"
border
style="width: 100%"
height="100%"
ref="multipleTable"
tooltip-effect="dark"
@selection-change="handleSelectionChange"
>
<el-table-column align="center" type="selection" width="55"></el-table-column>
<el-table-column
align="center"
:show-overflow-tooltip="true"
width="150"
label="电表ID"
prop="fileId"
v-if="false"
></el-table-column>
<el-table-column
align="center"
:show-overflow-tooltip="true"
width="150"
label="集中器ID"
prop="upGoingId"
v-if="false"
></el-table-column>
<!-- <el-table-column type="index" width="50" prop="index"></el-table-column> -->
<el-table-column
align="center"
:show-overflow-tooltip="true"
width="120"
label="户名"
prop="customerName"
></el-table-column>
<el-table-column
align="center"
:show-overflow-tooltip="true"
width="120"
label="户号"
prop="customerNum"
></el-table-column>
<el-table-column
align="center"
:show-overflow-tooltip="true"
width="150"
label="电表地址"
prop="meterAddress"
></el-table-column>
<el-table-column
align="center"
:show-overflow-tooltip="true"
label="安装地址"
prop="installAddress"
></el-table-column>
<el-table-column
align="center"
:show-overflow-tooltip="true"
width="150"
prop="readingStatus"
label="透抄结果"
>
<template slot-scope="scope">
<span v-if="scope.row.readingStatus==1" style="color: green">成功</span>
<span v-else-if="scope.row.readingStatus==0" style="color: red">失败</span>
<span v-else style="color: black">未透抄</span>
</template>
</el-table-column>
<el-table-column
align="center"
:show-overflow-tooltip="true"
width="150"
label="数据内容"
prop="readingData"
></el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div class="block">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="search.page"
:page-sizes="pages"
:page-size="search.size"
layout="total,sizes, prev, pager, next, jumper"
:total="params.total"
></el-pagination>
</div>
</div>
</template>
<script>
import { websocketFun } from "@/request/websocketApi";
import { getMeterSwitchList, openSwitch } from "@/request/meterapi";
export default {
data() {
return {
ws: "",
search: {
page: 1,
size: 10,
meterAddress: "",
customerName: "",
customerNum: "",
organizationid: "",
gid: "",
type:'',
},
// 分页
pages: [10, 20, 40],
tableData: [],
exchangeTableData: [],
params: {
total: 0
},
dealRows: [],
multipleSelection: []
};
},
computed:{
tree(){
return this.$store.state.tree
}
},
watch: {
tree:{
deep:true,//代表深层次的监听
immediate:true,//页面初始化的时候就立即触发一次
handler(val){
// console.log('vuex树',val)
if(val.type===3){
this.search.meterAddress = val.name
}else {
this.search.meterAddress = ''
}
if(val.type===2){
this.search.customerName = val.name
this.search.gid = val.gid
this.search.type = val.type
}else {
this.search.customerName = ''
}
if(val.type===1){
this.search.gid = val.gid
this.search.type = val.type
}
// console.log('this.search---',this.search)
this.page = 1
this.getMeterSwitchList();
}
}
},
methods: {
getMeterSwitchList() {
getMeterSwitchList(this.search).then(res => {
this.tableData = res.data.data;
this.params.total = res.data.total;
});
if (this.ws == "") {
this.ws = websocketFun(this.$store.state);
this.ws.onmessage = this.WSonMessage;
}
},
WSonMessage(event) {
if (!event) {
return;
}
let str = event.data; //要截取的字符串
let index = str.indexOf("{");
let result = str.substr(index, str.length);
let events = eval("(" + result + ")");
if (events.result == "nak") {
this.$message({
message: "与前置机连接被拒绝!",
type: "error",
duration: 3000
});
} else if (events.result == "ack") {
console.log("与前置机连接成功!");
} else {
console.log(events);
if (events.errorCode == "ok") {
this.$message({
message: "操作成功!",
type: "success",
duration: 3000
});
//同时修改数据库里电表下达状态,关于电表的数据在events.objJson里,
//还需解析,然后根据电表地址 判断index,将数据写入到对应的列
// this.tableData[this.dealRow].readingStatus=1;
// this.tableData[this.dealRow].readingData=events.objJson;
} else if (events.errorCode == "notOnline") {
this.$message({
message: "操作失败,集中器不在线!",
type: "error",
duration: 3000
});
//同时修改数据库里电表下达状态,关于电表的数据在events.objJson里,
//还需解析,然后根据电表地址 判断index,将数据写入到对应的行
//events.objJson.forEach((val) => {
this.multipleSelection.forEach(val => {
this.tableData.forEach((v, i) => {
if (val.fileId == v.fileId) {
this.dealRows.push(i);
}
});
});
this.$refs.multipleTable.clearSelection();
for (let dealRow of this.dealRows) {
this.tableData[dealRow].readingStatus = 0;
this.tableData[dealRow].readingData = events.objJson;
}
this.dealRows = [];
} else if (events.errorCode == "failed") {
this.$message({
message: "操作失败!",
type: "error",
duration: 3000
});
} else {
this.$message({
message: events,
type: "error",
duration: 3000
});
}
}
},
handleCurrentChange(val) {
this.search.page = val;
this.getMeterSwitchList();
},
handleSizeChange(val) {
this.search.size = val;
this.search.page = 1;
this.getMeterSwitchList();
},
readingSelect() {
if (this.multipleSelection.length == 0) {
this.$message({
message: "请勾选后操作!",
type: "warning",
duration: 2000
});
}
if (this.ws.readyState == 1) {
for (let select of this.multipleSelection) {
let electricmeter = {};
electricmeter.fileId = select.fileId;
electricmeter.upGoingId = select.upGoingId;
openSwitch(electricmeter).then(res => {
let openSwitchStr = res.data.data;
this.ws.send(openSwitchStr);
console.log("已发送");
});
}
} else {
this.$message({
message: "未连接前置机!",
type: "warning",
duration: 2000
});
}
console.log(this.multipleSelection);
},
handleSelectionChange(val) {
this.multipleSelection = val;
}
},
created() {
this.getMeterSwitchList();
}
};
</script>
<style lang="scss">
.meterSwitch {
height: 100%;
.header {
vertical-align: middle;
.search {
// display: inline-block;
vertical-align: top;
}
.Newly {
display: block;
}
}
.content {
height: calc(100% - 120px);
margin-top: 10px;
.el-form-item {
width: 33% !important;
}
.demo-table-expand {
font-size: 0;
}
.el-form-item__label {
// width: 90px;
color: #99a9bf !important;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
}
}
</style>
3. 使用vuex保存连接websocket的ip、端口等信息
1、安装vuex
import vuex from 'vuex'
2、在main.js里把vuex注册到vue全局组件里
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import store from './store/index.js'
import Vuex from 'vuex'
Vue.use(ElementUI)
Vue.use(Vuex)//使用vuex
Vue.config.productionTip = false
import './assets/font/iconfont.css'
// 引入echarts
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
// 引入reset.css
import './assets/css/reset.css'
import './assets/css/base.css'
state: {
websocketip:"193.168.1.100",
websocketport:"20020",
},
var store = new vuex.Store({//创建vuex中的store对象
state
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')