当前位置: 首页 > news >正文

基于 Vue3 + WebSocket 实现的平板控制端与大屏展示端联动方案

包含断线重连逻辑,采用「控制端 - 服务器 - 展示端」架构,通过 Vue 的响应式特性管理连接状态和指令交互。

技术栈

  • 服务器:Node.js + ws 库(WebSocket 服务)
  • 控制端 / 展示端:Vue3(Composition API) + 原生 WebSocket API
  • 构建工具:Vite(快速开发体验)

实现步骤

1. 服务器端(转发与连接管理)

与前方案核心逻辑一致,负责维护连接、转发指令和心跳检测(复用 server.js):

// server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });const clients = { controller: null, display: null }; // 存储两端连接
const HEARTBEAT_INTERVAL = 30000; // 30秒心跳检测wss.on('connection', (ws) => {let clientType = null;ws.on('message', (data) => {const msg = JSON.parse(data.toString());if (msg.type === 'register') {clientType = msg.role;clients[clientType] = ws;ws.send(JSON.stringify({ type: 'connected', msg: `已作为${clientType}连接` }));startHeartbeat(ws);} else if (clientType === 'controller' && msg.type === 'control') {// 转发控制指令到展示端if (clients.display?.readyState === WebSocket.OPEN) {clients.display.send(JSON.stringify({ type: 'control', data: msg.data }));} else {ws.send(JSON.stringify({ type: 'error', msg: '展示端未连接' }));}}});ws.on('close', () => {if (clientType) clients[clientType] = null;});function startHeartbeat(ws) {const timer = setInterval(() => {if (ws.readyState === WebSocket.OPEN) {ws.send(JSON.stringify({ type: 'heartbeat' }));} else {clearInterval(timer);}}, HEARTBEAT_INTERVAL);}
});console.log('WebSocket服务器运行于 ws://localhost:8080');

2. 控制端(平板 Vue 应用)

使用 Vue3 的 ref 和 onMounted 管理连接状态,通过按钮发送控制指令,包含断线自动重连逻辑。

(1)创建控制端项目
npm create vite@latest controller -- --template vue
cd controller
npm install
(2)核心组件 src/App.vue
<template><div class="controller"><h1>平板控制端</h1><p class="status" :class="{ connected: isConnected }">状态:{{ statusText }}</p><div class="controls"><button @click="sendControl('showText', 'Hello 大屏!')">显示文本</button><button @click="sendControl('changeColor', randomColor)">切换背景色</button><button @click="sendControl('clear', null)">清空内容</button></div></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';// 状态管理
const ws = ref(null);
const isConnected = ref(false);
const statusText = ref('未连接');
const SERVER_URL = 'ws://localhost:8080';
const RECONNECT_DELAY = 3000; // 重连间隔3秒
let reconnectTimer = null;// 生成随机颜色
const randomColor = () => {return `#${Math.floor(Math.random() * 16777215).toString(16)}`;
};// 初始化WebSocket连接
const initWebSocket = () => {// 关闭现有连接if (ws.value) {ws.value.close();}statusText.value = '连接中...';ws.value = new WebSocket(SERVER_URL);// 连接成功ws.value.onopen = () => {isConnected.value = true;statusText.value = '已连接';// 注册为控制端ws.value.send(JSON.stringify({ type: 'register', role: 'controller' }));// 清除重连定时器if (reconnectTimer) clearTimeout(reconnectTimer);};// 接收服务器消息ws.value.onmessage = (event) => {const msg = JSON.parse(event.data);if (msg.type === 'error') {statusText.value = `错误:${msg.msg}`;}};// 连接关闭(触发重连)ws.value.onclose = () => {isConnected.value = false;statusText.value = '已断开,重连中...';// 延迟重连,避免频繁尝试reconnectTimer = setTimeout(initWebSocket, RECONNECT_DELAY);};// 连接错误ws.value.onerror = (err) => {console.error('WebSocket错误:', err);statusText.value = '连接错误';};
};// 发送控制指令
const sendControl = (action, data) => {if (ws.value?.readyState === WebSocket.OPEN) {ws.value.send(JSON.stringify({type: 'control',data: { action, payload: data }}));} else {statusText.value = '未连接,无法发送指令';}
};// 组件挂载时初始化连接
onMounted(initWebSocket);// 组件卸载时清理
onUnmounted(() => {if (ws.value) ws.value.close();if (reconnectTimer) clearTimeout(reconnectTimer);
});
</script><style scoped>
.controller {padding: 20px;text-align: center;
}
.status {font-size: 18px;margin: 20px 0;color: #ff4444;
}
.status.connected {color: #00C851;
}
.controls {display: flex;flex-direction: column;gap: 15px;margin-top: 30px;
}
button {padding: 15px 20px;font-size: 16px;cursor: pointer;background: #2196F3;color: white;border: none;border-radius: 8px;
}
button:hover {background: #0b7dda;
}
</style>
3. 展示端(大屏 Vue 应用)

接收控制端指令并执行对应操作(更新文本、切换样式等),同样包含断线重连逻辑。

