html解析器仅负责标签转dom,不处理{{}}等模板语法;真正渲染模板需服务端引擎、构建时编译或运行时手动遍历文本节点替换。

HTML 本身不是模板引擎,也没有“HTML解析引擎”这个标准组件——浏览器原生只做 HTML 解析与渲染,不执行插值、不处理 {{ }}、不运行 {% if %}。所谓“用 HTML 解析引擎处理模板”,本质是混淆了「HTML 解析器」和「模板编译器」两个不同层级的工具。
浏览器内置 HTML 解析器不能渲染模板占位符
当你把 {{title}} 写进 <template></template> 或普通 <div> 里,浏览器会把它当纯文本保留,不会替换、不会报错、也不会执行。这是规范行为,不是 bug。
<p>常见错误现象包括:</p>
<ul>
<li>页面显示原始 <code>{{title}} 字符串,而不是实际值
innerHTML = templateString 后事件丢失、<input> 值被清空、<video></video> 播放中断根本原因:浏览器的 HTML 解析器只负责把标签转成 DOM 节点,它不关心你写了什么语法糖,也不提供数据绑定能力。
真正能处理模板的只有三类工具
必须明确区分使用场景,选错类型会导致功能失效或安全风险:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
-
服务端模板引擎(如 Jinja2、EJS、Go
html/template):在响应发出前就把{{user.name}}替换为字符串,返回纯 HTML。适合 SSR,天然防 XSS(默认转义) -
构建时预编译引擎(如 Handlebars +
html-loader):Webpack 构建阶段把.hbs编译成 JS 函数,运行时传入数据生成 HTML。不依赖全局Handlebars,但需配置esModule: false防路径误解析 -
运行时轻量方案(
<template></template>+cloneNode(true)+ 文本节点遍历):不引入任何库,手动查找并替换textContent中的{{key}},再挂载。必须避开属性值、事件处理器、<script></script>标签内部
用 DOMParser 解析 HTML 字符串时的坑
有人尝试用 new DOMParser().parseFromString(htmlStr, 'text/html') 来“解析模板”,这只能得到结构化 DOM,但依然不会执行任何模板逻辑。它只是把字符串变成可操作的节点树,{{title}} 仍以文本节点存在。
若硬要在此基础上做替换,注意:
- 别对整个
document.body.innerHTML做replace()—— 会破坏<script></script>、<style></style>、属性值里的合法大括号 - 只遍历
Text类型节点,在其textContent中匹配/{{\s*([^}]+)\s*}}/g,并做 HTML 实体转义后再赋值 -
DOMParser不处理自定义标签或指令(如v-if),也不能识别嵌套逻辑,{% for %}{% endfor %}必须靠 AST 解析,正则无法可靠实现
零依赖方案中容易被忽略的细节
用 <template id="item"><div>{{name}}</div></template> 开始写,看似简单,但真实项目里这几个点常被跳过:
- 克隆后必须调用
content.cloneNode(true),而不是innerHTML—— 否则<slot></slot>、<svg></svg>的命名空间信息丢失 - 用户输入内容(如
data.bio)必须用textContent赋值,绝不能用innerHTML,否则 XSS 风险直接落地 - 图片
src要校验协议:只允许https:、data:、/开头,防止javascript:alert(1)注入 - 每次切换视图前清空容器要用
container.replaceChildren()(现代 API)或container.textContent = '',而非innerHTML = ''—— 后者会触发重排且清空所有事件监听器










