如何通过href或其他方式在Handlebars模板间传递上下文数据?
咱们分两种常见场景来解决这个问题——一种是同一页面内渲染单个卡片(比如点击列表项展开详情),另一种是跳转新页面渲染单个卡片(通过href跳转),每种场景都有对应的实用处理方式:
场景1:同一页面内渲染(直接调用Partial)
如果你的card-single.html是作为局部模板在当前页面渲染(比如点击列表卡片后弹出详情面板),这是最直接的处理方式:在cards-list.html里调用card-single模板时,直接把当前循环的卡片上下文传递过去。
示例代码
在cards-list.html中:
{{#each cards}} <div class="card-item" onclick="toggleSingleCard(this)"> <!-- 列表卡片的展示内容 --> <h3>{{title}}</h3> <p>{{excerpt}}</p> <!-- 调用单个卡片模板,传递当前卡片的完整上下文 --> {{> card-single this}} </div> {{/each}}
这里的this就代表当前循环到的卡片对象,会直接把整个上下文传给card-single.html模板,你在单个卡片模板里可以直接用{{title}}、{{content}}、{{author}}等变量。如果需要控制显示隐藏,给card-single的容器加个默认隐藏的类,点击时切换类名即可。
场景2:通过href跳转新页面渲染
如果要跳转到独立的card-single.html页面,需要把卡片数据传递过去,常见两种实现方式:
方式1:URL参数传递关键信息
把卡片的唯一标识(比如ID)拼到href里,在目标页面通过ID从数据源(全局数组、后端接口)中获取完整数据再渲染:
在cards-list.html中:
{{#each cards}} <a href="/card-single.html?cardId={{id}}" class="card-link"> <h3>{{title}}</h3> <p>{{excerpt}}</p> </a> {{/each}}
然后在card-single.html的JS中处理:
// 解析URL中的cardId参数 const urlParams = new URLSearchParams(window.location.search); const targetCardId = urlParams.get('cardId'); // 假设你有全局的卡片数据源数组 const targetCard = window.cardsList.find(card => card.id === targetCardId); // 编译并渲染单个卡片模板 const template = Handlebars.compile(document.getElementById('card-single-tpl').innerHTML); document.getElementById('card-container').innerHTML = template(targetCard);
方式2:本地存储传递完整数据
如果卡片数据结构复杂、字段多,不适合拼URL,可以用sessionStorage临时存储完整数据:
首先在Handlebars中注册一个转JSON的辅助函数,用来把卡片对象转成字符串:
Handlebars.registerHelper('jsonStringify', function(obj) { return JSON.stringify(obj); });
然后在cards-list.html中添加点击事件存储数据:
{{#each cards}} <a href="/card-single.html" onclick="saveCardData({{jsonStringify this}})" class="card-link"> <h3>{{title}}</h3> <p>{{excerpt}}</p> </a> {{/each}}
对应的JS存储逻辑:
function saveCardData(cardData) { // 把卡片数据存在sessionStorage,仅当前会话有效 sessionStorage.setItem('currentCard', JSON.stringify(cardData)); }
最后在card-single.html中读取并渲染:
const cardData = JSON.parse(sessionStorage.getItem('currentCard')); // 渲染模板逻辑和上面一致 const template = Handlebars.compile(document.getElementById('card-single-tpl').innerHTML); document.getElementById('card-container').innerHTML = template(cardData); // 用完及时清除,避免残留数据 sessionStorage.removeItem('currentCard');
额外提示
如果是服务端渲染场景(比如Node.js + Handlebars),可以直接通过路由传递ID,服务端查询到完整卡片数据后,直接把上下文传给card-single模板渲染,不需要前端做额外处理;另外,用URL传递敏感数据要注意安全性,敏感内容建议通过后端接口查询。
内容的提问来源于stack exchange,提问作者AmintaCode

