ESP32使用ESPAsyncWebServer时如何传递变量值到网页显示
问题根因
直接调用request->send()发送存储在PROGMEM的静态HTML字符串时,ESPAsyncWebServer不会自动替换你写的%data%占位符,所以占位符会被当做普通文本原样输出。
解决方案
方案1:使用内置模板替换(改动最小,适合静态页面加载时一次性渲染变量)
ESPAsyncWebServer自带模板替换能力,只需要两步修改:
- 编写占位符匹配回调,匹配到对应占位符时返回要替换的变量值
- 根路由改用
send_P方法发送PROGMEM中的HTML,传入替换回调作为参数
修改后的完整代码:
String data = "text"; // 占位符替换回调 String templateProcessor(const String& placeholderName) { if (placeholderName == "data") { return data; } // 未匹配到的占位符返回空字符串即可 return String(); } const char index_html[] PROGMEM = R"rawliteral( <!DOCTYPE HTML><html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <p>%data%</p> </body> </html>)rawliteral"; void setupServer() { server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ // 注意:发送PROGMEM内容使用send_P,最后一个参数传入替换回调 request->send_P(200, "text/html", index_html, templateProcessor); }); server.on("/data", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(200, "text/plain", data); }); server.begin(); }
如果需要替换多个变量,直接在templateProcessor函数里新增对应变量名的判断分支即可。
方案2:前端异步拉取数据(适合动态数据频繁更新场景)
如果data值会频繁变动,不需要每次刷新整个页面才能更新值,可以保留你已经写好的/data接口,在前端通过JS异步拉取数据渲染,不需要做服务端模板替换:
// 服务端根路由不需要额外加回调,直接发送页面即可 const char index_html[] PROGMEM = R"rawliteral( <!DOCTYPE HTML><html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <p id="dataContainer"></p> <script> // 页面加载完成后拉取数据 async function fetchData() { const res = await fetch('/data'); const val = await res.text(); document.getElementById('dataContainer').textContent = val; } fetchData(); // 需要实时更新的话,打开下面的注释,每秒自动拉取一次最新值 // setInterval(fetchData, 1000); </script> </body> </html>)rawliteral"; server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/html", index_html); });
注意事项
- 存储在PROGMEM的网页内容必须用
send_P方法发送,不要直接用send,否则可能出现内存访问异常、替换不生效的问题 - 模板回调里判断的是
%包裹的占位符名称,判断逻辑里不需要带%符号 - 如果变量值包含HTML特殊字符,模板替换逻辑会自动做转义,不需要手动处理
内容的提问来源于stack exchange,提问作者Atropin
相关产品推荐
相关产品推荐

