Внешний шаблон в подстроке
Я использую шаблон подчеркивания. Можно добавить внешний файл в качестве шаблона?
В режиме Backbone View у меня есть:
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>
Это хорошо работает. Но Мне нужен внешний шаблон.
Я пытаюсь:
<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 ) })
но это не сработало.
Ответы
Ответ 1
EDIT: этот ответ устарел и устарел. Я бы удалил его, но это "принятый" ответ. Вместо этого я напишу свое мнение.
Я больше не буду это делать. Вместо этого я бы разделил все шаблоны на отдельные HTML файлы. Некоторые предложили бы загружать эти асинхронно (Require.js или кеш шаблонов). Это хорошо работает на небольших проектах, но в крупных проектах с большим количеством шаблонов вы обнаружите, что делаете тонну небольших асинхронных запросов на загрузку страницы, что мне очень не нравится. (ugh... ok, вы можете обойти его с помощью Require.js, предварительно скомпилировав свои исходные зависимости с помощью r.js, но для шаблонов это все равно мне не нравится)
Мне нравится использовать задачу grunt (grunt-contrib-jst) для компиляции всех HTML-шаблонов в один файл templates.js и включать это. Вы получаете лучшее из всех миров. IMO... шаблоны живут в файле, компиляция указанных шаблонов происходит во время сборки (не время выполнения), и у вас нет сотен крошечных асинхронных запросов при запуске страницы.
Все ниже - хлам
Для меня я предпочитаю простоту включения JS файла в свой шаблон. Итак, я могу создать файл с именем view_template.js, который включает в себя шаблон как переменную:
app.templates.view = " \
<h3>something code</h3> \
";
Затем это так же просто, как включение файла script, как обычный, и затем его использование в вашем представлении:
template: _.template(app.templates.view)
Сделав еще один шаг, я фактически использую coffeescript, поэтому мой код на самом деле больше похож на этот и избегает концевых символов конца строки:
app.templates.view = '''
<h3>something code</h3>
'''
Используя этот подход, вы избегаете выделения в require.js, где это действительно не нужно.
Ответ 2
Вот простое решение:
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"
- позволяет хранить каждый шаблон в отдельном html файле в статическом
dir
- очень легкий
- компилирует и кэширует шаблоны
- абстрактная логика загрузки шаблона. Например, в будущем вы можете использовать предварительно загруженные и предварительно скомпилированные шаблоны.
- прост в использовании
[Я редактирую ответ вместо комментария, потому что считаю, что это важно.]
если шаблоны не отображаются в родном приложении, и вы видите HIERARCHY_REQUEST_ERROR: DOM Exception 3
, посмотрите на ответ Дейва Робинсона на Что именно может вызвать "; HIERARCHY_REQUEST_ERR: DOM Exception 3 "-Error?.
В принципе, вы должны добавить
dataType: 'html'
к запросу $.ajax.
Ответ 3
Я не хотел использовать 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());
в представлениях Backbone.
Ответ 4
Этот mixin позволяет отображать внешний шаблон с помощью Underscore очень простым способом: _.templateFromUrl(url, [data], [settings])
. API-интерфейс метода почти такой же, как Underscore _. 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"});
Ответ 5
Это может быть немного не в тему, но вы можете использовать Grunt (http://gruntjs.com/) - который работает на node.js(http://nodejs.org/, доступный для всех основных платформ) для запуска задач из командной строки. Для этого инструмента есть куча плагинов, таких как компилятор шаблонов, https://npmjs.org/package/grunt-contrib-jst. См. Документацию по GitHub, https://github.com/gruntjs/grunt-contrib-jst. (Вам также нужно будет понять, как запустить диспетчер пакетов node, https://npmjs.org/. Не волнуйтесь, это невероятно просто и универсально.)
Затем вы можете сохранить все свои шаблоны в отдельных html файлах, запустить инструмент, чтобы предварительно скомпилировать их все с помощью подчеркивания (что, я считаю, является зависимостью для JST-плагина, но не беспокойтесь, node менеджер пакетов будет автоматически установлен зависимостей для вас).
Это объединяет все ваши шаблоны в один script, скажем
templates.js
Загрузка script по умолчанию задает глобальный - "JST" - который представляет собой массив функций и может быть доступен следующим образом:
JST['templates/listView.html']()
который был бы похож на
_.template( $('#selector-to-your-script-template'))
если вы поместили содержимое этого тега script в (templates/) listView.html
Однако реальный кикер: Grunt поставляется с этой задачей под названием "watch", которая будет в основном контролировать изменения файлов, которые вы определили в локальном файле grunt.js(который в основном представляет собой файл конфигурации для вашего проекта Grunt, в javascript). Если у вас есть grunt, запустите эту задачу, набрав:
grunt watch
из командной строки, Grunt будет отслеживать все изменения, внесенные вами в файлы, и автоматически выполнять все задачи, которые вы настроили для него в этом файле grunt.js, если он обнаруживает изменения - например, описанную выше задачу jst. Отредактируйте, а затем сохраните ваши файлы, и все ваши шаблоны перекомпилируются в один файл js, даже если они распределены по нескольким каталогам и подкаталогам.
Аналогичные задачи могут быть настроены для наложения вашего javascript, выполнения тестов, конкатенации и минимизации/удаления ваших файлов script. И все может быть привязано к задаче часов, поэтому изменения в ваших файлах автоматически инициируют новую "сборку" вашего проекта.
Потребовалось некоторое время, чтобы настроить и понять, как настроить файл grunt.js, но это хорошо, стоит потратить время, и я не думаю, что вы когда-нибудь вернетесь к предвзятому способу рабочая
Ответ 6
Я думаю, это, что может вам помочь. Все в решении вращается вокруг библиотеки require.js
, которая является файлом JavaScript и загрузчиком модуля.
Учебное пособие по приведенной выше ссылке очень хорошо показывает, как можно организовать проект магистральной сети. A примерная реализация. Надеюсь, это поможет.
Ответ 7
Меня заинтересовали шаблоны javascript, и теперь я делаю первые шаги с помощью магистрали. Это то, с чем я столкнулся, и, похоже, работает очень хорошо.
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();
Ответ 8
Мне пришлось установить тип данных в "текст", чтобы он работал у меня:
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;
}
Ответ 9
Я нашел решение, которое работает для меня с помощью 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>
И я поместил этот код в файл с именем map-template.html
После этого я создаю оболочку для файлов шаблонов.
<div id="templatesPool"></div>
Затем я включаю этот файл в свой основной файл html, например.
В голове:
<!-- Template Loader -->
<script>
$(function(){
$("#templatesPool").append($('<div>').load("map-template.html"));
});
</script>
Приветствия.
Ответ 10
Я знаю, что этот вопрос действительно старый, но он появился как первый результат поиска google для шаблонов ajax подчёркивания.
Я устал от того, что не нашел хорошего решения для этого, поэтому создал свой собственный:
https://github.com/ziad-saab/underscore-async-templates
В дополнение к загрузке шаблонов подчеркивания с использованием AJAX он добавляет <% include% > . Надеюсь, это может быть полезно кому-то.
Ответ 11
Мне было немного непросто заставить jQuery работать синхронно, поэтому я изменил предыдущий синхронный пример, используя promises. Это почти то же самое, но выполняется асинхронно. Я использую шаблоны 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
});
ПРИМЕЧАНИЕ. Как обсуждалось другими, было бы предпочтительнее компилировать все шаблоны в один файл templates.js и загружать вначале, а не иметь множество небольших синхронных вызовов AJAX для получения шаблонов при загрузке веб-страницы.
Ответ 12
Форвардное предупреждение - вот драконы:
Я упоминаю приведенный ниже подход просто для того, чтобы помочь тем, кто пытается сделать стеки ASP.NET(и аналогичные структуры) гармонично работать с экосистемой js-libs. Само собой разумеется, что это не общее решение. Сказав это...
/endforwardwarning
Если вы используете ASP.NET, вы можете экстеризировать свои шаблоны, просто разместив их в одном или нескольких частичных представлений. Aka внутри вашего .cshtml:
@Html.Partial("path/to/template")
Внутри вашего 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 @
// http://stackoverflow.com/info/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" });
Надеюсь, что этот неуловимый-очевидный подход поможет кому-то сэкономить час на поцарапание головы.