Подтвердить что ты не робот

Вложенные шаблоны underscore.js

Возможно ли каким-либо образом взять элемент DOM из шаблона подчеркивания и использовать его в качестве другого шаблона?

Идея состоит в том, что моему приложению нужно отобразить документ, содержащий цикл с элементами и сводкой. Мне нужно иногда повторно отображать только сводку или несколько элементов, поэтому я не могу просто перерисовать весь документ.

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

Я пытаюсь использовать что-то вроде этого:

<script type="text/template" id="document-template">
    <div id="document">
        <h1><%= name %></h1>
        <ul class="items">
            <% _.each(items, function(item) { %> 
                <li><%= item %></li>
            <% }); %>
        </ul>
        <div id="summary">
            <p>Total items: <%= totalitems %></p>
        </div>
    </div>
</script>

Теперь я могу легко сделать это var documentTemplate = _.template($('#document-template').html());, чтобы превратить это в шаблон документа, но я хотел бы также превратить итоговую часть в шаблон и элемент списка в шаблон.

Могу ли я сделать что-то вроде этого:

var summaryTemplate = _.template($('#document-template #summary').html());
var itemTemplate = _.template($('#document-template .items li').html());

PS. Фактически я загружаю шаблон из внешнего файла с помощью jQuery $.get. Таким образом, я получу шаблон документа в одной большой строке. Оттуда я могу сделать только documentTemplate = _.template(loadedString);.

Теперь, если бы я мог просто извлечь элемент #summary из строки, он должен работать. Но когда я пытаюсь преобразовать строку в элемент DOM (var domElement = $(loadedString)) (так что я мог бы сделать это: summaryTemplate = _.template($('#summary',domElement).html());, он не будет работать, потому что подчеркивание больше не будет распознавать теги <% =% > .

4b9b3361

Ответ 1

Вы можете передать вложенный шаблон в качестве переменной в назначениях шаблона основному шаблону, например:

HTML:

<script type="text/template" id="sub_template">
  <article>
    <h1>id: <%= id %><h1>
  </article>
</script>

<script type="text/template" id="main_template">
  <% for (var i = 0; i < num; i++) { %>
    <%= renderSub({id:i}) %>
  <% } %>
</script>

JS:

 var renderSub = _.template( $('#sub_template').remove().text() ),
     renderMain = _.template( $('#main_template').remove().text() );

  renderMain({num:5, renderSub:renderSub});

Ответ 2

Игровая площадка

/////// TEMPLATES //////

    var mainTemplate = "<ul> \
                          <% _.each(items, function(item) { %> \
                               <%= listItem({item:item}) %> \
                          <% }); %> \
                        <ul>";

    var subTemplate = '<li><%=item %></li>';


/////// MODEL (our data) //////

    var model = {
        items : [1,2,3,4,5]
    }


/////// COMPILE //////

    // add the subTemplate to the model data, to be passed to the mainTemplate
    model.listItem = _.template(subTemplate);

    // Render main template to the DOM
    document.body.innerHTML = _.template(mainTemplate, model);

Ответ 3

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

У вас есть основной шаблон документа и итоговый шаблон. Начальная загрузка тянется в документе-шаблоне, а затем втягивается в итоговый шаблон и вставляет его в скомпилированный DOM из первого шаблона. Затем вы можете перезагрузить второй шаблон в любое время. См. Следующие шаги:

1) Загрузите начальный шаблон, показанный ниже:

<script type="text/template" id="document-template">
    <div id="document">
        <h1><%= name %></h1>
        <ul class="items">
            <% _.each(items, function(item) { %> 
                <li><%= item %></li>
            <% }); %>
        </ul>
    </div>
</script>

2) После того, как это скомпилировано в DOM, загрузите второй шаблон с помощью подчеркивания, показанного ниже:

<script type="text/template" id="summary-template">
    <div id="summary">
        <p>Total items: <%= totalitems %></p>
    </div>
</script>

3) Вызов $( "# document" ). append (summaryTemplate) или любая переменная содержит скомпилированный шаблон.

4) Повторяйте шаги 2 и 3 в любое время, когда вам нужно перезагрузить сводку, за исключением того, что сначала удалите существующие $( "# summary" ) перед добавлением снова

Вы можете использовать эту же стратегию для элементов, просто убедитесь, что вы используете правильные селектор/методы jQuery, чтобы переписывать существующие divs в правильном порядке, поскольку append будет работать только для добавления чего-либо к конец элемента.

Ответ 4

Я знаю, что я на 3 года опоздал на разговор, но ни один из этих ответов не применил вообще к ситуации, которая была у меня в моем последнем проекте. И так как изначально я думал об этом, я решил, что должен опубликовать его на случай, если кто-то еще захочет на самом деле вложить шаблоны underscore.js, как говорится в названии этого вопроса.

Мои требования были в основном:

1) Если в шаблоне есть динамические элементы, они должны иметь возможность повторно отображать их индивидуально - без необходимости повторного рендеринга всего шаблона с обновленными данными.

2) Динамические фрагменты не должны быть разбиты на свои собственные шаблоны на том же уровне, что и родительский шаблон; скорее, должна быть своего рода иерархия шаблонов - шаблон, объявляющий все необходимые подтемы для себя.

Понятие вложенных шаблонов в Underscore.js такое же, как в PHP (например). Следующий код является примером "эхо-ответа PHP":

<?php echo '<?php echo $var_unknown_until_runtime; ?>'; ?>

Хотя этот вложенный синтаксис может стать супер запутанным и запутанным, идея проста:

Эхо-код, который будет эхо-значения позже.

Это также применяется в шаблонах Underscore.js.


Пример

Код будет выглядеть так:

<script type="text/template" id="outer-tpl">
    <%= value %>

    <script type="text/template" id="inner-tpl">
        <%= '<%= value %\>' %> <!-- NOTE how the inner '>' is escaped ('\>') -->
    <%= "</script\>" %> <!-- NOTE same thing -->
</script>

Позвольте немного сломать это. Линия с первой NOTE является нашей ключевой линией. Обычно, когда Underscore компилирует этот шаблон, вы ожидаете, что значение value будет напечатано как в внешнем, так и в внутреннем шаблонах. Мы сделали несколько вещей, чтобы это не произошло:

1) Вставьте вложенное выражение подчеркивания в строку.

2) Интерполируйте эту строку (<%= "string here" %>).

3) Побег закрытия > во вложенном выражении подчеркивания (\>). Это предотвращает совпадение регулярного выражения Underscore с тегом открытия с шага 2 (<%=). Когда эта строка будет эхом, escape-символ будет удален, оставив %>, готовый к интерпретации Underscore на следующем проходе.

Выполнение этой же задачи во втором NOTE в нашем примере предотвращает завершение первого тега script браузером. Вложенные теги script технически не разрешены, поэтому браузер ищет первую последовательность символов: </script>, а затем завершает выполнение script. Это не позволяет браузеру распознавать эту последовательность.

Для более подробного примера см. этот JSFiddle.


Отказ

Я не поддерживаю это как можно ближе к лучшему способу делать подобные вещи. Это, в конце концов, очень хаки. В то время как @John z отвечает, нарушает мое первое требование, которое не было для меня вариантом, другой вариант расщепления динамических элементов в шаблоне в их собственные шаблоны может быть легче справиться. Он менее организован.

Расположение всех этих вложенных тегов script в DOM может быть сложно отслеживать (поскольку вложенные теги script будут динамически вставляться в DOM, когда и где вы вставляете внешний шаблон). Риск дублирования является высоким и может раздражать его.

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