Внешний шаблон в подчеркивании

я использую подчеркивания шаблон. Можно прикрепить внешний файл как шаблон?

в представлении позвоночника у меня:

 textTemplate: _.template( $('#practice-text-template').html() ),

 initialize: function(){                                            
  this.words = new WordList;            
  this.index = 0;
  this.render();
 },

в моем html есть:

<script id="practice-text-template" type="text/template">
   <h3>something code</h3>
</script>

Он работает хорошо. Но!--8-->мне нужен внешний шаблон. Я стараюсь:

<script id="practice-text-template" type="text/template" src="templates/tmp.js">

или

textTemplate: _.template( $('#practice-text-template').load('templates/tmp.js') ),

или

$('#practice-text-template').load('templates/tmp.js', function(data){ this.textTemplate = _.template( data ) })

но это не сработало.

12 ответов


EDIT: этот ответ старый и устаревший. Я бы удалил его, но это" принятый " ответ. Вместо этого я выскажу свое мнение.

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

мне нравится использовать задачу grunt (grunt-contrib-jst) для компиляции всех шаблонов HTML в один шаблон.JS файл и включить это. Вы получаете лучшее из всех миров IMO... шаблоны живут в файле, компиляция указанных шаблонов происходит во время сборки (не во время выполнения), и у вас нет сотни крошечных асинхронных запросов при запуске страницы.

все, что ниже-хлам

для меня я предпочитаю простоту включения JS-файла с моим шаблоном. Итак, я могу создать файл с именем view_template.js, который включает шаблон в качестве переменной:

app.templates.view = " \
    <h3>something code</h3> \
";

тогда это так же просто, как включить файл сценария, как обычный, а затем использовать его в своем представлении:

template: _.template(app.templates.view)

Сделай шаг далее, я на самом деле используйте coffeescript, поэтому мой код на самом деле больше похож на это и избегайте символов конца строки:

app.templates.view = '''
    <h3>something code</h3>
'''

использование этого подхода позволяет избежать рассола в require.js, где это действительно не нужно.


вот простое решение:

var rendered_html = render('mytemplate', {});

function render(tmpl_name, tmpl_data) {
    if ( !render.tmpl_cache ) { 
        render.tmpl_cache = {};
    }

    if ( ! render.tmpl_cache[tmpl_name] ) {
        var tmpl_dir = '/static/templates';
        var tmpl_url = tmpl_dir + '/' + tmpl_name + '.html';

        var tmpl_string;
        $.ajax({
            url: tmpl_url,
            method: 'GET',
            dataType: 'html', //** Must add 
            async: false,
            success: function(data) {
                tmpl_string = data;
            }
        });

        render.tmpl_cache[tmpl_name] = _.template(tmpl_string);
    }

    return render.tmpl_cache[tmpl_name](tmpl_data);
}

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

Итак, функция "render"

  1. позволяет хранить каждый шаблон в отдельном html-файле в статическом реж.--11-->
  2. очень легкий
  3. компилирует и кэширует шаблоны
  4. логика загрузки шаблонов тезисов. Например, в будущем вы можете использовать предустановленные и предварительно скомпилированные шаблоны.
  5. прост в использовании

[я редактирую ответ, а не оставлять комментарий, потому что считаю это важным.]

Если шаблоны не отображаются в приложение, а вы видите HIERARCHY_REQUEST_ERROR: DOM Exception 3 посмотри на ответ Дэйв Робинсон что именно может вызвать ошибку"Hierarchy_request_err: DOM Exception 3"?.

В основном, вы должны добавить

dataType: 'html'

к $.запрос AJAX.


этот mixin позволяет визуализировать внешний шаблон с помощью подчеркивание очень простым способом:_.templateFromUrl(url, [data], [settings]). Метод API почти такой же, как библиотеки Underscore!--5--> _.template (). Кэширование включено.

_.mixin({templateFromUrl: function (url, data, settings) {
    var templateHtml = "";
    this.cache = this.cache || {};

    if (this.cache[url]) {
        templateHtml = this.cache[url];
    } else {
        $.ajax({
            url: url,
            method: "GET",
            async: false,
            success: function(data) {
                templateHtml = data;
            }
        });

        this.cache[url] = templateHtml;
    }

    return _.template(templateHtml, data, settings);
}});

