Node-RED Dashboard V3.6.2:自定义UI节点收消息后如何更新HTML?
Node-RED自定义UI节点动态更新仪表盘内容的解决方案
首先明确:不能直接在node.on('input')回调里修改addWidget的format参数,因为addWidget是节点初始化时执行的一次性操作,后续无法直接修改已注册组件的format属性。正确的做法是利用Node-RED Dashboard的消息传递机制和模板渲染能力来实现动态更新。
先修正你代码里的基础错误
- 节点构造函数里的
node.on('input')要改成this.on('input'),this才是当前节点的实例引用 RED.nodes.registerType('ui_node',FirstNode)里的FirstNode是笔误,应该改成nodeaddWidget的format属性后面的分号要改成逗号,符合对象语法
方案一:动态更新数据(推荐,适合速度表这类实时刷新数值的场景)
通过beforeEmit属性把消息里的数值传递到前端模板,前端用模板语法绑定数据。
示例代码:
module.exports = function(RED) { // 生成带模板占位符的HTML function html(config) { return String.raw` <div class="speed-container"> <p>当前速度:</p> <p class="speed-value">{{msg.payload}} km/h</p> </div> `; } function SpeedNode(config) { var ui = RED.require("node-red-dashboard")(RED); RED.nodes.createNode(this, config); const node = this; var done = ui.addWidget({ node: node, format: html(config), templateScope: "local", // 确保每个节点实例独立 group: config.group, width: config.width || 3, height: config.height || 2, beforeEmit: function(msg, value) { // 在这里预处理消息数据,传递给前端模板 return { msg: msg }; } }); // 监听输入消息 node.on('input', function(msg) { // 确保msg.payload是速度数值,可在此做格式转换 // msg.payload = parseFloat(msg.payload); node.send(msg); // 把消息传递给前端模板 }); // 节点关闭时清理资源 node.on('close', function() { done(); }); } RED.nodes.registerType('ui-speed-gauge', SpeedNode); }
方案二:完全替换HTML内容(适合需要动态改变结构的场景)
如果需要根据消息完全替换HTML代码,可以在消息里传递HTML字符串,前端用三重大括号{{{...}}}避免HTML转义。
示例代码:
module.exports = function(RED) { // 初始化基础模板,留空占位 function html(config) { return String.raw`{{{msg.dynamicHtml}}}`; } function DynamicHtmlNode(config) { var ui = RED.require("node-red-dashboard")(RED); RED.nodes.createNode(this, config); const node = this; var done = ui.addWidget({ node: node, format: html(config), templateScope: "local", group: config.group, width: config.width || 6, height: config.height || 4 }); node.on('input', function(msg) { // 根据消息内容生成新的HTML const speed = msg.payload; let htmlContent = ''; if (speed < 60) { htmlContent = `<div class="safe-speed"><p>当前速度: ${speed} km/h</p><p>安全</p></div>`; } else { htmlContent = `<div class="warn-speed"><p>当前速度: ${speed} km/h</p><p>超速警告</p></div>`; } // 将生成的HTML放到消息的自定义字段中 msg.dynamicHtml = htmlContent; node.send(msg); }); node.on('close', function() { done(); }); } RED.nodes.registerType('ui-dynamic-html', DynamicHtmlNode); }
关键说明
beforeEmit是Dashboard提供的钩子函数,用于在消息发送到前端前处理数据,可修改msg内容或添加自定义字段供模板使用。- 模板里的
{{msg.xxx}}是Mustache语法,用于渲染动态数据;三重大括号{{{msg.xxx}}}会直接渲染HTML内容,不转义。 - 设
templateScope为local可避免多个节点实例之间的数据干扰。
内容的提问来源于stack exchange,提问作者user24151662
相关产品推荐
相关产品推荐

