在Handlebars.js/express-handlebars局部模板中访问JavaScript变量
解决Express-Handlebars中无法访问页面上下文/脚本数据的问题
我太懂这种明明大部分配置都走通了,却卡在上下文访问上的憋屈感——咱们一步步拆解问题,看看哪里出了岔子:
1. 服务端传递的页面上下文无法在客户端脚本/模板里访问?
Handlebars是服务端渲染引擎,模板里的变量只在服务端编译阶段生效,客户端脚本默认拿不到这些数据。要让客户端能访问,得主动把上下文挂载到全局作用域里:
<!-- 在你的主模板(比如layout.hbs)中添加这段代码 --> <script> // 把服务端传递的上下文转成合法JS对象,挂载到window上 window.pageContext = { user: {{JSON.stringify user}}, pageMeta: {{JSON.stringify pageMeta}} }; </script>
之后你在页面脚本或者局部模板的客户端逻辑里,就能通过window.pageContext.user这类方式访问到服务端传递的数据了。
2. 页面脚本声明的JS数据无法在Handlebars模板中访问?
Handlebars编译模板的时候是在服务端运行的,客户端脚本里的变量(比如你写的const localData = { foo: 'bar' })是浏览器运行时才存在的,服务端根本看不到这些变量,直接在模板里用{{localData.foo}}肯定无效。
这种情况有两个解决方向:
- 如果数据能提前在服务端生成:把数据移到服务端渲染上下文里,不要在客户端脚本声明,直接从路由传过来。
- 如果必须在客户端生成数据:放弃用Handlebars渲染这部分内容,改用客户端JS动态修改DOM。比如先留个占位符:
再在脚本里填充内容:<div id="dynamic-placeholder"></div>const localData = { foo: 'bar' }; document.getElementById('dynamic-placeholder').textContent = localData.foo;
3. 局部模板(比如你的blag)无法访问页面全局上下文?
默认情况下express-handlebars的局部模板会继承父模板的上下文,但如果调用partial时没正确传递数据,就会出现访问不到的情况。正确的调用方式:
<!-- 直接调用,自动继承当前全局上下文 --> {{> blag}} <!-- 手动传递额外数据,同时保留全局上下文 --> {{> blag extraInfo=extraInfo}}
如果还是不行,检查下你的express-handlebars配置,确保partial的路径设置正确,没有限制上下文的传递。
4. 小心Handlebars的作用域陷阱
比如在{{#each}}循环里,上下文会切换成当前循环项,这时候要访问全局上下文的变量,得用../或者@root来指定:
{{#each articles}} <p>文章标题:{{title}},作者:{{../user.name}}</p> <!-- 用@root更清晰,避免多层嵌套时路径混乱 --> <p>文章标题:{{title}},作者:{{@root.user.name}}</p> {{/each}}
如果你的局部模板是在循环里调用的,别忘了用@root来定位全局上下文的变量。
内容的提问来源于stack exchange,提问作者apostrophedottilde
相关产品推荐
相关产品推荐