(1)创建展示端项目
npm create vite@latest display -- --template vue
cd display
npm install
(2)核心组件 src/App.vue
<template><div class="display"><h1>大屏展示端</h1><p class="status" :class="{ connected: isConnected }">状态:{{ statusText }}</p><div class="display-area" :style="{ backgroundColor: bgColor }">{{ displayText }}</div></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';// 状态管理
const ws = ref(null);
const isConnected = ref(false);
const statusText = ref('未连接');
const displayText = ref('等待控制指令...');
const bgColor = ref('');
const SERVER_URL = 'ws://localhost:8080';
const RECONNECT_DELAY = 3000;
let reconnectTimer = null;// 初始化WebSocket连接
const initWebSocket = () => {if (ws.value) ws.value.close();statusText.value = '连接中...';ws.value = new WebSocket(SERVER_URL);ws.value.onopen = () => {isConnected.value = true;statusText.value = '已连接';ws.value.send(JSON.stringify({ type: 'register', role: 'display' }));if (reconnectTimer) clearTimeout(reconnectTimer);};// 接收控制指令并处理ws.value.onmessage = (event) => {const msg = JSON.parse(event.data);if (msg.type === 'control') {handleControl(msg.data);}};ws.value.onclose = () => {isConnected.value = false;statusText.value = '已断开,重连中...';reconnectTimer = setTimeout(initWebSocket, RECONNECT_DELAY);};ws.value.onerror = (err) => {console.error('WebSocket错误:', err);statusText.value = '连接错误';};
};// 处理控制指令
const handleControl = (data) => {switch (data.action) {case 'showText':displayText.value = data.payload;break;case 'changeColor':bgColor.value = data.payload;break;case 'clear':displayText.value = '已清空';bgColor.value = '';break;}
};onMounted(initWebSocket);
onUnmounted(() => {if (ws.value) ws.value.close();if (reconnectTimer) clearTimeout(reconnectTimer);
});
</script><style scoped>
.display {padding: 30px;text-align: center;
}
.status {font-size: 20px;margin: 20px 0;color: #ff4444;
}
.status.connected {color: #00C851;
}
.display-area {margin: 50px auto;padding: 60px 30px;width: 80%;min-height: 300px;border: 5px solid #333;border-radius: 10px;font-size: 36px;transition: all 0.3s ease;
}
</style>

核心特性说明

1. 响应式状态管理
  • 控制端 / 展示端均通过 Vue 的 ref 管理连接状态(isConnected)、状态文本(statusText)等,界面实时响应状态变化。
  • 展示端的 displayText 和 bgColor 与 DOM 绑定,接收指令后自动更新视图,体现 Vue 数据驱动的优势。
2. 断线重连机制
  • 自动重连:两端在 onclose 事件中触发重连逻辑,通过 setTimeout 实现 3 秒间隔重试,直到连接成功。
  • 连接清理:组件卸载时(onUnmounted)关闭 WebSocket 连接并清除重连定时器,避免内存泄漏。
  • 状态可视化:通过颜色区分连接状态(绿色 = 已连接,红色 = 未连接 / 错误),用户可直观感知。
3. 指令交互流程
  1. 控制端点击按钮 → 调用 sendControl 发送指令(包含 action 和 payload)。
  2. 服务器接收指令 → 转发给展示端。
  3. 展示端 onmessage 接收指令 → 调用 handleControl 执行对应操作(更新文本 / 颜色)。

运行方式

  1. 启动 WebSocket 服务器:
    node server.js
  2. 分别启动控制端和展示端:

    # 控制端
    cd controller
    npm run dev
    # 访问 http://localhost:5173(平板或浏览器模拟)# 展示端
    cd display
    npm run dev
    # 访问 http://localhost:5174(大屏或浏览器模拟)
  3. 操作控制端按钮,观察大屏是否同步响应;断开服务器再重启,测试重连功能。

扩展性优化

  • 多设备支持:修改服务器 clients 为数组,存储多个控制端 / 展示端,通过设备 ID 区分指令目标。
  • 指令加密:对传输的指令进行简单加密(如 Base64),防止恶意指令干扰。
  • 心跳响应:展示端 / 控制端收到心跳包后回复 heartbeat_ack,增强连接稳定性检测。

此方案充分利用 Vue3 的响应式和组件化特性,结合 WebSocket 实现了低延迟的跨设备联动,适合会议、展览等场景的实时控制需求。

http://www.dtcms.com/a/523543.html

相关文章:

  • 提高自己的网站网站 利润
  • 外贸seo软文发布平台上海百度推广优化排名
  • Qt 图像与定时器实战:实现动态图片轮播效果
  • C++ 模板初阶:从函数重载到泛型编程的优雅过渡
  • 第 01 天:Linux 是什么?内核、发行版及其生态系统
  • Docker 安装 MongoDB 完整指南:从入门到实战
  • Docker 离线安装
  • CUDA和cuDNN安装
  • 一篇初识什么是容器,引出 Docker
  • HTML 理论笔记
  • 《Linux系统编程之入门基础》【权限管理】
  • ELK(Elasticsearch + Logstash + Kibana + Filebeat)采集方案
  • 网站建设金手指排名霸屏主机类型wordpress
  • uniapp微信小程序简单表格展示
  • 【html】每日打卡页面
  • Server 15 ,VMware ESXi 实战指南:Ubuntu 20.04.6 版本虚拟机静态 IP 配置、分辨率固定及远程访问实践
  • 吴恩达深度学习课程一:神经网络和深度学习 第三周:浅层神经网络(三)
  • Copilot使用体验
  • uniapp video 加载完成后全屏播放
  • 从MongoDB到国产数据库:一场2TB电子证照系统的“平滑着陆”实践
  • 电子商务网站开发与建设试卷wordpress如何删除已安装主题
  • 内蒙古城乡建设网站免费详情页模板网站
  • Android EDLA开发认证说明和开发流程
  • DevExpress WPF中文教程:Data Grid - 如何使用虚拟源?(三)
  • UniApp缓存系统详解
  • 【LLM】用 FastAPI 搭建「OpenAI 兼容」DeepSeek-OCR 服务 + 简洁WebUI
  • 企业内部SRE/DevOps向精通Linux课程培训大纲
  • 《Effective Java》第13条:谨慎的覆盖clone
  • 第一章、React + TypeScript + Webpack项目构建
  • 前端:金丝雀部署(Canary Deployment)/ A、B部署 / 灰度部署