Pergunta antiga, mas como a pergunta é "usando jQuery", pensei em fornecer uma opção que permita fazer isso sem introduzir nenhuma dependência de fornecedor.
Embora existam muitos mecanismos de modelagem por aí, muitos de seus recursos caíram em desagrado recentemente, com iteração ( <% for
), condicionais ( <% if
) e transformações ( <%= myString | uppercase %>
) vistas como micro-idioma na melhor das hipóteses e antipadrões na pior. As práticas modernas de modelagem incentivam simplesmente o mapeamento de um objeto para sua representação DOM (ou outra), por exemplo, o que vemos com propriedades mapeadas para componentes no ReactJS (especialmente componentes sem estado).
Modelos dentro do HTML
Uma propriedade em que você pode confiar para manter o HTML do seu modelo próximo ao restante do HTML é usar um não executável <script>
type
, por exemplo <script type="text/template">
. Para o seu caso:
<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>
No carregamento do documento, leia o seu modelo e o tokenize usando um simples String#split
var itemTpl = $('script[data-template="listitem"]').text().split(/\$\{(.+?)\}/g);
Observe que, com nosso token, você o obtém no [text, property, text, property]
formato alternado . Isso nos permite mapeá-lo bem usando uma Array#map
função de mapeamento:
function render(props) {
return function(tok, i) { return (i % 2) ? props[tok] : tok; };
}
Onde props
poderia parecer { url: 'http://foo.com', img: '/images/bar.png', title: 'Lorem Ipsum' }
.
Reunindo tudo, assumindo que você analisou e carregou o seu itemTpl
como acima, e você tem uma items
matriz no escopo:
$('.search').keyup(function () {
$('.list-items').append(items.map(function (item) {
return itemTpl.map(render(item)).join('');
}));
});
Essa abordagem também é apenas apenas jQuery - você deve ser capaz de adotar a mesma abordagem usando javascript vanilla com document.querySelector
e .innerHTML
.
jsfiddle
Modelos dentro de JS
Uma pergunta a ser feita é: você realmente deseja / precisa definir modelos como arquivos HTML? Você sempre pode componente + reutilizar um modelo da mesma maneira que reutilizaria a maioria das coisas que deseja repetir: com uma função.
No es7-land, usando funções de desestruturação, seqüências de caracteres de modelo e setas, você pode escrever funções de componentes absolutamente bonitas que podem ser facilmente carregadas usando o $.fn.html
método acima.
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>
`;
Então você poderia renderizá-lo facilmente, mesmo mapeado a partir de uma matriz, assim:
$('.list-items').html([
{ url: '/foo', img: 'foo.png', title: 'Foo item' },
{ url: '/bar', img: 'bar.png', title: 'Bar item' },
].map(Item).join(''));
Ah, e observação final: não se esqueça de higienizar suas propriedades passadas para um modelo, se forem lidas em um banco de dados ou se alguém puder passar HTML (e depois executar scripts etc.) da sua página.