使用 handlebars.js 模板以数组中的最后一项为条件

Posted

技术标签:

【中文标题】使用 handlebars.js 模板以数组中的最后一项为条件【英文标题】:conditional on last item in array using handlebars.js template 【发布时间】:2012-07-13 19:29:47 【问题描述】:

我正在为我的模板引擎使用handlebars.js,并希望仅当它是模板配置对象中包含的数组中的最后一项时才显示条件段。


  columns: [<obj>,<obj>,<obj>,<obj>,<obj>]

我已经引入了一个助手来进行一些相等/大于/小于比较,并且已经成功地以这种方式识别了初始项目,但没有运气访问我的目标数组的长度。

Handlebars.registerHelper('compare', function(lvalue, rvalue, options) ...)

"#each_with_index columns"+
"<div class='#equal index 0 first/equal#equal index ../columns.length() last/equal'>"+
"</div>"+
"/each_with_index"

有没有人知道捷径、不同的方法和一些车把优点,可以让我不必撕入车把.js 引擎来确定最佳路线?

【问题讨论】:

我会推荐underscoreJS的模板库,它比handlebars.js更有意义,效率也更高 嗯,我 我没有询问其他模板引擎。我已经做出了我的选择,很多次迭代之前。许多技术人员为这个问题提供了很好的解决方案,但可惜我没有与这些技术人员合作,所以它们现在对我来说毫无用处。 如果你说的只是“显示”,你能用 CSS 处理它吗?我意识到这是一个警察,但如果数据已经在客户端上,只需隐藏 style="display: none" 实际上,使用 css 是行不通的,因为我用它来表示要使用哪个类。如果排在第一位(并且发现是特殊的),那么它会得到一个特殊的类,如果在行的最后一个(并且发现是特殊的)它会得到一个特殊的类(一些额外的变量告诉我特殊类是什么,所以不是此表的标准)。 【参考方案1】:

仅供参考:如果您被 Handlebars

在您正在迭代的对象上定义一个类似isLast 的属性并像这样使用它

#each objectsInList"property": "value"#unless isLast,/unless/each

构建一个 JSON 对象。

【讨论】:

【参考方案2】:

解决方案:

<div class='#compare index 1 first/compare#compare index total last/compare'></div>

利用以下博客和要点中的助手...

https://gist.github.com/2889952

http://doginthehat.com.au/2012/02/comparison-block-helper-for-handlebars-templates/

// #each_with_index records
//  <li class="legend_itemindex"><span></span>Name</li>
// /each_with_index

Handlebars.registerHelper("each_with_index", function(array, fn) 
  var total = array.length;
  var buffer = "";

  //Better performance: http://jsperf.com/for-vs-foreach/2
  for (var i = 0, j = total; 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;
    item.total = total;
    // show the inside of the block
    buffer += fn(item);
  

  // return the finished buffer
  return buffer;

);

Handlebars.registerHelper('compare', function(lvalue, rvalue, options) 

    if (arguments.length < 3)
        throw new Error("Handlerbars Helper 'compare' needs 2 parameters");

    operator = options.hash.operator || "==";

    var operators = 
        '==':       function(l,r)  return l == r; ,
        '===':      function(l,r)  return l === r; ,
        '!=':       function(l,r)  return l != r; ,
        '<':        function(l,r)  return l < r; ,
        '>':        function(l,r)  return l > r; ,
        '<=':       function(l,r)  return l <= r; ,
        '>=':       function(l,r)  return l >= r; ,
        'typeof':   function(l,r)  return typeof l == r; 
    

    if (!operators[operator])
        throw new Error("Handlerbars Helper 'compare' doesn't know the operator "+operator);

    var result = operators[operator](lvalue,rvalue);

    if( result ) 
        return options.fn(this);
     else 
        return options.inverse(this);
    

);

注意起始索引是正确的 1。

【讨论】:

如果没有 comparetotal 的定义,这个答案是不完整的。此外,0 是第一个索引,而不是 1。【参考方案3】:

从 Handlebars v1.1.0 开始,您现在可以在每个帮助器中使用 @first@last 布尔值来解决这个问题:

#each foo
    <div class='#if @firstfirst/if
                #if @last last/if'>
      @key - @index
    </div>
/each

我写的一个快速帮手是:

Handlebars.registerHelper("foreach",function(arr,options) 
    if(options.inverse && !arr.length)
        return options.inverse(this);

    return arr.map(function(item,index) 
        item.$index = index;
        item.$first = index === 0;
        item.$last  = index === arr.length-1;
        return options.fn(item);
    ).join('');
);

然后你可以写:

#foreach foo
    <div class='#if $first first/if#if $last last/if'></div>
/foreach

【讨论】:

干得好!尚未验证它是否有效,但我看起来应该,如果是这样,将在周末重新访问和重新分配。谢谢! 我刚刚使用了上面的助手,完全按照宣传的方式工作......谢谢! gist.github.com/zeroasterisk/5360895 不错的答案,但我确实注意到一个挂断。如果您的数组中的项目是字符串或任何其他原语,您将无法向其附加属性。我的解决方法是使用 item 的值创建一个新字符串,这在技术上是一个对象,并将属性附加到它,就像在这个要点中一样:https://gist.github.com/jordancooperman/5440241 为什么the answer with first and last being native效率更高时会接受这个答案? 惯性。这个答案是两年前写的并被接受。具有原生结构的 Handlebars 版本仅在一年多前发布。我猜 OP 已经继续前进了。【参考方案4】:

自 Handlebars 1.1.0 以来,first 和 last 已成为 each 助手的原生功能。见票#483。

用法类似于Eberanov's帮助类:

#each foo
    <div class='#if @firstfirst/if#if @last last/if'>@key - @index</div>
/each

【讨论】:

#unless @last,/unless FTW!【参考方案5】:

我对 Matt Brennan 的帮助器做了一些改进,您可以将此帮助器与对象或数组一起使用,此解决方案需要 Underscore 库:

Handlebars.registerHelper("foreach", function(context, options) 
  options = _.clone(options);
  options.data = _.extend(, options.hash, options.data);

  if (options.inverse && !_.size(context)) 
    return options.inverse(this);
  

  return _.map(context, function(item, index, list) 
    var intIndex = _.indexOf(_.values(list), item);

    options.data.key = index;
    options.data.index = intIndex;
    options.data.isFirst = intIndex === 0;
    options.data.isLast = intIndex === _.size(list) - 1;

    return options.fn(item, options);
  ).join('');
);

用法:

#foreach foo
    <div class='#if @firstfirst/if#if @last last/if'>@key - @index</div>
/foreach

【讨论】:

【参考方案6】:

如果您只是尝试处理数组的第一项,这可能会有所帮助

#each data-source#if @index,/if"this"/each

@index 由 each 助手提供,对于第一项,它将等于 0,因此可以由 if 助手处理。

【讨论】:

提醒任何发现此内容并希望将其与Meteor 的 Handlebars 实现一起使用的人,它不会起作用。 @ 打破了一切。

以上是关于使用 handlebars.js 模板以数组中的最后一项为条件的主要内容,如果未能解决你的问题,请参考以下文章

markdown 在使用AJAX呈现的Handlebars.js模板文件上显示平面JSON文件中的数据。

Handlebars.js 模板引擎

Handlebars.js 是不是允许动态模板?

如何访问 Handlebars.js 数组中的最终元素?

使用 handlebars.js 制作“if x in dict(json)”语句

Handlebars.js模板