HBS自定义isEmpty块助手嵌套{{#each}}无法渲染问题求助
问题:Handlebars自定义isEmpty助手嵌套{{#each}}无法渲染数据
场景说明
我搭建了一个简单的表单输入页面,提交表单后,表单数据会以条目形式展示。
相关代码
路由代码(Express)
const express = require('express'); const router = express.Router(); const view = 'users'; const data = []; const croute = '/users'; router .route(croute) .get((req, res) => res.render(view, { udat: data })) .post((req, res) => { const {name, age} = req.body; data.push({name, age}); console.log(data); res.redirect(croute); }); module.exports = router;
HBS视图代码
<form action="/users" method="POST"> <div> <label> Name: <input type="text" name="name" required/> </label> </div> <div> <label> Age: <input type="number" name="age" required/> </label> </div> <div> <button type="submit"> Submit </button> </div> </form> {{#isEmpty udat}} <h4> There are no users yet. Add Some. </h4> {{else}} <table> <thead> <tr> <td> No. </td> <td>Name</td> <td>Age</td> </tr> </thead> <tbody> {{#each udat}} <tr> <td>{{@index}}</td> <td>{{name}}</td> <td>{{age}}</td> </tr> {{/each}} </tbody> </table> {{/isEmpty}}
自定义Handlebars块助手代码
hbs.registerHelper('isEmpty', (arg, options) => { return arg.length <= 0 ? options.fn(this) : options.inverse(this); });
问题现象
- 无用户数据时,
isEmpty助手的首个分支(提示无用户)能正常渲染; - 提交数据后,
<thead>部分正常显示,但{{#each}}循环无法渲染用户条目; - 直接使用
{{#each}}而不嵌套在isEmpty助手内时,能正常展示所有条目。
解决方案
问题出在自定义助手的上下文传递上:调用options.fn(this)和options.inverse(this)时,传递的this是助手自身的上下文,而非模板的原始根上下文,导致{{#each}}无法访问到udat变量。
修改自定义助手代码,通过options.data.root传递模板根上下文:
hbs.registerHelper('isEmpty', (arg, options) => { return arg.length <= 0 ? options.fn(options.data.root) : options.inverse(options.data.root); });
原理说明
Handlebars中,options.data.root指向渲染模板时传入的根上下文对象(即本场景中的{ udat: data })。原代码传递的this是助手内部的上下文,嵌套的{{#each}}无法从中获取到udat,因此循环不执行。修改后,嵌套模板能直接访问根上下文里的变量,{{#each}}即可正常渲染数据。
内容的提问来源于stack exchange,提问作者Caleb Jawa Hkun
相关产品推荐
相关产品推荐

