老问题,但由于问题询问“使用 jQuery”,我想我会提供一个选项,让您在不引入任何供应商依赖性的情况下执行此操作。
虽然有很多模板引擎,但它们的许多功能最近都变得不受欢迎,迭代<% for
(现代模板实践鼓励简单地将对象映射到它的 DOM(或其他)表示,例如,我们看到的属性映射到 ReactJS 中的组件(尤其是无状态组件)。<% if
<%= myString | uppercase %>
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 - 您应该能够使用带有document.querySelector
and的 vanilla javascript 采用相同的方法.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(然后运行脚本等)。