作爲一名有追求的碼農來說,不管是前端、後端、抑或是測試、運維,都需要保持一定的好奇心纔可以,那麼大家都知道Vue作爲前端框架的集大成者,擁有着易用、靈活和高效的優點,那麼對於在Vue項目中集成WebSocket,大家有沒有實踐過呢?今天我爲大家分享一下如何在Vue項目中集成WebSocket。
開發環境
- Window 10.0.17763
- Node 10.18.0
- Visual Studio Code 1.48.2
- Vue 2.6.12
特別說明
本項目使用
SockJS-Client
和STOMP.js
來支持WebSocket後端(Node.js、Java等),在支持WebSocket的瀏覽器中可以直接進行連接、消息收發和端口等操作(詳細內容請參考相關文檔)。
接入步驟
添加依賴
我們在項目的入庫頁面(index.html
)中通過CDN的方式引入SockJS-Client
和STOMP.js
,文件內容如下。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>
<title>信息管理系統</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.0/sockjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
<div id="app"></div>
</body>
</html>
在Vue文件中連接和關閉WebSocket
既然我們在項目的入口頁面中引入了WebSocket相關庫,那麼掛載在app
下的Vue組件均可以使用STOMP
和SockJS
,此時我們在Vue的生命週期函數mounted
、和beforeDestroy
中分別調用WebSocket的初始化和銷燬函數,在data中聲明WebSocket連接的Host
、Topic
等相關變量,下面給出Vue文件的內容如下。
<template>
<div class="app-container">
<el-row>
<el-col>
<search @getTableData="getTableData" @deleteSelected="remove"></search>
</el-col>
</el-row>
<el-row>
<el-col>
<Table @search="search" :data="gridData" :table="table" :pageParams="pageParams" :pageSizes="[10, 20, 50]" @getSelected="getSelected"></Table>
</el-col>
<el-button @click="sendMessage">發送消息</el-button>
</el-row>
</div>
</template>
<script>
import {
list,
save
} from "@/api/dashboard/enterprise/myMessage";
import Table from "@/components/table";
import to from "@/to";
import {
getToken
} from "@/utils/auth";
import search from "./search";
import {
mapState,
mapActions
} from "vuex";
const moment = require("moment");
export default {
name: "MesageList",
components: {
Table,
search
},
data: function () {
return {
table: {
// 行定義
columns: [{
prop: "content",
label: "消息內容",
width: ""
},
{
prop: "sender",
label: "發送者",
width: ""
},
{
prop: "typeName",
label: "消息類型",
width: ""
}
],
total: 0
},
wsHost: "http://localhost:8080/websocket",
wsTopic: "/topic/greeting",
websocket: null,
stompClient: null,
isConnected: false,
message: {},
messages: [],
headers: {
Authorization: getToken()
}
};
},
computed: {
...mapState("dashboard/message/index", [
"editDialogVisible",
"editDialogTitle",
"gridData",
"pageParams",
"checkboxSelected",
"params",
"total",
"form"
])
},
mounted() {
this._initSockJs();
},
beforeDestroy() {
this._destroySockJs();
},
methods: {
...mapActions("dashboard/message/index", ["setStateData"]),
// 操作回調
action(obj) {
if (obj.methods === "delete") {
this.setStateData({
checkboxSelected: [obj.row]
});
this.remove();
}
},
// 刪除
remove() {
if (this.checkboxSelected && this.checkboxSelected.length > 0) {
this.$confirm("此操作將永久刪除, 是否繼續?", "提示", {
confirmButtonText: "確定",
cancelButtonText: "取消",
type: "warning"
})
.then(async () => {
let [err, res] = await to(deleteByIds(this.checkboxSelected));
if (err) {
throw new Error(err.message);
}
this.$message({
type: "success",
message: "刪除成功"
});
this.getTableData();
})
.catch(() => {
this.$message({
type: "info",
message: "已取消刪除"
});
});
}
},
// 查詢
search(pageParams) {
this.setStateData({
pageParams: pageParams
});
this.getTableData();
},
// 選中回調
getSelected(multipleSelection) {
this.setStateData({
checkboxSelected: multipleSelection
});
},
// 獲取數據
async getTableData() {
let response = await list(this.params, this.pageParams);
let gridData = response.data.list;
let total = response.data.total;
this.setStateData({
gridData: gridData
});
this.table.total = total;
},
_initSockJs() {
this.getTableData();
this.socket = new SockJS(this.wsHost);
this.stompClient = Stomp.over(this.socket);
// 訂閱
this.stompClient.connect(this.headers, frame => {
console.log("WebSocket連接成功", frame);
this.isConnected = true;
// 廣播
this.stompClient.subscribe(this.wsTopic, response => {
console.log("/websocket/message", JSON.parse(response.body));
this.messages.push(JSON.parse(response.body));
this.setStateData({
gridData: this.messages
});
});
// 一對一
this.stompClient.subscribe("/user/topic/greeting", response => {
console.log(
"/user/topic/greeting/message",
JSON.parse(response.body)
);
this.messages.push(JSON.parse(response.body));
this.setStateData({
gridData: this.messages
});
});
// 廣播
this.stompClient.subscribe("/topic/greeting", response => {
console.log("/topic/greeting/message", JSON.parse(response.body));
this.messages.push(JSON.parse(response.body));
this.setStateData({
gridData: this.messages
});
});
});
},
_destroySockJs() {
if (this.stompClient != null) {
this.stompClient.disconnect();
this.socket.onclose;
this.socket.close();
this.stompClient = {};
this.socket = {};
this.isConnected = false;
}
console.log("WebSocket斷開成功");
},
async sendMessage() {
this.message = {
sender: this.$store.getters.introduction,
type: "3",
content: "消息內容",
receiver: "*",
sendingDate: moment(new Date()).format("YYYY-MM-DD HH:mm:ss")
};
let [err, res] = await to(save(this.message));
if (err) {
throw new Error(err.message);
}
this.stompClient.send(this.wsTopic, {}, JSON.stringify(this.message));
this.$message({
showClose: true,
message: "消息發送成功",
type: "success"
});
}
}
};
</script>
sendMessage
函數用於測試消息發送,發送完消息後持久化消息並通過訂閱的Topic即時收取消息,收到消息後保存到表格中。
getToken
函數是爲了獲取登錄認證後保存的個人信息。
驗證連接結果
我們啓動前後端的項目,然後定位到該頁面,打開開發者工具並切換到控制檯,控制檯會顯示以下信息。
通過以上的截圖我們可以得知WebSocket
連接的後端地址,心跳檢測的輸出和stompClient
的認證字段,那麼急於此我們可以構建不同的應用場景,比如聊天、消息收發、任務提醒等功能,再配合其他功能來滿足客戶的訴求,我相信WebSocket
的接入會讓你的應用更好用。
個人收穫及感想
我們的文章今天爲大家介紹了Vue項目中接入WebSocket的方法,通過連接、收發消息和斷開等方法來接入WebSocket後端,接入之後就可以愉快地集成其他的業務啦。而在現在的複雜多變的產品迭代週期中,WebSocket不可或缺,並且會不斷髮展和變化,相信過不了多久,我們的產品也會慢慢完善,並趨於完美。讓我們一起持續打造能滿足客戶訴求的好產品,持續爲客戶做好服務,成爲更好的團隊和更好的自己。