【问题标题】:Bind this to a handlebars button将此绑定到车把按钮
【发布时间】:2014-09-27 21:37:06
【问题描述】:

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

这可以用 mustache 或其他模板语言来完成吗?

JSON:

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

模板:

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

【问题讨论】:

  • 你为什么在 2014 年使用 onclick 属性?

标签: javascript underscore.js handlebars.js mustache


【解决方案1】:

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

请务必注意,Mustache 在设计上是 无逻辑。这样做的目的是agravate激励开发人员将逻辑与表示分离,即任何使您的表示标记“跳舞”或链接到仅用标记无法表达的“事物”的东西都应该保留远离你的模板。

但回到我们的问题......真正的尤里卡时刻来到我的脑海,我意识到我的问题不是“我如何将它与标记绑定”。

我真正的问题是:“循环和循环的项目之间显然涉及逻辑。为什么我要使用 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 之后,明显的回味:我必须这样做才能绑定一个事件,我宁愿在我的模板中放一个 &lt;script&gt; 标记!?

如果您问过自己这个问题,也许 无逻辑 模板不适合您。

免责声明:我使用 Handlebars/Mustache 还不到一个月,但我仍然发现自己在针对某些用例提出上述问题。这不是Silver Bullet。

【讨论】:

  • 非常感谢!这是一个很好的解决方案,但它是胡须/车把顶部的 js 猴子补丁。必须有一种直接的方法来做到这一点,尽管我承认这可以解决问题
  • 我也相信可能有一种单一的解决方案可以解决所有这些问题,但我感觉它不涉及 Mustache/Handlebars。
  • 我已准备好尝试任何其他可以让我的生活更轻松的模板语言。我将深入研究 jquery 模板的参考并让您知道
【解决方案2】:

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

【讨论】:

  • 无论{{getThis}} 返回什么都应该转义以适应属性(如引号和& 符号),Mustache/Handlebars 只会转义代码以用作标记。进一步假设它只包含可编码的数据(没有函数、引用、其他非原始类型)
  • 感谢您指出这一点,它肯定应该逃脱。另外,你是对的,它不会真正返回this,而是一个没有非原始类型或函数的副本;我仍然认为这足以满足 OP 的需求,同时保持代码精简和可行。
  • 感谢您的回复,但我对 onclick="_.bind(func,{as-long-as-hell-data-in-here} 感到不舒服。我强烈希望有一些参考相反(正如我在最初的问题中所写)
  • 对,我同意你的观点,但你开始使用onclick。正如有人在 cmets 中对主要问题指出的那样,最好避免它。要使用一些引用,我想你可以重新设计你的初始数据。
猜你喜欢
  • 1970-01-01
  • 2014-02-10
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
  • 2018-09-09
  • 1970-01-01
  • 2014-06-01
相关资源
最近更新 更多