19

我正在寻找最符合标准/面向未来的前端 HTML 模板方法。

HTML 模板存在一个相对较新的W3C 草案规范,例如:

<template id="mytemplate">
    <img src="" alt="great image">
    <div class="comment"></div>
</template>

有谁知道是否已经存在任何好的JavaScript polyfills以使 <template>元素以跨浏览器的方式可用?最好符合本标准。


困难

根据HTML5Rocks 指南,这些模板具有以下属性:

  • “它的内容在被激活之前实际上是惰性的”
  • “脚本不运行,图像不加载,音频不播放,”
  • “内容被认为不在文档中”
  • "模板可以放置在<head>, <body>, 或<frameset>"

我认为完全使用 JavaScript polyfill 实现所有这四个属性是不可能的,所以任何解决方案都只是部分的。

4

4 回答 4

12

Xotic750 提供了一个可靠的 polyfill,它通过改变 HTML 元素来工作——但是如果以后将任何新模板添加到 DOM 中,它就会失败,并且越来越不鼓励改变(在可以避免的情况下)。

相反,我建议在您使用模板时引入“polyfill”行为。将此函数添加到您的 JS:

function templateContent(template) {
    if("content" in document.createElement("template")) {
        return document.importNode(template.content, true);
    } else {
        var fragment = document.createDocumentFragment();
        var children = template.childNodes;
        for (i = 0; i < children.length; i++) {
            fragment.appendChild(children[i].cloneNode(true));
        }
        return fragment;
    }
}

使用对模板元素的引用调用该函数。它将提取内容,并返回一个 documentFragment,然后您可以将其附加到另一个元素(或对模板内容执行任何其他操作)。像这样:

var template = document.querySelector("template#my-template");
var content = templateContent(template);
someElm.appendChild(content);

现在,另一个答案没有提到它,但你可能想要一些 CSS 来隐藏<template>元素。

template { display: none; }

这是一个将所有内容组合在一起的CodePen

现在,这将在原生支持该元素的浏览器和不支持该<template>元素的浏览器中正常工作。与另一个答案类似,它不是一个完美的 polyfill,因为它不会使模板变得惰性(这将是复杂、缓慢且容易出错的)。但它足以让我在生产中使用。

如果您有任何疑问或问题,请发表评论,我会相应地进行修改。

于 2015-10-15T02:49:55.463 回答
9

有一个jsfiddle演示了这样的 polyfill。

<script>
    // Shim so we can style in IE6/7/8
    document.createElement('template');
</script>

<template id="example">
    <h1>
        This is template content.
    </h1>
    <p>
        It's really great.
    </p>
</template>


<div id="target">
    <p>
        This is regular old content.
    </p>
</div>

/* POLYFILL */
(function templatePolyfill(d) {
    if('content' in d.createElement('template')) {
        return false;
    }

    var qPlates = d.getElementsByTagName('template'),
        plateLen = qPlates.length,
        elPlate,
        qContent,
        contentLen,
        docContent;

    for(var x=0; x<plateLen; ++x) {
        elPlate = qPlates[x];
        qContent = elPlate.childNodes;
        contentLen = qContent.length;
        docContent = d.createDocumentFragment();

        while(qContent[0]) {
            docContent.appendChild(qContent[0]);
        }

        elPlate.content = docContent;
    }
})(document);

/* EXAMPLE */
var elExample = document.getElementById('example'),
    elTarget = document.getElementById('target');

elTarget.appendChild(elExample.content.cloneNode(true));

至于库,我不知道他们是否支持它,但尝试一下ModernizrInitializr

于 2013-04-17T09:08:37.560 回答
4

另一种可能性是Web Components polyfills,其中包含一个用于<template>标签的 polyfill。请记住,webcomponents.js 不仅包含<template>标签,还包含 polyfill。

于 2016-04-29T15:38:53.933 回答
2

另一种可能性是 Neovov 的Template-Element-Polyfill

这是一个专用的<template>polyfill,你可以在 Github 上找到。

于 2016-12-17T13:43:23.350 回答