использование:

var someHtml = _.templateFromUrl("http://example.com/template.html", {"var": "value"});

Я не хотел использовать require.js для этой простой задачи, поэтому я использовал модифицированное решение koorchik.

function require_template(templateName, cb) {
    var template = $('#template_' + templateName);
    if (template.length === 0) {
        var tmpl_dir = './templates';
        var tmpl_url = tmpl_dir + '/' + templateName + '.tmpl';
        var tmpl_string = '';

        $.ajax({
            url: tmpl_url,
            method: 'GET',
            contentType: 'text',
            complete: function (data, text) {
                tmpl_string = data.responseText;
                $('head').append('<script id="template_' + templateName + '" type="text/template">' + tmpl_string + '<\/script>');
                if (typeof cb === 'function')
                    cb('tmpl_added');
            }
        });
    } else {
        callback('tmpl_already_exists');
    }
}

require_template('a', function(resp) {
    if (resp == 'tmpl_added' || 'tmpl_already_exists') {
        // init your template 'a' rendering
    }
});
require_template('b', function(resp) {
    if (resp == 'tmpl_added' || 'tmpl_already_exists') {
        // init your template 'b' rendering
    }
});

зачем добавлять шаблоны в документ, а не хранить их в объекте javascript? Поскольку в рабочей версии я хотел бы создать html-файл со всеми уже включенными шаблонами, поэтому мне не нужно будет делать никаких дополнительных запросов ajax. И в то же время мне не нужно будет делать рефакторинг в моем коде, так как я использую

this.template = _.template($('#template_name').html());

в моем позвоночнике просмотр.


