Определение HTML-шаблона для добавления с помощью JQuery
У меня есть массив, который я перебираю. Каждый раз, когда условие истинно, я хочу добавить копию кода HTML
ниже в контейнерный элемент с некоторыми значениями.
Где я могу поместить этот HTML-код для повторного использования интеллектуальным способом?
<a href="#" class="list-group-item">
<div class="image">
<img src="" />
</div>
<p class="list-group-item-text"></p>
</a>
JQuery
$('.search').keyup(function() {
$('.list-items').html(null);
$.each(items, function(index) {
// APPENDING CODE HERE
});
});
Ответы
Ответ 1
Вы можете решить использовать в своем проекте механизм шаблонов, например:
Если вы не хотите включать другую библиотеку, John Resig предлагает решение jQuery, похожее на приведенное ниже.
Браузеры и устройства чтения с экрана игнорируют непризнанные типы script:
<script id="hidden-template" type="text/x-custom-template">
<tr>
<td>Foo</td>
<td>Bar</td>
<tr>
</script>
Используя jQuery, добавление строк на основе шаблона будет напоминать:
var template = $('#hidden-template').html();
$('button.addRow').click(function() {
$('#targetTable').append(template);
});
Ответ 2
Старый вопрос, но поскольку вопрос задает "использование jQuery", я думал, что предоставил бы вариант, который позволит вам сделать это, не введя никакой зависимости от поставщика.
Несмотря на то, что в мире много шаблонов, многие из их функций в последнее время стали разочаровываться, итерация (<% for
), условные обозначения (<% if
) и преобразования (<%= myString | uppercase %>
), рассматриваемые как микроязык в лучшими и анти-шаблонами в худшем случае. Современные шаблонные методы поощряют просто сопоставление объекта с его представлением DOM (или другого), например. что мы видим со свойствами, сопоставленными с компонентами в ReactJS (особенно безстоящими компонентами).
Шаблоны внутри HTML
Одно свойство, на которое вы можете положиться, для хранения HTML-кода для вашего шаблона рядом с остальной частью вашего HTML, - это использование неиспользуемого <script>
type
, например. <script type="text/template">
. Для вашего случая:
<script type="text/template" data-template="listitem">
<a href="${url}" class="list-group-item">
<table>
<tr>
<td><img src="${img}"></td>
<td><p class="list-group-item-text">${title}</p></td>
</tr>
</table>
</a>
</script>
При загрузке документа прочитайте свой шаблон и отметьте его с помощью простого String#split
var itemTpl = $('script[data-template="listitem"]').text().split(/\$\{(.+?)\}/g);
Обратите внимание, что с нашим токеном вы получаете его в переменном формате [text, property, text, property]
. Это позволяет нам красиво сопоставить его с помощью Array#map
с функцией отображения:
function render(props) {
return function(tok, i) { return (i % 2) ? props[tok] : tok; };
}
Где props
может выглядеть как { url: 'http://foo.com', img: '/images/bar.png', title: 'Lorem Ipsum' }
.
Объединяя все вместе, если вы проанализировали и загрузили ваш itemTpl
, как указано выше, и у вас есть массив items
в области:
$('.search').keyup(function () {
$('.list-items').append(items.map(function (item) {
return itemTpl.map(render(item)).join('');
}));
});
Этот подход также является всего лишь едва jQuery - вы должны использовать тот же подход, используя ванильный javascript с document.querySelector
и .innerHTML
.
jsfiddle
Шаблоны внутри JS
Вопрос, который вы задаете себе, - это: хотите ли вы/нужно определить шаблоны в виде файлов HTML? Вы всегда можете компоновать + повторно использовать шаблон так же, как вы бы повторно использовали большинство вещей, которые хотите повторить: с помощью функции.
В es7-land, используя деструктурирование, шаблонные строки и функции-стрелки, вы можете написать совершенно красивые компоненты компонента, которые можно легко загрузить с помощью метода $.fn.html
выше.
const Item = ({ url, img, title }) => `
<a href="${url}" class="list-group-item">
<div class="image">
<img src="${img}" />
</div>
<p class="list-group-item-text">${title}</p>
</a>
`;
Затем вы можете легко отобразить его, даже отображаемый из массива, например:
$('.list-items').html([
{ url: '/foo', img: 'foo.png', title: 'Foo item' },
{ url: '/bar', img: 'bar.png', title: 'Bar item' },
].map(Item).join(''));
О и последнее замечание: не забывайте санировать ваши свойства, переданные в шаблон, если они читаются из БД, или кто-то может передать HTML (а затем запустить скрипты и т.д.) со своей страницы.
Ответ 3
Добавить где-нибудь в теле
<div class="hide">
<a href="#" class="list-group-item">
<table>
<tr>
<td><img src=""></td>
<td><p class="list-group-item-text"></p></td>
</tr>
</table>
</a>
</div>
затем создайте css
.hide { display: none; }
и добавьте в js
$('#output').append( $('.hide').html() );
Ответ 4
Используйте вместо этого HTML-шаблон!
Поскольку принятый ответ будет представлять собой перегрузку метода script, я хотел бы предложить другой, который, на мой взгляд, намного чище и безопаснее из-за рисков XSS, связанных с перегрузкой скриптов.
Я сделал демо, чтобы показать вам, как использовать его в действии и как вставлять один шаблон в другой, редактировать, а затем добавлять в документ DOM.
https://codepen.io/DevWL/pen/YrjyWm?editors=1010
пример html
<template id="mytemplate">
<style>
.image{
width: 100%;
height: auto;
}
</style>
<a href="#" class="list-group-item">
<div class="image">
<img src="" />
</div>
<p class="list-group-item-text"></p>
</a>
</template>
пример js
// select
var t = document.querySelector('#mytemplate');
// set
t.content.querySelector('img').src = 'demo.png';
t.content.querySelector('p').textContent= 'demo text';
// add to document DOM
var clone = document.importNode(t.content, true); // where true means deep copy
document.body.appendChild(clone);
HTML <template >
-
+ Его содержимое эффективно инертно до активации. По сути, ваш
разметка скрыта DOM и не отображает.
-
+ Любой контент в шаблоне не будет иметь побочных эффектов. Скрипты не запускаются, изображения не загружаются, звук не воспроизводится... пока не будет использован шаблон.
-
+ Содержимое не считается в документе. Использование document.getElementById()
или querySelector()
на главной странице не будет возвращать дочерние узлы шаблона.
-
+ Шаблоны могут быть размещены в любом месте <head>
, <body>
или <frameset>
и могут содержать любой тип контента, который разрешен в этих элементах. Обратите внимание, что "где угодно" означает, что <template>
можно безопасно использовать в тех местах, где не разрешен парсер HTML.
Возврат назад
Поддержка браузеров не должна быть проблемой, но если вы хотите охватить все возможности, вы можете легко проверить:
Чтобы обнаружить функцию <template>
, создайте элемент DOM и убедитесь, что существует свойство .content:
function supportsTemplate() {
return 'content' in document.createElement('template');
}
if (supportsTemplate()) {
// Good to go!
} else {
// Use old templating techniques or libraries.
}
Некоторые сведения о методе перегрузки script
- + Ничего не отображается - браузер не отображает этот блок, поскольку по умолчанию тег
<script>
имеет display:none
.
- + Inert - браузер не анализирует содержимое script как JS, потому что его тип имеет значение, отличное от
"text/javascript"
.
- - Проблемы безопасности - поощряет использование
.innerHTML
. Анализ времени выполнения пользовательских данных может легко привести к уязвимостям XSS.
Полная статья: https://www.html5rocks.com/en/tutorials/webcomponents/template/#toc-old
Полезная ссылка:
https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode
http://caniuse.com/#feat=queryselector
Ответ 5
Другая альтернатива: Pure
Я использую его, и это очень помогло мне.
Пример, показанный на их веб-сайте:
HTML
<div class="who">
</div>
JSON
{
"who": "Hello Wrrrld"
}
Результат
<div class="who">
Hello Wrrrld
</div>
Ответ 6
Чтобы решить эту проблему, я распознаю два решения:
-
Первый идет с AJAX, с помощью которого вам придется загрузить шаблон из другого файла и просто добавлять каждый раз, когда вы хотите с .clone()
.
$.get('url/to/template', function(data) {
temp = data
$('.search').keyup(function() {
$('.list-items').html(null);
$.each(items, function(index) {
$(this).append(temp.clone())
});
});
});
Учтите, что событие должно быть добавлено после завершения ajax, чтобы убедиться, что данные доступны!
-
Второй способ заключается в том, чтобы напрямую добавить его в исходный html, выбрать его и скрыть в jQuery:
temp = $('.list_group_item').hide()
После добавления нового экземпляра шаблона с помощью
$('.search').keyup(function() {
$('.list-items').html(null);
$.each(items, function(index) {
$(this).append(temp.clone())
});
});
-
Как и предыдущий, но если вы не хотите, чтобы шаблон оставался там, но только в javascript, я думаю, вы можете использовать (не проверял его!) .detach()
вместо скрытия.
temp = $('.list_group_item').detach()
.detach()
удаляет элементы из DOM, сохраняя данные и события живыми (.remove() не работает!).