旧问题,但是由于该问题询问“使用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而已-您应该能够使用带有document.querySelector
和的原始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(然后运行脚本等),请不要忘记清理传递给模板的属性。