HTML-шаблоны Полифиллы JavaScript

Я ищу наиболее совместимый со стандартами / перспективный метод для внешнего интерфейса HTML-шаблонов.

Существует относительно новая черновая спецификация W3C W3C для шаблонов HTML., например:

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

Кто-нибудь знает, существуют ли какие-либо хорошие полифиллы JavaScript для создания <template> можно использовать в кроссбраузерном режиме? Желательно соответствие этому стандарту.


Трудности

Согласно руководству по HTML5Rocks, эти шаблоны обладают следующими свойствами:

  • «Его содержимое эффективно инертно, пока не будет активировано»
  • "Скрипт не запускается, изображения не загружаются, звук не воспроизводится",
  • "Содержимое считается отсутствующим в документе"
  • "Шаблоны можно размещать в любом месте внутри <head>, <body> или <frameset>"

Я думаю, что невозможно реализовать все эти четыре свойства исключительно с помощью полифилла JavaScript, поэтому любое решение будет только частичным.


person Robin Winslow    schedule 17.04.2013    source источник
comment
stackoverflow.com/about   -  person Xotic750    schedule 11.05.2013


Ответы (4)


Существует jsfiddle, демонстрирующий такой полифилл.

<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));

Что касается библиотек, и я не знаю, поддерживают ли они это, но попробуйте что-то вроде Modernizr и Инициализ

person Xotic750    schedule 17.04.2013
comment
Ссылка в моем ответе выше, нажмите на текст jsfiddle - person Xotic750; 17.04.2013
comment
Ваш ответ не поддерживает важное требование - безопасность. ;) Как только вы поместите свой шаблон в элемент <template> в браузере, который не обрабатывает его специально, у вас не будет инертного шаблона. Загрузите jsfiddle.net/h3EmY/80 в IE10-11, и вы увидите. - person mgol; 12.05.2014
comment
Вы можете имитировать инертность с помощью тега script с пользовательским типом mime, но тогда вы не получите .content. - person mgol; 12.05.2014
comment
Я не использую IE какой-либо версии, и, хотя полезно указать на безопасность, ОП хотел: желательно полифилл, соответствующий стандартам, но если он недоступен, то любое близкое к нему решение. Цитата из Modernizr: то, что вы можете использовать полифилл, не означает, что вы должны - person Xotic750; 12.05.2014
comment
Обратите внимание, что этот полифилл отлично работает для основной части, но если ваш шаблон содержит теги скриптов, это не помешает их выполнению. Другими словами, не используйте скрипты js внутри ваших шаблонов, если вы заботитесь о ie11. - person ling; 09.10.2016

Xotic750 предложил надежный полифилл, который работает путем мутации элементов HTML, но он потерпит неудачу, если какие-либо новые шаблоны будут позже добавлены в DOM, а мутация все чаще не рекомендуется (там, где ее можно избежать).

Вместо этого я рекомендую ввести поведение «полифилл» в тот момент, когда вы используете шаблоны. Добавьте эту функцию в свой 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>, и в тех, которые его не поддерживают. Как и в другом ответе, это не идеальный полифилл, поскольку он не делает шаблоны инертными (это было бы сложно, медленно и подвержено ошибкам). Но он работает достаточно хорошо для меня, чтобы использовать его в производстве.

Оставьте комментарий, если у вас есть вопросы или проблемы, и я внесу соответствующие изменения.

person ivanreese    schedule 15.10.2015

Другой возможностью являются полифиллы веб-компонентов, которые включают полифилл для тега <template>. Имейте в виду, что webcomponents.js содержит полифиллы не только для тега <template>.

person donnapep    schedule 29.04.2016
comment
Если вам нужен только полифил шаблона, вам просто нужно включить github .com/webcomponents/webcomponentsjs/blob/master/src/ (делает в основном то же самое, что и полифилл, упомянутый в других ответах, но на domReady). - person ernesto; 10.10.2016
comment
Ссылка @ernesto не работает, так как полифил шаблона веб-компонента теперь является автономным пакетом и имеет собственный репозиторий. Вот он: github.com/webcomponents/template - person Iwazaru; 19.12.2017
comment
Он снова перемещен: github.com/webcomponents/polyfills/tree/master/packages/ - person JamesQMurphy; 24.02.2020

Еще одна возможность — Template-Element-Polyfill от Neovov.

Это специальный <template> полифил, который вы можете найти на Github.

person Supersharp    schedule 17.12.2016