如何实现关联Oracle数据库的DOM表格数据动态无刷新更新?
实现前端表格无刷新动态更新的方案
下面是几种可行的实现方案,从快速改造到高效实时场景都有覆盖:
方案一:定时Fetch轮询(快速改造现有代码)
这是门槛最低的方案,不需要大幅改动现有架构,通过定时调用API获取最新数据,对比后更新表格。
改造步骤:
- 先移除页面自动刷新的
<meta http-equiv="refresh" content="5"> - 把数据获取逻辑封装成独立函数,用
setInterval定时执行 - 记录最后一次获取的最新数据标识(比如时间、唯一ID),只新增变化的数据,避免重复渲染整个表格
修改后的前端代码示例:
<!DOCTYPE html> <html lang="pt-br"> <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>Apontamentos da Produção</title> <link rel="stylesheet" type="text/css" href="styles.css" media="screen" /> </head> <body> <div id="data"></div> <div class="grid-container"> <div class="container"> <div class="texto"> PAINEL-1 | APONTAMENTOS DA PRODUÇÃO</div> <div class="clock"></div> </div> </div> <br> <table id="table" class="tablePrincipal"> <tr class="trPrincipal"> <th class="th2" style="width: 11%;">Data</th> <th class="th2" style="width: 8%; ">Hora</th> <th class="th2" style="width: 5%;">Orig.</th> <th class="th2" style="width: 8%;">O.P.</th> <th class="th2" style="width: 10%;">Produto</th> <th class="th2" style="width: 8%;">Deriv.</th> <th class="th2" style="width: 9%;">Peso (TN)</th> <th class="th2" style="width: 7%;">Refugo (TN)</th> <th class="th2" style="width: 13%;">Lote</th> <th class="th2" style="width: 60%;">Operador</th> </tr> </table> <script> let lastLatestTime = null; // 记录最后一条数据的时间,用来判断是否有新增 const table = document.getElementById('table'); // 封装数据获取与更新逻辑 async function updateTable() { try { const response = await fetch('http://localhost:3000/teste'); const data = await response.json(); if (!data.length) return; // 假设返回的第一条数据是最新的,取Hora列作为时间标识(可换成唯一ID) const currentLatestTime = data[0][1]; if (!lastLatestTime) { // 首次加载:清空现有行(除表头),渲染前7条数据 while (table.rows.length > 1) { table.deleteRow(1); } for (let i = 0; i < Math.min(7, data.length); i++) { addRow(data[i]); } } else if (currentLatestTime !== lastLatestTime) { // 有新数据:插入到表格顶部,保持最多7行 addRow(data[0], true); if (table.rows.length > 8) { table.deleteRow(table.rows.length - 1); } } lastLatestTime = currentLatestTime; } catch (error) { console.error('更新表格失败:', error); } } // 新增行到表格的工具函数 function addRow(rowData, insertAtTop = false) { const row = table.insertRow(insertAtTop ? 1 : table.rows.length); const cells = []; for (let i = 0; i < 10; i++) { cells.push(row.insertCell(i)); } cells[0].innerHTML = rowData[0]; cells[1].innerHTML = rowData[1]; cells[2].innerHTML = rowData[2]; cells[3].innerHTML = rowData[3]; cells[4].innerHTML = rowData[4]; cells[5].innerHTML = rowData[5]; cells[6].innerHTML = rowData[6]; cells[7].innerHTML = rowData[7]; cells[8].innerHTML = rowData[8]; cells[9].innerHTML = rowData[9]; } // 页面初始化+定时更新 window.onload = function() { updateTable(); setInterval(updateTable, 5000); // 每5秒查询一次,可根据需求调整间隔 }; </script> </body> </html>
方案二:WebSocket实时推送(低延迟实时更新)
如果需要更低延迟的实时效果,推荐用WebSocket。后端在数据库有新数据入库时,主动推送给前端,前端接收消息后直接更新表格。
后端(Node.js)示例:
先安装ws库:npm install ws
const express = require('express'); const WebSocket = require('ws'); const app = express(); const server = require('http').createServer(app); const wss = new WebSocket.Server({ server }); // 替换成你的Oracle查询函数,获取最新一条入库数据 async function getLatestProductionData() { // 这里写你的Oracle查询逻辑 const latestData = await yourOracleQueryMethod(); return latestData; } // 监听WebSocket连接 wss.on('connection', (ws) => { console.log('客户端已连接'); // 定时检查数据库新数据(也可以改成数据库插入触发器触发推送) const checkInterval = setInterval(async () => { const latestData = await getLatestProductionData(); if (latestData) { ws.send(JSON.stringify(latestData)); } }, 2000); // 每2秒检查一次,可调整 ws.on('close', () => { console.log('客户端断开连接'); clearInterval(checkInterval); }); }); server.listen(3000, () => { console.log('服务器运行在端口3000'); });
前端修改示例:
const table = document.getElementById('table'); let ws; function initWebSocket() { ws = new WebSocket('ws://localhost:3000'); ws.onopen = () => console.log('WebSocket连接成功'); ws.onmessage = (event) => { const newData = JSON.parse(event.data); // 插入新数据到表格顶部 addRow(newData, true); // 保持最多7行数据 if (table.rows.length > 8) { table.deleteRow(table.rows.length - 1); } }; ws.onerror = (error) => console.error('WebSocket错误:', error); ws.onclose = () => { console.log('连接断开,3秒后重连'); setTimeout(initWebSocket, 3000); }; } // 复用方案一中的addRow函数 function addRow(rowData, insertAtTop = false) { const row = table.insertRow(insertAtTop ? 1 : table.rows.length); const cells = []; for (let i = 0; i < 10; i++) { cells.push(row.insertCell(i)); } cells[0].innerHTML = rowData[0]; cells[1].innerHTML = rowData[1]; cells[2].innerHTML = rowData[2]; cells[3].innerHTML = rowData[3]; cells[4].innerHTML = rowData[4]; cells[5].innerHTML = rowData[5]; cells[6].innerHTML = rowData[6]; cells[7].innerHTML = rowData[7]; cells[8].innerHTML = rowData[8]; cells[9].innerHTML = rowData[9]; } window.onload = initWebSocket;
方案三:Server-Sent Events (SSE)(单向推送,实现简单)
SSE是HTTP协议的扩展,适合后端单向向前端推送数据,无需额外WebSocket库,实现成本低。
后端(Node.js)示例:
const express = require('express'); const app = express(); app.get('/sse', async (req, res) => { // 设置SSE响应头 res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); // 发送最新数据的函数 const sendLatestData = async () => { const latestData = await yourOracleQueryMethod(); // 查询最新数据 if (latestData) { res.write(`data: ${JSON.stringify(latestData)}\n\n`); } }; // 首次发送数据 await sendLatestData(); // 定时推送新数据 const interval = setInterval(sendLatestData, 2000); // 客户端断开时清理定时器 req.on('close', () => { clearInterval(interval); res.end(); }); }); app.listen(3000, () => { console.log('服务器运行在端口3000'); });
前端修改示例:
const table = document.getElementById('table'); function initSSE() { const eventSource = new EventSource('http://localhost:3000/sse'); eventSource.onmessage = (event) => { const newData = JSON.parse(event.data); addRow(newData, true); if (table.rows.length > 8) { table.deleteRow(table.rows.length - 1); } }; eventSource.onerror = (error) => { console.error('SSE错误:', error); eventSource.close(); setTimeout(initSSE, 3000); // 断开后自动重连 }; } // 复用addRow函数 function addRow(rowData, insertAtTop = false) { const row = table.insertRow(insertAtTop ? 1 : table.rows.length); const cells = []; for (let i = 0; i < 10; i++) { cells.push(row.insertCell(i)); } cells[0].innerHTML = rowData[0]; cells[1].innerHTML = rowData[1]; cells[2].innerHTML = rowData[2]; cells[3].innerHTML = rowData[3]; cells[4].innerHTML = rowData[4]; cells[5].innerHTML = rowData[5]; cells[6].innerHTML = rowData[6]; cells[7].innerHTML = rowData[7]; cells[8].innerHTML = rowData[8]; cells[9].innerHTML = rowData[9]; } window.onload = initSSE;
内容的提问来源于stack exchange,提问作者Jean Zacarchuka
相关产品推荐
相关产品推荐

