Vue3 無(wú)所不能!我用 Vue3 寫(xiě)接口給前端用你們信嗎?
最近接到一個(gè)需求,有兩個(gè)頁(yè)面分別連接了兩個(gè)Websocket連接,并且這兩個(gè)頁(yè)面可以通過(guò)Websocket去相互影響
圖片
為了方便講解,以下會(huì)簡(jiǎn)化業(yè)務(wù)。
這兩個(gè)頁(yè)面簡(jiǎn)化后如下:
圖片
- 當(dāng)點(diǎn)擊頁(yè)面1更新按鈕后,頁(yè)面1會(huì)+1,而 頁(yè)面2 會(huì)變成 頁(yè)面1 數(shù)值的10倍。
- 當(dāng)點(diǎn)擊頁(yè)面2清空按鈕后,頁(yè)面1和2的數(shù)值都會(huì)變成0。
- 頁(yè)面2需要定時(shí)去獲取數(shù)值,并展示出來(lái)。
效果如下:
圖片
最普通的做法?
其實(shí)不難,只需要用 Nodejs新建兩個(gè) Websocket連接,然后維護(hù)一個(gè) count變量即可。
npm i ws至于怎么跨兩個(gè)Websocket進(jìn)行通信呢?其實(shí)也簡(jiǎn)單,無(wú)非就是定義兩個(gè)全局變了,去存儲(chǔ)兩個(gè)Websocket實(shí)例唄!
圖片
接著就是前端頁(yè)面進(jìn)行Websocket通信,即可完成。
Page1
圖片
Page2
圖片
即可完成效果。
圖片
不太好維護(hù)吧?
其實(shí)這個(gè)需求唯一的難點(diǎn)就在于怎么去跨兩個(gè)Websocket進(jìn)行通信,上面的做法是定義兩個(gè)全局變量去存儲(chǔ)
但是感覺(jué)這樣不太妥,如果以后Websocket連接實(shí)例多了,那么維護(hù)起來(lái)會(huì)不會(huì)很費(fèi)勁?
我有個(gè)想法:能不能讓每一個(gè) Websocket 連接各自管自己的事
但是其實(shí)想要做到各管各的,是有難處的,難就難在于:他們都依賴于count的變化,一個(gè)實(shí)例改變了 count之后,怎么通知另一個(gè)實(shí)例去做操作呢?
想到這里我就想到了 Vue3,當(dāng)數(shù)據(jù)變化時(shí),可以監(jiān)聽(tīng)數(shù)據(jù)變化,并在監(jiān)聽(tīng)函數(shù)中去做你想做的事情
圖片
那么能不能把Vue3的那一套響應(yīng)式 API 拿到 Nodejs中去用呢?
答案是:可以?。?!Vue3是真的牛,他把 API 都拆出來(lái)放在 @vue/reactivity這個(gè)包中了,就算你不在瀏覽器環(huán)境,也能用這個(gè)包去做響應(yīng)式邏輯,這個(gè)包擁有了幾乎所有 Vue 的響應(yīng)式 API。
npm i @vue/reactivity我們只需要用到ref、computed、watch,即可讓每個(gè) Websocket 實(shí)例各管各的。
圖片
圖片
其實(shí)大家可以把@vue/reactivity當(dāng)做一個(gè)工具庫(kù)來(lái)看,不要綁定上 Vue,他就是一個(gè)響應(yīng)式工具庫(kù)?。?!甚至在 React 項(xiàng)目中也可以用。
// Nodejs 端 index.js
// 引入 WebSocket 庫(kù)
const WebSocket = require('ws');
// 引入 Vue 響應(yīng)式 API
const reactivity = require('@vue/reactivity')
const {
ref,
computed,
watch
} = reactivity
// 創(chuàng)建 WebSocket 服務(wù)器
const wss1 = new WebSocket.Server({
port: 8001
});
const wss2 = new WebSocket.Server({
port: 8002
});
// 記錄數(shù)字
const count = ref(0)
// 計(jì)算出 10 倍
const sum = computed(() => 10 * count.value)
// 連接1
wss1.on('connection', (ws) => {
// 處理來(lái)自客戶端的消息
ws.on('message', (message) => {
// count 變化
count.value = Number(String(message))
});
// 監(jiān)聽(tīng) count,并通知頁(yè)面2
watch(count, v => {
ws.send(v)
})
});
// 連接2
wss2.on('connection', (ws) => {
// 處理來(lái)自客戶端的消息
ws.on('message', () => {
// 執(zhí)行清空命令
count.value = 0
});
// 監(jiān)聽(tīng) sum,并通知頁(yè)面2
watch(sum, v => {
ws.send(v)
})
// 模擬定時(shí)任務(wù)
setTimeout(() => {
ws.send(sum.value)
}, 3600 * 12);
});
<!-- Page1.vue -->
<template>
<div class="flex justify-center mb-3 text-4xl font-bold">頁(yè)面1</div>
<Button type="primary" @click="click">點(diǎn)擊更新數(shù)據(jù)</Button>
<div class="text-lg">當(dāng)前數(shù)值:{{ count }}</div>
</template>
<script setup lang="ts">
import { Button } from 'ant-design-vue';
import { ref } from 'vue';
const count = ref(0);
// 創(chuàng)建 WebSocket 客戶端
const socket = new WebSocket('ws://localhost:8001');
const click = () => {
count.value++;
// 發(fā)送消息到服務(wù)器
socket.send(`${count.value}`);
};
// 接受服務(wù)端的消息
socket.addEventListener('message', e => {
count.value = e.data;
});
</script>
<!-- Page2.vue -->
<template>
<div class="flex justify-center mb-3 text-4xl font-bold">頁(yè)面2</div>
<Button type="primary" @click="click">清空數(shù)據(jù)</Button>
<div class="text-lg">當(dāng)前數(shù)值:{{ count }}</div>
</template>
<script setup lang="ts">
import { Button } from 'ant-design-vue';
import { ref } from 'vue';
const count = ref(0);
// 創(chuàng)建 WebSocket 客戶端
const socket = new WebSocket('ws://localhost:8002');
const click = () => {
// 發(fā)送消息到服務(wù)器
socket.send('Hello, server!');
};
// 接受服務(wù)端的消息
socket.addEventListener('message', e => {
count.value = e.data;
});
</script>






























