孝感市网站建设_网站建设公司_一站式建站_seo优化
2026/1/9 23:54:19 网站建设 项目流程

图示:

在Nodejs中的写法:

websocket.js:

const WebSocket = require("ws"); // 创建全局 WebSocket 服务器实例 let wss = null; let vueClients = new Set(); // 初始化 WebSocket 服务器 function initWebSocket(server) { if (!wss) { wss = new WebSocket.Server({ server }); // WebSocket 连接处理 wss.on("connection", (ws) => { console.log("Vue客户端已连接"); vueClients.add(ws); ws.on("close", () => { vueClients.delete(ws); }); ws.on("error", (error) => { console.error("Vue客户端错误:", error); }); // 发送消息给客户端说"注意了!" 使用json格式 ws.send(JSON.stringify({ type: "notice", message: "注意了!" })); }); } return wss; } // 获取 WebSocket 服务器实例 function getWebSocketServer() { return wss; } // 获取 Vue 客户端集合 function getVueClients() { return vueClients; } module.exports = { initWebSocket, getWebSocketServer, getVueClients };

app.js

const express = require("express"); const http = require("http"); const app = express(); const { db } = require("./config/database"); //连接数据库 // 创建HTTP服务器 const server = http.createServer(app); // 引入websocket.js const { initWebSocket } = require("./websocket"); // 初始化WebSocket服务器 initWebSocket(server); .....省略 server.listen(8060, () => { console.log("✅ 服务器已启动:http://localhost:8060"); console.log("✅ WebSocket 已启用:ws://localhost:8060"); console.log(`📝 白名单配置:`); publicPaths.forEach((path) => { console.log(` - ${path}`); }); });

在使用的接口中引入websocket服务器,并写入数据:

aritcle.js:

const WebSocket = require("ws"); const { getVueClients } = require("../../websocket"); ...省略 // 修改文章信息接口 router.put("/:id", (req, res) => { const { id } = req.params; // 使用getVueClients获取所有Vue客户端 const vueClients = getVueClients(); // 发送消息“数据修改了” vueClients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(JSON.stringify({ type: "notice", message: "数据修改了" })); } }); console.log("===id="+id); console.log(`文章 ${id} 已更新`); res.json({ success: true, code: 20000, message: "文章更新成功", data: '', }); }); module.exports = router;

解释:

这个时候看客户端Vue:

<template> <div class="app-container"> <div class="filter-container"> <el-button class="filter-item" type="primary" icon="el-icon-refresh" @click="fetchData"> 刷新 </el-button> </div> <el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%;"> <el-table-column label="ID" prop="id" align="center" width="80"> <template slot-scope="{row}"> <span>{{ row.id }}</span> </template> </el-table-column> <el-table-column label="标题" min-width="200"> <template slot-scope="{row}"> <span class="link-type" @click="handleView(row)">{{ row.title }}</span> </template> </el-table-column> <el-table-column label="内容" min-width="300"> <template slot-scope="{row}"> <span>{{ row.content }}</span> </template> </el-table-column> <el-table-column label="更新时间" width="180" align="center"> <template slot-scope="{row}"> <span>{{ row.updatedAt | parseTime('{y}-{m}-{d} {h}:{i}') }}</span> </template> </el-table-column> <el-table-column label="操作" align="center" width="120" class-name="small-padding fixed-width"> <template slot-scope="{row}"> <el-button type="primary" size="mini" @click="handleView(row)"> 查看 </el-button> <el-button type="primary" size="mini" @click="handleUpdate(row)"> 修改 </el-button> </template> </el-table-column> </el-table> <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> <el-form ref="dataForm" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;"> <el-form-item label="ID"> <span>{{ temp.id }}</span> </el-form-item> <el-form-item label="标题"> <span>{{ temp.title }}</span> </el-form-item> <el-form-item label="内容"> <span>{{ temp.content }}</span> </el-form-item> <el-form-item label="更新时间"> <span>{{ temp.updatedAt | parseTime('{y}-{m}-{d} {h}:{i}:{s}') }}</span> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogFormVisible = false">关闭</el-button> </div> </el-dialog> </div> </template> <script> import { fetchArticles, updateArticle } from '@/api/article' export default { name: 'Ac24Index', filters: { parseTime(time, cFormat) { if (!time) return '' const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' let date if (typeof time === 'object') { date = time } else { if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { time = parseInt(time) } if ((typeof time === 'number') && (time.toString().length === 10)) { time = time * 1000 } date = new Date(time) } const formatObj = { y: date.getFullYear(), m: date.getMonth() + 1, d: date.getDate(), h: date.getHours(), i: date.getMinutes(), s: date.getSeconds(), a: date.getDay() } const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { let value = formatObj[key] if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } if (result.length > 0 && value < 10) { value = '0' + value } return value || 0 }) return time_str } }, data() { return { list: null, listLoading: true, dialogFormVisible: false, dialogStatus: '', textMap: { view: '查看文章' }, temp: { id: undefined, title: '', content: '', updatedAt: '' }, ws: null } }, created() { this.fetchData() this.initWebSocket() }, methods: { fetchData() { this.listLoading = true fetchArticles().then(response => { if (response.success) { this.list = response.data.items console.log("===this.list==") } else { console.log("===this.list no data==") this.$message({ message: '获取数据失败', type: 'error', duration: 5 * 1000 }) } this.listLoading = false }).catch(error => { console.error('API调用失败:', error) this.listLoading = false this.$message({ message: 'API调用失败,请检查网络连接', type: 'error', duration: 5 * 1000 }) }) }, // 初始化 WebSocket 连接 initWebSocket() { const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; this.ws = new WebSocket(`${protocol}//localhost:8060`); this.ws.onopen = () => { console.log("WebSocket 连接已建立"); }; this.ws.onmessage = (event) => { const message = JSON.parse(event.data); console.log("===message==") console.log(message) }; this.ws.onerror = (error) => { console.error("WebSocket 错误:", error); }; this.ws.onclose = () => { console.log("WebSocket 连接关闭,尝试重连..."); setTimeout(this.initWebSocket, 3000); }; }, handleView(row) { this.temp = Object.assign({}, row) this.dialogStatus = 'view' this.dialogFormVisible = true this.$nextTick(() => { this.$refs['dataForm'].clearValidate() }) }, handleUpdate(row) { // 调用updateArticle方法 updateArticle(row.id).then(response => { if (response.success) { this.$message({ message: '修改成功', type: 'success', duration: 5 * 1000 }) } else { this.$message({ message: '修改失败', type: 'error', duration: 5 * 1000 }) } }).catch(error => { console.error('API调用失败:', error) this.$message({ message: 'API调用失败,请检查网络连接', type: 'error', duration: 5 * 1000 }) }) }, } } </script> <style scoped> .app-container { padding: 20px; } .filter-container { padding-bottom: 10px; } .link-type { color: #1890ff; cursor: pointer; } .link-type:hover { color: #40a9ff; text-decoration: underline; } </style>

解释:

最终展示:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询