将其绑定到车把按钮

时间:2014-09-27 21:37:07

标签: javascript underscore.js handlebars.js mustache

所以我得到了一个大型JSON,其中包含许多嵌入主题的项目,我使用mustache.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}} 

2 个答案:

答案 0 :(得分:1)

上周我尝试将事件绑定到“事物”列表时遇到了类似的问题。我的哲学斗争引导我得到关于小胡子(和把手)逻辑少性质的答案:https://stackoverflow.com/a/4946409/365252

值得注意的是,Mustache是​​ - 按设计 - 逻辑少。这要做的是加剧激励开发人员将逻辑与表示分离,即任何使你的演示标记“跳舞”或链接到单独用标记无法表达的“事物”的东西应该保持不变地狱远离你的模板。

但回到我们的问题......当我意识到我的问题不是“如何用标记绑定”时,真正的 Eureka 时刻来到我身边。

我真正的问题是:“循环与循环项目之间存在明显的逻辑关系。为什么我使用 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 / Moustache不到一个月,我仍然发现自己在某些用例中询问上述问题。这不是Silver Bullet

答案 1 :(得分:1)

我发现(在把手中,但可能也适用于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,然后再转换为对象。这意味着目标对象将缺少所有非原始对象(例如,函数)。考虑一下这是否足以满足您的需求。