Templates 在Mustach中,如何获取当前节的索引

Templates 在Mustach中,如何获取当前节的索引,templates,mustache,Templates,Mustache,我正在使用和使用数据 { "names": [ {"name":"John"}, {"name":"Mary"} ] } 我的胡子模板是: {{#names}} {{name}} {{/names}} 我希望能够得到数组中当前数字的索引。比如: {{#names}} {{name}} is {{index}} {{/names}} 把它打印出来 John is 1 Mary is 2 有没有可能把这个和胡子连在一起?或者使用Handlebar或其他扩展?如果可以控制JSO

我正在使用和使用数据

{ "names": [ {"name":"John"}, {"name":"Mary"} ] }
我的胡子模板是:

{{#names}}
    {{name}}
{{/names}}
我希望能够得到数组中当前数字的索引。比如:

{{#names}}
    {{name}} is {{index}}
{{/names}}
把它打印出来

John is 1
Mary is 2

有没有可能把这个和胡子连在一起?或者使用Handlebar或其他扩展?

如果可以控制JSON字符串的输出,请尝试此操作

{ "names": [ {"name":"John", "index":"1"}, {"name":"Mary", "index":"2"} ] }

因此,在创建JSON字符串时,将索引添加为每个对象的另一个属性。

在handlebar.js中,您可以通过一个helper函数来实现这一点。(事实上,这里提到的关于Handlebar的一个优点是,您可以使用helpers,而不必在调用模板之前重写对象

所以,你可以这样做:

  var nameIndex = 0;
  Handlebars.registerHelper('name_with_index', function() {
    nameIndex++;
    return this.name + " is " + nameIndex;
  })
然后,您的模板可以是:

{{#names}}
<li>{{name_with_index}}</li>
{{/names}}
您可以得到以下输出:

<li>John is 1</li>
<li>Mary is 2</li>
约翰一岁了
  • 玛丽2岁
  • 要使其真正起作用,nameIndex需要在每次呈现模板时进行重置,以便在列表的开头有一个重置帮助程序。因此完整代码如下所示:

      var data = { "names": [ {"name":"John"}, {"name":"Mary"} ] };
      var templateSource = "<ul>{{reset_index}}{{#names}}<li>{{name_with_index}}</li>{{/names}}</ul>";
      var template = Handlebars.compile(templateSource);
    
      var helpers = function() {
        var nameIndex = 0;
        Handlebars.registerHelper('name_with_index', function() {
          nameIndex++;
          return this.name + " is " + nameIndex;
        });
        Handlebars.registerHelper('reset_index', function() {
          nameIndex = 0;
        })
      }();
    
      var htmlResult= template(data);
      $('#target').html(htmlResult);
    
      var htmlResult2= template(data);
      $('#target2').html(htmlResult2);
    
    var data = { 
       names: [ {"name":"John"}, {"name":"Mary"} ],
        index: function() {
            return function(array, render) {
                return data[array].indexOf(this);
            }
        }
    };
    
    var html = Mustache.render(template, data);
    
    {{#array}}
        {{@index}}
    {{/array}}
    
    var data={“name”:[{“name”:“John”},{“name”:“Mary”}]};
    var templateSource=“
      {{reset_index}}{{{{names}}
    • {{name_with_index}}
    • {{/names}
    ”; var template=handlebar.compile(templateSource); var helpers=函数(){ var-nameIndex=0; 车把.注册表帮助器('name_,带索引',function()){ nameIndex++; 返回this.name+“is”+nameIndex; }); 把手.注册表帮助器('reset_index',function(){ nameIndex=0; }) }(); var htmlResult=模板(数据); $('#target').html(htmlResult); var htmlResult2=模板(数据); $('#target2').html(htmlResult2);
    (这可以正确地渲染模板两次。)

    这里是伟大的助手:

    // {{#each_with_index records}}
    //  <li class="legend_item{{index}}"><span></span>{{Name}}</li>
    // {{/each_with_index}}
    
    Handlebars.registerHelper("each_with_index", function(array, fn) {
        var buffer = "";
        for (var i = 0, j = array.length; i < j; i++) {
            var item = array[i];
    
            // stick an index property onto the item, starting with 1, may make configurable later
            item.index = i+1;
    
            // show the inside of the block
            buffer += fn(item);
        }
    
        // return the finished buffer
        return buffer;
    
    });
    
    /{{{{#每个_都有_索引记录}
    //
  • {{{Name}
  • //{{/each_with_index} 把手。注册表帮助器(“每个带索引的”功能(数组,fn){ var buffer=“”; 对于(var i=0,j=array.length;i

    来源:

    这是我在JavaScript中的实现方式:

    var idx = 0;
    
    var data = { 
       "names": [ 
           {"name":"John"}, 
           {"name":"Mary"} 
        ],
        "idx": function() {
            return idx++;
        }
    };
    
    var html = Mustache.render(template, data);
    
    您的模板:

    {{#names}}
        {{name}} is {{idx}}
    {{/names}}
    
    {{#names}}
        {{name}} is {{index}}
    {{/names}}
    
    {{#names}}
        {{name}} is {{#index}}names{{/index}}
    {{/names}}
    

    我的主要用例是在项目上放置一个“活动”类的能力。我把“equals”助手与“index_for_each”助手组合起来搞砸了,但这太复杂了

    相反,我提出了以下基本的“活动”助手。它非常具体,但对于任何菜单/选择列表场景来说都是一个常见的用例:

    用法:

      <ul>
        {{{active 2}}}
        {{#each menuItem}}
          <li class="{{{active}}}">{{this}}</li>
        {{/each}}
      </div>
    

    您可以在对象列表上运行以下循环

    此解决方案具有以下优点:

    • 不更改模型数据
    • 该索引可以多次访问
    代码:

    for( var i=0; i< the_list.length; i++) {
        the_list[i].idx = (function(in_i){return in_i+1;})(i);
    }
    
    for(var i=0;i
    说明:

    for( var i=0; i< the_list.length; i++) {
        the_list[i].idx = (function(in_i){return in_i+1;})(i);
    }
    

    使用函数而不是变量名,因此数据不会发生变化。闭包用于在循环中创建函数时返回“i”值,而不是在循环结束时返回“i”值。

    作为参考,此功能现在内置于与Mustache兼容的把手中

    使用
    {{@index}}

    {{#names}}
        {{name}} is {{@index}}
    {{/names}}
    
    约翰0岁


    Mary是1

    只要您没有进入多个数组,就可以将索引存储在帮助器上,并在上下文更改时增加索引。我使用的是类似于以下内容的内容:

    var data = {
        foo: [{a: 'a', 'b': 'a'}, {'a':'b', 'b':'b'}], 
        i: function indexer() {
            indexer.i = indexer.i || 0;
            if (indexer.last !== this && indexer.last) {                                          
                indexer.i++;
            }   
            indexer.last = this;
            return String(indexer.i);
         }   
    };
    
    Mustache.render('{{#foo}}{{a}}{{i}}{{b}}{{i}}{{/foo}}', data);
    

    更好的方法是使用一个函数,该函数使用
    indexOf
    获取索引:

    var data = { 
       names: [ {"name":"John"}, {"name":"Mary"} ],
        index: function() {
            return data.names.indexOf(this);
        }
    };
    
    var html = Mustache.render(template, data);
    
    在模板中:

    {{#names}}
        {{name}} is {{idx}}
    {{/names}}
    
    {{#names}}
        {{name}} is {{index}}
    {{/names}}
    
    {{#names}}
        {{name}} is {{#index}}names{{/index}}
    {{/names}}
    
    缺点是此
    索引
    函数具有数组硬编码的
    数据。名称
    为了使其更具动态性,我们可以使用以下另一个函数:

      var data = { "names": [ {"name":"John"}, {"name":"Mary"} ] };
      var templateSource = "<ul>{{reset_index}}{{#names}}<li>{{name_with_index}}</li>{{/names}}</ul>";
      var template = Handlebars.compile(templateSource);
    
      var helpers = function() {
        var nameIndex = 0;
        Handlebars.registerHelper('name_with_index', function() {
          nameIndex++;
          return this.name + " is " + nameIndex;
        });
        Handlebars.registerHelper('reset_index', function() {
          nameIndex = 0;
        })
      }();
    
      var htmlResult= template(data);
      $('#target').html(htmlResult);
    
      var htmlResult2= template(data);
      $('#target2').html(htmlResult2);
    
    var data = { 
       names: [ {"name":"John"}, {"name":"Mary"} ],
        index: function() {
            return function(array, render) {
                return data[array].indexOf(this);
            }
        }
    };
    
    var html = Mustache.render(template, data);
    
    {{#array}}
        {{@index}}
    {{/array}}
    
    模板中的用法:

    {{#names}}
        {{name}} is {{idx}}
    {{/names}}
    
    {{#names}}
        {{name}} is {{index}}
    {{/names}}
    
    {{#names}}
        {{name}} is {{#index}}names{{/index}}
    {{/names}}
    
    还有一个小缺点是,在本例中,必须将数组名传递给index函数
    names
    {{{index}}names{{/index}}

    (在节点4.4.7,小胡子2.2.1中测试)

    如果你想要一个干净的函数方式来实现它,不涉及全局变量或改变对象本身,使用这个函数

    var withIds = function(list, propertyName, firstIndex) {
        firstIndex |= 0;
        return list.map( (item, idx) => {
            var augmented = Object.create(item);
            augmented[propertyName] = idx + firstIndex;
            return augmented;
        })
    };
    
    在组装视图时使用它

    var view = {
        peopleWithIds: withIds(people, 'id', 1) // add 'id' property to all people, starting at index 1
    };
    
    这种方法的好处在于,它创建了一组新的“viewmodel”对象,将旧对象集用作原型。您可以像读取
    person.firstName
    一样读取
    person.id
    。但是,此函数根本不会更改您的people对象,因此其他代码(可能依赖于不存在ID属性)不会受到影响

    算法是O(N),非常好而且快速。


    推荐解决方案
    我的建议是添加一个
    索引

    let data = { "names": [ {"name":"John"}, 
    {"name":"Mary"} ] };
    
    // Add an index manually
    data = {
      names: [
        { id: 0, name: "John" },
        { id: 1, name: "Mary" }
      ]
    };
    
    // Add an index with a loop
    data = data.names
      .map(function (name, i) {
        name.id = i;
        return name;
      });
    
    // Nested arrays with indices (parentId, childId)
    data = {
      names: [{
        parentId: 0,
        name: "John",
        friends: [{
          childId: 0,
          name: "Mary"
        }]
      }]
    };
    
    其他建议的解决方案没有那么干净,并且存在许多问题,详情如下


    建议的胡须索引解决方案的问题
    @Index

    小胡子不支持@Index

    IndexOf

    此解决方案在O(n^2)时间内运行,因此没有最佳性能。此外,必须为每个列表手动创建索引

    const data = {
      list: ['a', 'b', 'c'],
      listIndex: function () {
        return data.list.indexOf(this);
      }
    };
    
    Mustache.render('{{#list}}{{listIndex}}{{/list}}', data);
    
    const data = {
      list: ['a', 'b', 'c'],
      listIndex: function () {
        return (++window.listIndex || (window.listIndex = 0));
      }
    };
    
    Mustache.render('{{#list}}{{listIndex}}{{/list}}', data);
    
    全局变量

    此解决方案在O(n)时间内运行,因此在这里性能更好,但也“污染了全局空间”(即,添加到
    窗口
    对象的任何属性,在浏览器窗口关闭之前都不会被垃圾回收),并且必须为每个列表手动创建索引

    const data = {
      list: ['a', 'b', 'c'],
      listIndex: function () {
        return data.list.indexOf(this);
      }
    };
    
    Mustache.render('{{#list}}{{listIndex}}{{/list}}', data);
    
    const data = {
      list: ['a', 'b', 'c'],
      listIndex: function () {
        return (++window.listIndex || (window.listIndex = 0));
      }
    };
    
    Mustache.render('{{#list}}{{listIndex}}{{/list}}', data);
    
    局部变量

    此解决方案在O(n)时间内运行,不会“污染全局空间”,并且不需要手动进行cr