html模板无原生上下文传递机制,需依赖模板引擎或框架实现;go template中必须显式传入上下文如{{template "name" .}},否则子模板的.为nil;jsrender需用~访问context且不可穿透父data;纯html+js需手动注入数据并防范xss。

HTML 模板本身不提供原生的“上下文传递”机制,所谓上下文传递,本质是模板引擎(如 Go template、JsRender、Handlebars)或框架(如 React、Vue)在渲染时对 . 或 data 的作用域控制。纯 HTML + 原生 JS 无法自动继承父级数据,必须靠显式传入或手动注入。
Go template 中 {{template "name" .}} 是唯一可靠方式
Go 的 html/template 默认调用 {{template "header"}} 时,子模板的 . 是 nil —— 这不是 bug,是设计行为。你看到 {{.Title}} 渲染为空,就是因为没传上下文。
- 必须写成
{{template "header" .}},其中.表示当前模板的数据对象(比如map[string]interface{}) - 如果子模板需要局部变量,可用
{{template "item" $}}($指向最外层上下文),或{{template "item" (dict "item" . "index" $i)}}(需自定义函数) - 嵌套层级深时,避免反复解构:不要在子模板里写
{{$.User.Name}},而应在传入时扁平化结构,减少依赖链
JsRender 的 ~ 上下文访问语法必须配合 render(data, context)
JsRender 允许你在 render() 第二个参数中传入辅助对象,但模板内必须用 ~name 显式引用,否则 {{name}} 会去查 data 而非上下文。
- 调用时:
$.templates("#listTmpl").render(items, { format: formatDate, reverseSort: true }) - 模板内:
{{>~format(title)}}、{{if ~reverseSort}}...—— 漏掉~就查不到 -
~只能访问传入的 context 对象,不能穿透到父模板的 data;若需混合使用,得提前 merge:$.extend({}, data, context)
纯 HTML + 原生 JS 不存在自动上下文,只能手动注入
没有模板引擎时,“组件”只是字符串或 DOM 片段,innerHTML 或 insertAdjacentHTML 不带作用域。所谓“传递上下文”,其实是把数据序列化后塞进 HTML 字符串或 dataset 属性里。
- 安全做法:用
JSON.stringify()编码数据,再通过data-context注入:<div data-context='{"id":123,"name":"foo"}'></div> - 危险做法:拼接字符串模板(如
`<span>${obj.name}</span>`),易 XSS,且无法处理 undefined/null - DOM 级别复用:可封装一个
renderComponent(selector, data)函数,统一做 escape 和属性绑定,但仍是手动映射,不是真正的上下文继承
真正容易被忽略的点是:不同模板引擎对 . 的语义定义完全不同。Go template 的 . 是数据根,JsRender 的 . 是当前迭代项,Handlebars 的 this 可能是块级上下文——混用时务必确认当前引擎的文档,别凭直觉写 {{.}}。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