это может быть немного не по теме, но вы можете использовать Grunt (http://gruntjs.com/) - который работает на узле.js (http://nodejs.org/, доступно для всех основных платформ) для выполнения задач из командной строки. Для этого инструмента есть куча плагинов, таких как компилятор шаблонов,https://npmjs.org/package/grunt-contrib-jst. См. документацию по GitHub,https://github.com/gruntjs/grunt-contrib-jst. (Вам также нужно будет понять, как запустить Диспетчер пакетов узлов, https://npmjs.org/. Не волнуйтесь, это невероятно легко и универсально. )

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

это компилирует все ваши шаблоны в один скрипт, скажем

templates.js

загрузка скрипта установит глобальный - " JST " по default-который представляет собой массив функций и может быть доступен следующим образом:

JST['templates/listView.html']()

который был бы похож на

_.template( $('#selector-to-your-script-template'))

если вы поместите содержимое этого тега скрипта в (templates/)listView.HTML-код

однако настоящий Кикер таков: Grunt поставляется с этой задачей под названием "watch", которая в основном будет отслеживать изменения в файлах, которые вы определили в своем локальном grunt.JS-файл (который в основном является конфигурационным файлом для вашего проекта Grunt, в яваскрипт.) Если у вас есть grunt, начните эту задачу для вас, набрав:

grunt watch

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

подобных задач можно настроить для автоматической проверки кода ваш JavaScript, запуск тестов, объединение и сокращение / уродуя свои файлы скриптов. И все могут быть привязаны к задаче watch, поэтому изменения в ваших файлах автоматически вызовут новую "сборку" вашего проекта.

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


Я думаю этой - это то, что может помочь вам. Все в решении вращается вокруг require.js библиотеки-это JavaScript-файл и загрузчик модуль.

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


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

window.App = {

    get : function(url) {
        var data = "<h1> failed to load url : " + url + "</h1>";
        $.ajax({
            async: false,
            url: url,
            success: function(response) {
                data = response;
            }
        });
        return data;
    }
}

App.ChromeView = Backbone.View.extend({
    template: _.template( App.get("tpl/chrome.html") ),
    render: function () {
        $(this.el).html(this.template());
        return this;
    },
});

App.chromeView = new App.ChromeView({ el : document.body });
App.chromeView.render();

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

get : function(url) {
    var data = "<h1> failed to load url : " + url + "</h1>";
    $.ajax({
        async: false,
        dataType: "text",
        url: url,
        success: function(response) {
            data = response;
        }
    });
    return data;
}

Я нашел решение, которое работает для меня с помощью jQuery.

я добавляю код шаблона подчеркивания с помощью jQuery.метод load (), в основной HTML-файл.

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

концепция:

у меня есть код шаблона карты подчеркивания:

<!-- MAP TEMPLATE-->
<script type="text/template" id="game-map-template">
    <% _.each(rc, function(rowItem, index){ %>
      <ul class="map-row" data-row="<%- index %>">
        <li class="map-col <%- colItem.areaType ? 'active-area' : '' %>"></li>
        ...
</script>

и я поместил этот код в файл под названием карта-шаблон.HTML-код

после этого я создаю оболочку для файлов шаблонов.

<div id="templatesPool"></div>

затем я включаю этот файл в свой основной html-файл так.

в голову:

<!-- Template Loader -->
<script> 
    $(function(){
      $("#templatesPool").append($('<div>').load("map-template.html")); 
    });
</script> 

Ура.


Я знаю, что этот вопрос действительно старый, но он появился в качестве первого результата поиска google для шаблонов подчеркивания ajax.

Я устал не найти хорошего решения для этого, поэтому я создал свой собственный:

https://github.com/ziad-saab/underscore-async-templates

помимо загрузки шаблонов подчеркивания с помощью AJAX, он добавляет функциональность . Надеюсь, это кому-нибудь пригодится.


мне было немного неудобно заставлять jQuery работать синхронно, поэтому я изменил предыдущий синхронный пример, используя обещания. Это почти то же самое, но работает асинхронно. Я использую шаблоны hbs в этом примере:

var asyncRenderHbs= function(template_name, template_data) {
    if (!asyncRenderHbs.template_cache) { 
        asyncRenderHbs.template_cache= {};
    }

    var promise= undefined;

    if (!asyncRenderHbs.template_cache[template_name]) {
        promise= new Promise(function(resolve, reject) {
            var template_url= '/templates/' + template_name;
            $.ajax({
                url: template_url,
                method: 'GET',
                success: function(data) {
                    asyncRenderHbs.template_cache[template_name]= Handlebars.compile(data);
                    resolve(asyncRenderHbs.template_cache[template_name](template_data));
                },
                error: function(err, message) {
                    reject(err);
                }           
            });
        });
    } else {
        promise= Promise.resolve(asyncRenderHbs.template_cache[template_name](template_data));
    }

    return promise;
};

затем использовать визуализированный html:

asyncRenderHbs('some_template.hbs', context)
    .then(function(html) {
        applicationMain.append(html);
        // Do other stuff here after html is rendered...
    })
    .catch(function(err) {
        // Handle errors
    });

Примечание: как обсуждалось другими, было бы предпочтительнее скомпилировать все шаблоны в один шаблон.JS-файл и загрузите его в начале, а не иметь много небольших синхронных AJAX вызовы для получения шаблонов при загрузке веб-страницы.


вперед предупреждение - здесь будьте драконы:

я упоминаю подход, показанный ниже, просто чтобы помочь тем, кто пытается сделать ASP.NET стеки (и аналогичные структуры) работают гармонично с экосистемой js-libs. Разумеется, это не универсальное решение. Сказав это ...

/endforwardwarning

Если вы используете ASP.NET вы можете экстернализовать свои шаблоны, просто поместив их внутри одного или нескольких частичных представлений. Также известный как внутри твоего .cshtml по:

  @Html.Partial("path/to/template")

внутри шаблона.cshtml по:

   // this is razorview and thusly if you ever need to use the @ character in here  
   // you will have to either escape it as @@ or use the html codepoint which is &#64
   // http://stackoverflow.com/questions/3626250/escape-character-in-razor-view-engine
   <script type="text/x-template" id="someId">
        <span class="foo"><%= name %></span>
   </script>

и теперь вы можете использовать шаблон, как обычно:

  _.template($("#someId").html())({ name: "Foobar" });

надеюсь, что этот неуловимо очевидный подход поможет кому-то сэкономить час на почесывание головы.