把这个绑在车把按钮上

Bind this to a handlebars button

本文关键字:按钮      更新时间:2023-09-26

所以我得到了一个很大的JSON,其中有许多项嵌套在主题中,我使用splash.js从每个主题中制作一个按钮。现在,我想将对子对象的引用绑定到每个按钮中,这样它的onClick()就不必执行大量查找,也不必将大量数据粘贴到按钮的事件中。

这可以用胡子或其他模板语言完成吗?

JSON:

myJson={
   "topics": [
   {
       "name":"topic 1",
       "id":1,
       "items":[
           "name":"a great item",
           "data": {...}
       ]
   },
   ...
}

模板:

{{#topics}}
     <button onClick="_.bind(browseToTopic,{{this}})">{{name}}</button>
{{/topics}} 

上周我在尝试将事件绑定到"事物"列表时遇到了类似的问题。我的哲学斗争使我得出了关于Mustache(和Handlebars)的无逻辑性质的答案:https://stackoverflow.com/a/4946409/365252

需要注意的是,Mustache在设计上没有逻辑。这试图实现的是加剧激励开发人员将逻辑与演示分离,即任何使您的演示标记"跳舞"或链接到无法单独用标记表达的"事物"的东西都应该远离您的模板。

但回到我们的问题。。。当我意识到我的问题不是"如何将其与标记绑定"时,我才意识到真正的尤里卡时刻。

我真正的问题是:"循环和循环的项目之间显然涉及逻辑。为什么我要使用Mustache在一个没有逻辑的环境中迭代它们?"

因此,在拐弯抹角几分钟后,你可能会想知道我的解决方案是什么:

这是我虚构的模板:

<h1>Argh these pesky topics!</h1>
{{{#topics}}} <!-- Note the 3 mustaches to avoid html escaping -->

这是我的行模板:

<button>Shiver me timber, I'm rusty ol' {{name}}</button>

然后所有逻辑与旧的Javascript:

/* Important: Assuming you're using jQuery, if not you'll have to convert the render output from a string to a DOM Node first. jQuery is NOT necessary for this to work - I'm just trying to avoid innerHTML hacks */
var topics = [/* whatever topics are,*/],
    topicsDOM = document.createDocumentFragment(),
    $ = jQuery,
    list,
    i, t, row;
for (i = 0, t = topics.length; i < t; i++) {
    row = $(Mustache.render(yourRowTemplate, topics[i]));
    row.on('click', function () {
        /* We know exactly what row this is via topics[i] so you can do anything you'd like here */
    };
    topicsDOM.appendChild(row);
}
/* Now... this bit I'm not very proud of and I'm hoping someone can point out a better solution */
list = $(Mustache.render(yourListTemplate, {
           topics: '<ins class="no-collision-please">'}));
/* We're doing this because we want to preserve the decorated DOM Nodes,
   Mustache expects plain markup as a string (our <ins>) */
list.find('ins.no-collision-please').replaceWith(topicsDOM);
/* Note that the <ins> never leaves our little sandbox nor does
   it cause reflow/layouting since we're working inside a documentFragment (list) */
return list;

最后,在吞下所有这些Kool Aid后,明显的回味是:我必须这样做才能绑定事件,我宁愿在我的模板中放一个<script>标签

如果您问过自己这个问题,那么无逻辑的模板可能不适合您。

免责声明:我使用Handlebars/Mustache不到一个月了,我仍然发现自己在某些用例中会问上面的问题。这不是银弹。

我发现(在车把中,但可能也适用于Mustache)这样做的方法如下:

  • 创建一个以JSON(字符串化)形式返回this对象的助手
  • 创建一个函数,解析JSON并返回对象
  • 从模板中调用该函数

代码:

Handlebars.registerHelper('getThis', function() {
    return JSON.stringify(this);
});
browseToTopic = function(obj){
    console.log(JSON.parse(obj));
    // do other stuff..
}

HTML/模板:

{{#topics}}
  <button onClick="_.bind(browseToTopic,{{getThis}})">{{name}}</button>
{{/topics}}

请参阅此处的示例(名称不同,操作相同):http://jsfiddle.net/awhb772m/

更新:添加了一个与初始代码更相似的示例:http://jsfiddle.net/fbL7xjet/

请考虑:

1) 您的对象格式不正确。以下部分:

 "items":[
       "name":"a great item",
       "data": {...}
   ]

应该是:

 "items":[
     {
       "name":"a great item",
       "data": {...}
     }
   ]

2) 我编写的代码只是一个概念验证,您可能想要改进getThis帮助程序来转义字符串化的JSON;

3) 您将在browseToTopic函数中找到的this对象不是原始上下文的1:1副本,但它已转换为JSON,然后再次转换为对象。这意味着目标对象将缺少所有非基元对象(例如函数)。考虑一下这是否足以满足您的需求。