You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用res.render渲染.hbs文件时无法正常展示HTML表格

问题:Express中res.render渲染Handlebars时HTML标签未被解析

在Express项目中,我拼接了HTML表格字符串,使用res.send()时可正常展示表格样式,但调用res.render()渲染form_process_title.hbs文件时,表格的HTML标签被直接显示而非解析成表格。我期望通过res.render实现正常的HTML表格展示,相关代码如下:

GET路由代码

app.get('/data/search/title', (req, res, next) => {
  res.render('form_process_title', { name: 'Form Title' });
});

form_process_title.hbs代码

<!DOCTYPE html>
<html lang="en">
<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>Document</title>
</head>
<body>
    <h1>Welcome to {{ name }} page</h1>
    <form method="POST" action="/form_route_title">
        <input type="text" name="title" placeholder="title">
        <input type="submit">
    </form>
    <p>{{ans}}</p>
</body>
</html>

POST路由代码

app.post('/form_route_title', function (req, res, next) {
  var ans = "<table border = 3>";
  ans += "<tr>";
  ans += "<td>" + "Title" + "</td>";
  ans += "<td>" + "ISBN" + "</td>";
  ans += "<td>" + "Description" + "</td>" + "</tr>";
  var count = 0;
  try {
    let data = JSON.parse(fs.readFileSync('myData.json'));
    for (var i = 0; i < data.length; i++) {
      if (data[i].title.includes(req.body.title)) {
        ans += "<tr>";
        count++;
        ans += "<td>" + data[i].title + "</td>";
        ans += "<td>" + data[i].isbn + "</td>";
        ans += "<td>" + data[i].shortDescription + "</td>";
        ans += "</tr>";
      }
    }
    ans += "</table>";
    console.log("Count = " + count);
    res.render('form_process_title', { name: 'Form Title', ans: ans });
  }
  catch {
    res.render('form_process_title', { name: 'Form Title', ans: "Sorry the data does not exist" });
  }
});

解决方案

问题原因

Handlebars模板引擎默认会对输出内容做HTML转义(防止XSS攻击),所以用{{ans}}输出时,HTML标签会被转成实体字符(比如<变成&lt;),导致浏览器把标签当成普通文本显示,而不是解析成表格。

两种解决方式

方式1:使用Handlebars三重大括号语法

直接在hbs模板里把{{ans}}改成{{{ans}}},三重大括号会告诉Handlebars跳过转义处理,直接输出原始HTML:

修改后的form_process_title.hbs关键代码:

<!-- 把原来的<p>{{ans}}</p>替换成下面的代码 -->
{{{ans}}}

注意:如果ans的内容包含用户输入,必须先做安全校验,避免注入恶意HTML代码引发XSS风险。

方式2:后端用SafeString包装HTML内容

在后端导入Handlebars的SafeString,把拼接好的HTML字符串用它包裹后再传给模板,这样Handlebars就不会转义该内容:

修改后的POST路由代码:

// 先导入SafeString
const { SafeString } = require('handlebars');

app.post('/form_route_title', function (req, res, next) {
  var ans = "<table border = 3>";
  ans += "<tr>";
  ans += "<td>" + "Title" + "</td>";
  ans += "<td>" + "ISBN" + "</td>";
  ans += "<td>" + "Description" + "</td>" + "</tr>";
  var count = 0;
  try {
    let data = JSON.parse(fs.readFileSync('myData.json'));
    for (var i = 0; i < data.length; i++) {
      if (data[i].title.includes(req.body.title)) {
        ans += "<tr>";
        count++;
        ans += "<td>" + data[i].title + "</td>";
        ans += "<td>" + data[i].isbn + "</td>";
        ans += "<td>" + data[i].shortDescription + "</td>";
        ans += "</tr>";
      }
    }
    ans += "</table>";
    console.log("Count = " + count);
    // 用SafeString包装ans
    res.render('form_process_title', { name: 'Form Title', ans: new SafeString(ans) });
  }
  catch {
    // 错误提示也可以用SafeString包装(纯文本不包装也没问题)
    res.render('form_process_title', { name: 'Form Title', ans: new SafeString("Sorry the data does not exist") });
  }
});

这种方式适合需要在后端统一处理安全校验的场景,确保传入模板的HTML内容是可信的。


内容的提问来源于stack exchange,提问作者user9115947

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 00:25:23