定义要使用JQuery追加的HTML模板

Pat*_*eck 106 javascript jquery json

我有一个我正在循环的数组.每次条件为真时,我都想将HTML下面代码的副本附加到带有一些值的容器元素.

我可以在哪里以智能方式重复使用此HTML?

<a href="#" class="list-group-item">
    <div class="image">
         <img src="" />
    </div>
    <p class="list-group-item-text"></p>
</a>
Run Code Online (Sandbox Code Playgroud)

JQuery的

$('.search').keyup(function() {
    $('.list-items').html(null);

    $.each(items, function(index) {
        // APPENDING CODE HERE
    });
});
Run Code Online (Sandbox Code Playgroud)

Mat*_*tra 147

您可以决定在项目中使用模板引擎,例如:

如果您不想包含其他库,John Resig提供了一个jQuery解决方案,类似于下面的解决方案.


浏览器和屏幕阅读器忽略无法识别的脚本类型:

<script id="hidden-template" type="text/x-custom-template">
    <tr>
        <td>Foo</td>
        <td>Bar</td>
    <tr>
</script>
Run Code Online (Sandbox Code Playgroud)

使用jQuery,基于模板添加行将类似于:

var template = $('#hidden-template').html();

$('button.addRow').click(function() {
    $('#targetTable').append(template);
});
Run Code Online (Sandbox Code Playgroud)

  • 如何在此处编辑模板的示例:https://jsfiddle.net/meehanman/7vw8bc84/ (9认同)

Jos*_*bou 144

老问题,但由于问题是"使用jQuery",我想我会提供一个选项,让你可以在不引入任何供应商依赖的情况下执行此操作.

虽然那里有许多模板引擎,但它们的许多功能最近都不受欢迎,其中iteration(<% for),conditionals(<% if)和transforms(<%= 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>
Run Code Online (Sandbox Code Playgroud)

在文档加载时,阅读您的模板并使用简单的标记 String#split

var itemTpl = $('script[data-template="listitem"]').text().split(/\$\{(.+?)\}/g);
Run Code Online (Sandbox Code Playgroud)

请注意,使用我们的令牌,您可以以交替[text, property, text, property]格式获取它.这让我们可以使用Array#map带有映射函数的映射来很好地映射它:

function render(props) {
  return function(tok, i) { return (i % 2) ? props[tok] : tok; };
}
Run Code Online (Sandbox Code Playgroud)

哪里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('');
  }));
});
Run Code Online (Sandbox Code Playgroud)

这种方法也仅是勉强的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>
`;
Run Code Online (Sandbox Code Playgroud)

然后你可以轻松渲染它,甚至可以从数组映射,如下所示:

$('.list-items').html([
  { url: '/foo', img: 'foo.png', title: 'Foo item' },
  { url: '/bar', img: 'bar.png', title: 'Bar item' },
].map(Item).join(''));
Run Code Online (Sandbox Code Playgroud)

哦,最后注意:不要忘记清理传递给模板的属性,如果它们是从数据库中读取的,或者有人可以从您的页面传入HTML(然后运行脚本等).

  • 你的**里面的JS**模板是炸弹 (30认同)
  • 哇,这真是太好了。我正在为每个模板添加一个 data-url 属性。并为每个获取 ajax 数据。这真是太好了,节省了我很多时间!谢谢你。 (3认同)
  • 你能为"Inside Inside HTML"方法添加一个演示/小提琴吗? (2认同)

Dev*_*vWL 34

请改用HTML模板!

由于接受的答案将代表重载脚本方法,我想建议另一个,在我看来,由于重载脚本带来的XSS风险,它更清洁,更安全.

我做了一个演示,向您展示如何在一个动作中使用它以及如何将一个模板注入另一个模板,编辑然后添加到文档DOM.

示例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>
Run Code Online (Sandbox Code Playgroud)

示例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);
Run Code Online (Sandbox Code Playgroud)

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.
}
Run Code Online (Sandbox Code Playgroud)

关于重载脚本方法的一些见解

  • +没有渲染 - 浏览器不渲染此块,因为默认情况下<script>标记具有display:none.
  • + Inert - 浏览器不会将脚本内容解析为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

  • Internet Explorer不支持`template`元素(截至2018年,IE11).使用http://w3c.github.io/html/single-page.html的示例580进行测试. (3认同)

Mat*_*wak 13

添加到身体的某个地方

<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>
Run Code Online (Sandbox Code Playgroud)

然后创建CSS

.hide { display: none; }
Run Code Online (Sandbox Code Playgroud)

并添加到您的js

$('#output').append( $('.hide').html() );
Run Code Online (Sandbox Code Playgroud)

  • OP 有一个 JSON,并希望使用该数组作为数据源呈现一些 html。这个答案是如何解决问题的?您的答案需要一个 html 节点并克隆/复制它,而与数据绑定无关。 (2认同)