Handlebars Block Helper:每个都有排序

Posted

技术标签:

【中文标题】Handlebars Block Helper:每个都有排序【英文标题】:Handlebars Block Helper : each with sort 【发布时间】:2013-07-13 18:39:26 【问题描述】:

我有一个使用 Handlebars 模板输出的 json 对象数组;我目前正在使用 #each object.../each。我现在需要通过对象的一个​​属性对对象进行排序,这再次使用把手助手和咖啡脚本没有问题,但是,我的模板中有一个问题,因为我无法弄清楚如何使用每个来迭代排序的数组.

到目前为止,我的研究表明我可能需要编写一个自定义的 Handlebars 助手,它实际上是:

#each_with_sort array

我现有的排序助手是这样的

   Handlebars.registerHelper sort_me =>
     myArray.sort (a,b)->
       return if +a.sort_index >= +b.sort_index then 1 else -1

但是,我很难在模板中使用排序后的数组——例如,它不像

那么简单
 #each sort_me(myArray)

数据来自第三方API,所以我必须在handlebars/coffeescript中进行排序。

【问题讨论】:

【参考方案1】:

最简单的做法是在数据到达 Handlebars 之前对其进行排序,然后您可以像往常一样使用#each ...,并且不需要任何助手。这种方法在 Handlebars 中很常见,模板通常分为两部分:用于数据修改/重新排列的 (Java|Coffee)Script 部分和模板本身。

顺便说一句,您需要调整比较器函数以使其具有行为属性。来自fine manual:

如果提供了compareFunction,则数组元素根据比较函数的返回值进行排序。如果ab 是被比较的两个元素,那么:

如果compareFunction(a, b) 小于0,则将a 排序到比b 低的索引,即a 排在第一位。 如果compareFunction(a, b) 返回0,则保持ab 彼此保持不变,但对所有不同元素进行排序。注意:ECMAscript 标准不保证这种行为,因此并非所有浏览器(例如至少可以追溯到 2003 年的 Mozilla 版本)都尊重这一点。 如果compareFunction(a, b) 大于0,则将b 排序到低于a 的索引。

所以如果a.sort_indexb.sort_index 相同,您想返回0,更像这样:

myArray.sort (a,b)->
  a = +a.sort_index
  b = +b.sort_index
  return  1 if a > b
  return  0 if a == b
  return -1 if a < b

如果您必须在模板内进行排序,那么您需要添加一个自定义的 each_with_sort 助手来进行排序和迭代,如下所示:

# If you're always sorting by sort_index then you don't need the key argument
# and you might want to put the '+'-casting back in.
Handlebars.registerHelper('each_with_sort', (array, key, opts) ->
    data  = Handlebars.createFrame(opts.data) if(opts.data)
    array = array.sort (a, b) ->
        a = a[key]
        b = b[key]
        return  1 if a > b
        return  0 if a == b
        return -1 if a < b
    s = ''
    for e, i in array
        data.index = i if(data) # Support the usual @index.
        s += opts.fn(e, data: data)
    s
)

你的模板会是这样的:

#each_with_sort array "sort_index"
    ...
/each_with_sort

演示:http://jsfiddle.net/ambiguous/zusq2tt4/

【讨论】:

帮助程序的代码如何以排序方式迭代对象的属性? @JoachimBreitner javascript 对象没有指定的顺序,因此您需要将对象转换为 [[key,value],...] array-of-arrays 并对其进行排序;或者您可以将键提取到一个数组中,对键数组进行排序,然后对排序后的键进行迭代。 谢谢。我做了后者并将其集成到我自己的#each 变体中。 @muistooshort 它工作得很好:) 谢谢你,我唯一的问题是我丢失了我的 (at)index 参考。它总是返回 0(注意:我正在迭代一个对象数组)。 :S @Guillermo:看看我更新的答案。我认为 @index 的东西在我发布这个答案后被添加到 Handlebars 中,毕竟三年对于软件来说是很长的时间了 :)【参考方案2】:

我只是收集各种 javascript 函数并将其推送到车把,如下所示:

Handlebars.registerHelper(
    eq: (v1, v2) => v1 === v2,
    ne: (v1, v2) => v1 !== v2,
    lt: (v1, v2) => v1 < v2,
    gt: (v1, v2) => v1 > v2,
    lte: (v1, v2) => v1 <= v2,
    gte: (v1, v2) => v1 >= v2,    
    sort() 
        return arguments[0].sort();
    
);

我这样用它作为:

#each (sort students)
  <div> this </div>
/each

#if (eq arg1 arg2)
  <div> Delete </div>
/if

如果您需要许多函数,您可以将助手拆分为“if”函数和“each”函数......只是为了让它更有条理......

【讨论】:

以上是关于Handlebars Block Helper:每个都有排序的主要内容,如果未能解决你的问题,请参考以下文章

handlebars自定义helper的写法

js模版引擎handlebars.js实用教程——由于if功力不足引出的Helper

构建帮助方法

如何覆盖 Handlebars 的 `if` 助手

handlebars 判断要加表达式怎么加

在 Ember Handlebar If block helper 中检查值是不是等于