Возвращает массив объектов из Handlebars Helper

Я пытаюсь написать помощник, который будет возвращать массив объектов, которые затем можно будет пройти через цикл. Вот что у меня есть сейчас:

Handlebars.registerHelper('testHelper', () => {
  return [
    { slug: 'Test', title: 'This is it!' },
    { slug: 'Test 2', title: 'This is the second it!' },
  ];
});

Используя его как:

{{#entries this}}
  <a href="/{{slug}}">{{title}}</a>
{{/entries}}

И я получаю [object, Object] для каждого объекта в массиве вместо отдельных значений. Пожалуйста помоги :)

Спасибо!


person jasonetco    schedule 18.02.2017    source источник
comment
Цель помощника — вернуть строку разметки, а не данные. Почему вы хотите, чтобы ваш помощник хранил ваши данные?   -  person 76484    schedule 19.02.2017
comment
@ 76484, чтобы уменьшить объем данных, которые я компилирую, чтобы ускорить компиляцию на стороне сервера, я хотел бы иметь возможность использовать только те данные, которые мне нужны.   -  person jasonetco    schedule 19.02.2017
comment
Вы не компилируете данные. Вы компилируете шаблон.   -  person 76484    schedule 19.02.2017
comment
Я понимаю, но в хелпере я бы сделал запрос к базе данных, который мне не нужно было бы делать при компиляции шаблона   -  person jasonetco    schedule 19.02.2017
comment
Компиляция строки в функцию. Это не имеет ничего общего с запросом базы данных. Если вы визуализируете свои представления на сервере, то похоже, что вы пытаетесь добиться перемещения запроса к базе данных со слоя контроллера на слой представления. Это ничего не экономит, и делает код намного труднее для понимания.   -  person 76484    schedule 19.02.2017


Ответы (1)


Способ работы помощников в Handlebars немного сложен. Вместо того, чтобы передавать данные из помощника в тело основного шаблона, вы передаете часть тела шаблона, связанную с помощником, помощнику.

Итак, например, когда вы делаете это:

{{#entries this}}
  <a href="/{{slug}}">{{title}}</a>
{{/entries}}

Вы предоставляете помощнику entries две вещи: 1) текущий контекст (этот) 2) некоторую логику шаблона для применения

Вот как помощник получает эти элементы:

Handlebars.registerHelper('entries', (data, options) => {
  // data is whatever was provided as a parameter from caller
  // options is an object provided by handlebars that includes a function 'fn'
  //   that we can invoke to apply the template enclosed between 
  //   #entries and /entries from the main template
   :
   :
});

Итак, чтобы сделать то, что вы хотите сделать:

Handlebars.registerHelper('testHelper', (ignore, opt) => {
  var data = [
    { slug: 'Test', title: 'This is it!' },
    { slug: 'Test 2', title: 'This is the second it!' },
  ];
  var results = '';
  data.forEach( (item) => {
    results += opt.fn(item);
  });
  return results;
});

opt.fn(item) применяет эту часть шаблона:

<a href="/{{slug}}">{{title}}</a>

и идея состоит в том, чтобы создать строку (часть вашего html), которая затем возвращается и помещается в строку, сформулированную вашим основным шаблоном.

Вот пример, чтобы показать, как это работает.

<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js"></script>
</head>
<body>

<script id="t" type="text/x-handlebars">
    {{#testHelper this}}
    <a href="/{{slug}}">{{title}}</a>
    {{/testHelper}}
</script>

<script>
    Handlebars.registerHelper('testHelper', (ignore, opt) => {
        var data = [
            { slug: 'Test', title: 'This is it!' },
            { slug: 'Test 2', title: 'This is the second it!' },
        ];
        var results = '';
        data.forEach((item) => {
            results += opt.fn(item);
        });
        return results;
    });

    var t = Handlebars.compile($('#t').html());
    $('body').append(t({}));
</script>
</body>
</html>

Позвольте мне также повторить то, что другие пытались вам сказать. Нет особого смысла пытаться заполнить данные в ваших шаблонах. Это должно быть передано в качестве контекста для ваших шаблонов. В противном случае вы смешиваете свою бизнес-логику с логикой шаблона (представление), и это излишне усложняет ситуацию.

Вот простое изменение, которое вы можете внести в тот же фрагмент, передав данные в свои шаблоны:

<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js"></script>
</head>
<body>

<script id="t" type="text/x-handlebars">
    {{#testHelper this}}
    <a href="/{{slug}}">{{title}}</a>
    {{/testHelper}}
</script>

<script>
    Handlebars.registerHelper('testHelper', (ignore, opt) => {
        var results = '';
        data.forEach((item) => {
            results += opt.fn(item);
        });
        return results;
    });

    var data = [
        { slug: 'Test', title: 'This is it!' },
        { slug: 'Test 2', title: 'This is the second it!' },
    ];
    var t = Handlebars.compile($('#t').html());
    $('body').append(t(data));
</script>
</body>
</html>

Таким образом, вы можете получить свои данные в своем javascript и сохранить шаблоны для того, для чего они были предназначены - формулировка html.

person rasmeister    schedule 19.02.2017