把手-基于模板中的阵列键的计算

时间:2019-07-02 14:50:01

标签: javascript jquery handlebars.js

我是Handlebars的新手,正在使用4.1.2版本。我正在尝试将一些用PHP编写的模板移到Handlebars。

我的数据源是一个JSON提要,其结构如下:

[
    {
        "regulations_label": "Europe",
        "groups_label": "Group 1",
        "filters_label: "FF1A"
    },
    {
        "regulations_label": "Europe",
        "groups_label": "Group 1",
        "filters_label: "FF1B"
    },
    {
        "regulations_label": "Europe",
        "groups_label": "Group 2",
        "filters_label: "FF2A"
    },
    {
        "regulations_label": "Asia",
        "groups_label": "Group 999",
        "filters_label: "FF999A"
    },
    {
        "regulations_label": "Asia",
        "groups_label": "Group 999",
        "filters_label: "FF999B"
    },
    {
        "regulations_label": "Americas",
        "groups_label": "Group 10000",
        "filters_label: "FF10000A"
    },
]

我的HTML模板(PHP版本)的输出如下:

  • 欧洲
    • 第1组
      • FF1A
      • FF1B
    • 第2组
      • FF2A
  • 亚洲
    • 999组
      • FF999A
      • FF999B
  • 美洲
    • 10000组
      • FF10000A

达到此目的的方式-在输出过程中不复制任何regulations_labelgroups_label -是使用条件逻辑来检查先前的数组值以查看如果已经改变,例如

// $data is the JSON above. 
foreach ($data as $key => $d): 
    if ($data[$key-1]['groups_label'] !== $d['groups_label'])
        echo $d['groups_label'];
    endif;
endforeach;

上面的代码表示groups_label仅在与先前值不同的情况下才呈现,即,它只能打印“ Group 1”一次,等等。

因此,在手把中,我想应用相同的原理。我已阅读Handlebars/Mustache - Is there a built in way to loop through the properties of an object?,并了解到有{{@index}}{{@key}}

我遇到的问题是我无法在这些条件上应用条件逻辑。例如,没有{{@index - 1}}这样的东西。

我的设置方法如下:

<script id="regulations-template" type="text/x-handlebars-template">
    {{#each myregs}}
        - {{regulations_label}} <br>
        -- {{groups_label}} <br>
        ---- {{filters_label}} <br>
    {{/each}}
</script>


<script type="text/javascript">
    var regsInfo = $('#regulations-template').html();

    var template = Handlebars.compile(regsInfo);

    var regsData = template({ myregs: // JSON data shown above });

    $('#output').html(regsData);
</script>


<div id="output"></div>

内容呈现到#output div,但是它会重复每个级别,例如

- Europe
    -- Group 1
        ---- FF1A
- Europe
    -- Group 1
        ---- FF1B

之所以会出现此问题,是因为我无法找到一种方法来查看先前的数组值是什么,并且无法执行条件逻辑。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

我使用了一个递归函数(准备一个宽松的衬垫)来格式化数据,这种方式应该更容易显示。您可以将地图映射在孩子身上,然后使用标签进行打印:

const data = [
  { regulations_label: "Europe", groups_label: "Group 1", filters_label: "FF1A" },
  { regulations_label: "Europe", groups_label: "Group 1", filters_label: "FF1B" },
  { regulations_label: "Europe", groups_label: "Group 2", filters_label: "FF2A" },
  { regulations_label: "Asia", groups_label: "Group 999", filters_label: "FF999A" },
  { regulations_label: "Asia", groups_label: "Group 999", filters_label: "FF999B" },
  { regulations_label: "Americas", groups_label: "Group 10000", filters_label: "FF10000A" }
];

const r = (o, keys) => Object.entries(o.reduce((a, { [keys[0]]: l, ...r }) => ({ ...a, [l]: a[l] ? [...a[l], r] : [r] }), {})).map(([k, v]) => ({ label: k, children: keys.length === 2 ? v.map(o => o[keys[1]]) : r(v, keys.slice(1))}))

const myregs = r(data, ['regulations_label', 'groups_label', 'filters_label'])
const log = () => console.log(myregs)

var regsInfo = document.getElementById('regulations-template').innerHTML
var template = Handlebars.compile(regsInfo);
var regsData = template({myregs});
document.getElementById('output').innerHTML = regsData
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.js"></script>
<script id="regulations-template" type="text/x-handlebars-template">
    {{#each myregs}}
      - {{this.label}} <br>
        {{#each this.children}}
          - - {{this.label}} <br>
          {{#each this.children}}
            - - - {{this}} <br>
          {{/each}}
        {{/each}}
    {{/each}}
</script>

<button onclick="log()">Log data</button>
<div id="output"></div>

  

请注意,我删除了jQuery,只是因为我觉得不需要它,但可以随时将其添加回:)

答案 1 :(得分:0)

在纯车把解决方案中,您可以使用以下助手:

<script id="regulations-template" type="text/x-handlebars-template">
{{#each myregs}}
    {{#ifPrevRegulation}} - {{regulations_label}} <br> {{/ifPrevRegulation}}
    {{#ifPrevGroup}}-- {{groups_label}} <br>{{/ifPrevGroup}}
    {{#ifPrevFilter}} ---- {{filters_label}} <br>{{/ifPrevFilter}}
    {{setPrevContext}}
{{/each}}
</script>

哪里

var prevContext = null;
Handlebars.registerHelper('setPrevContext', function(){
    prevContext = this;
});

Handlebars.registerHelper('ifPrevRegulation', function(options){
    if(!(prevContext  && this.regulations_label == prevContext.regulations_label)){
      return options.fn(this);
    }
});

Handlebars.registerHelper('ifPrevGroup', function(options){
    if(!(prevContext  && this.regulations_label == prevContext.regulations_label && this.groups_label== prevContext.groups_label)){
      return options.fn(this);
    }
});

Handlebars.registerHelper('ifPrevFilter', function(options){
    if(!(prevContext  && this.regulations_label == prevContext.regulations_label && this.groups_label== prevContext.groups_label && this.filters_label == prevContext.filters_label)){
      return options.fn(this);
    }
});