Handlebars 的模板语法在编译期确定,运行期拼出来的字符串不会被当成变量名解析。期望用 {{result[0]}} 这类写法按索引取变量,模板只会把它当成一条普通路径,输出为空或原样保留。

能做的一件事:lookup
{{lookup this fieldName}}
const html = template({ fieldName: 'title', title: '示例标题' });
lookup 接收对象与键名,适合字段名来自变量、层级只有一层的场景。嵌套路径与表达式拼接仍然不支持。
更通用的做法:在 JS 层预处理
const keys = ['title', 'author', 'date'];
const data = {
rows: list.map((row) => ({
cells: keys.map((key) => ({ key, value: row[key] ?? '' }))
}))
};
const html = template(data);
{{#each rows}}
<tr>
{{#each cells}}
<td data-field="{{key}}">{{value}}</td>
{{/each}}
</tr>
{{/each}}
把「按变量名取值」转成「按键取值后一起传进模板」,模板里只剩遍历与输出,不再依赖运行期解析。列顺序、字段白名单、缺省值都在 JS 层控制。
三个注意点
- 不要用 eval 或 new Function 拼表达式。模板层没有这类能力,硬加会引入注入风险。
- 预处理时定白名单。字段名来自外部输入时先与白名单求交集,避免把内部字段渲染出去。
- 转义交给模板。取值后由
{{value}}做 HTML 转义,需要原样输出时用三个大括号并确认来源可信。
取舍
字段固定的表格直接用点路径最省事;字段名由配置或后端下发的场景,走 JS 层预处理。定下这一条之后,模板不需要为动态取值再引入自定义 helper。
