Как создать HTML-шаблон?

Проблема

У меня есть коллекция изображений со связанными подписями на странице. Я хочу, чтобы каждый из них имел идентичный HTML.

Обычно я копирую и вставляю HTML снова и снова для каждого элемента. Проблема в том, что если я хочу настроить HTML, я должен сделать это для всех. Это отнимает много времени, и есть риск ошибок.

Быстрое и грязное шаблонирование

Я хотел бы написать только одну копию HTML, перечислить элементы содержимого в виде простого текста, а при рендеринге страницы HTML будет автоматически повторяться для каждого элемента содержимого.

HTML

<p><img src=IMAGE-URL>
<br>
<a target='_blank' href=LINK-URL>CAPTION</a></p>

Список содержимого

IMAGE-URL, LINK-URL, CAPTION
/data/khang.jpg, https://khangssite.com, Khang Le
/data/sam.jpg, https://samssite.com, Sam Smith
/data/joy.jpg, https://joyssite.com, Joy Jones
/data/sue.jpg, https://suessite.com, Sue Sneed
/data/dog.jpg, https://dogssite.com, Brown Dog
/data/cat.jpg, https://catssite.com, Black Cat

Отдельный предмет

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

TEMPLATE=MyTemplate1, IMAGE-URL=khang.jpg, LINK-URL=https://khangssite.com, CAPTION=Khang Le

Реализация

Широко используются системы шаблонов, такие как Django и Smarty на стороне сервера, и Mustache на стороне клиента. Этот вопрос ищет простое решение шаблона с одним файлом без использования внешних библиотек.

Я хочу добиться этого без фреймворка, библиотеки и т. д. Я хотел бы поместить HTML и список содержимого в один и тот же файл .html.

Базы точно нет. Это должно быть быстро и просто настроить на странице, без установки или настройки дополнительных сервисов.

В идеале я хотел бы сделать это без javascript, но это не является строгим требованием. Если есть javascript, он не должен знать имена полей. В идеале очень коротко и просто. Пожалуйста, без jquery.

Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
1
0
116
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

вы имеете в виду Литералы шаблонов (строки шаблонов) ?

const arrData = 
  [ { img: '/data/khang.jpg', link: 'https://khangssite.com', txt: 'Khang Le'  }  
  , { img: '/data/sam.jpg',   link: 'https://samssite.com',   txt: 'Sam Smith' } 
  , { img: '/data/joy.jpg',   link: 'https://joyssite.com',   txt: 'Joy Jones' } 
  , { img: '/data/sue.jpg',   link: 'https://suessite.com',   txt: 'Sue Sneed' } 
  , { img: '/data/dog.jpg',   link: 'https://dogssite.com',   txt: 'Brown Dog' } 
  , { img: '/data/cat.jpg',   link: 'https://catssite.com',   txt: 'Black Cat' } 
  ] 

const myObj = document.querySelector('#my-div')

arrData.forEach(({ img, link, txt }) => 
  {
  myObj.innerHTML += `
    <p>
      <img src = "${img}">
      <br>
      <a target='_blank' href = "${link}">${txt}</a>
    </p>`
  });
<div id = "my-div"></div>

Красивый! Является ли arrData JSON? Спасибо!

johny why 14.11.2022 07:53

@johnywhy Почти это объект JavaScript (JSO), где синтаксис двойных кавычек не требуется. В JSON это обязательно, потому что документ JSON представляет собой простой текст в кодировке UTF-8, а в качестве разделителей используются двойные кавычки (за исключением числовых типов); и вам нужно использовать анализатор JSON, чтобы преобразовать этот текст в полезные данные. В JS это команда JSON.parse(), которая создает данные JSO. -- У JSO больше технических возможностей, чем у JSON, поскольку они могут содержать методы.

Mister Jojo 14.11.2022 17:08

Существует ли JSO-эквивалент JSON.parse()?

johny why 14.11.2022 17:49

@johnywhy JSO — это (редко используемый) акроним для объектов JavaScript, JSON — это обычное сокращение для «формат JSON» , это также JSGO (глобальный объект JS) с именем JSON (с различными методами, такими как JSON.parse() или [JSON.stringify()](JSON.stringify())). Пожалуйста, прочитайте документ и, если возможно, отметьте мой ответ как принятый.

Mister Jojo 14.11.2022 20:23

Итак, ваш arrData уже является объектом, и его не нужно анализировать, верно?

johny why 14.11.2022 20:27

Спасибо за этот ответ, но он не выполняет запрос на перечисление данных и имен полей в файле HTML.

johny why 23.11.2022 17:18

я проголосовал за ваш ответ, кстати.

johny why 23.11.2022 18:06
Ответ принят как подходящий

Этот ответ является полным решением. Очень интересно редактировать HTML-шаблон в codepen и наблюдать за изменением макета каждой копии в режиме реального времени — это похоже на опыт редактирования класса CSS и наблюдения за изменениями в реальном времени.

Вот код, за которым следует объяснение.

HTML

<span id = "template-container"></span>

<div hidden id = "template-data">
    IMG,, LINK,, CAPTION
    https://www.referenseo.com/wp-content/uploads/2019/03/image-attractive.jpg,, khangssite.com,, Khang Le
    https://i.redd.it/jeuusd992wd41.jpg,, suessite.com,, Sue Sneed
    https://picsum.photos/536/354,, catssite.com,, Black Cat
</div>

<template id = "art-template">
    <span class = "art-item">
        <p>
            <a href = "${LINK}" target = "_blank">
                <img src = "${IMG}" alt = "" />
                <br>
                ${CAPTION}
            </a>
        </p>
    </span>
</template>

Javascript

window.onload = function LoadTemplate() {
    // get template data. 
    let sRawData = document.querySelector("#template-data").innerHTML.trim();

    // load header and data into arrays
    const headersEnd = sRawData.indexOf("\n");
    const headers = sRawData.slice(0, headersEnd).split(",,");
    const aRows = sRawData.slice(headersEnd).trim().split("\n");
    const data = aRows.map((element) => {
        return element.split(",,");
    });

    // grab template and container
    const templateHtml = document.querySelector("template").innerHTML;
    const container = document.querySelector("#template-container");

    // make html for each record
    data.forEach((row) => {
        let workingCopy = templateHtml;

        // load current record into template
        headers.forEach((header, column) => {
            let value = row[column].trim();
            let placeholder = `\$\{${header.trim()}\}`;
            workingCopy = workingCopy.replaceAll(placeholder, value);
        });

        // append template to page, and loop to next record
        container.innerHTML += workingCopy;
    });
};

Новая версия на гитхабе: https://github.com/johnaweiss/HTML-микро-шаблоны

Требование

Как указано в вопросе, это решение предназначено для оптимизации процесса кодирования на стороне HTML. В этом весь смысл любого веб-шаблона. Таким образом, JS должен работать немного усерднее, чтобы облегчить жизнь HTML-программисту.

Вопрос ищет многоразовое решение. Поэтому JS не должен знать о шаблоне, полях и списке данных. Так что, в отличие от ответа @MisterJojo, шаблон и все данные находятся в моем HTML, а не в javascript. Код JS является общим.

Дизайн

Мое решение основано на теге <template>, который предназначен именно для этого использования. Он имеет различные преимущества, например, шаблон не отображается, не обрабатывается и не проверяется браузером, поэтому он меньше влияет на производительность. Программисту не нужно писать явный display:none стиль. https://news.ycombinator.com/item?id=33089975

Однако теги <template> обычно предназначены только для загрузки контента в макет. Это неадекватно. Этот инструмент позволяет использовать переменные шаблона в любом месте HTML, в том числе внутри тегов (например, таких атрибутов, как <img src).

HTML

Мой HTML состоит из трех блоков:

  • шаблон: HTML-кодировщик разрабатывает желаемую структуру отображения вывода в реальном HTML (не в обычном тексте). Использует <template>
  • data: список записей, каждая из которых должна отображаться с использованием одного и того же шаблона. Использует <span> со СКРЫТЫМ атрибутом.
  • контейнер: место для отображения всех выходных блоков. Использует <span>.

Шаблон

Мой образец шаблона включает 3 заполнителя для данных:

${LINK}
${IMG}
${CAPTION}

Но, конечно, вы можете использовать любые заполнители, любое их количество. Я использую стиль разделителя строковых литералов (хотя на самом деле я не использую их как строковые литералы — я просто позаимствовал стиль разделителя).

Элемент данных

Вопрос указывает, что данные должны храниться в HTML. Это должно требовать минимальных нажатий клавиш.

  • Я не хотел повторять имена полей в каждой строке. Я не использовал слоты, синтаксис JSO, Jason или XML, потому что все они многословны. https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots
  • Это простой список с разделителями. Я удалил все фигурные скобки, квадратные скобки, знаки равенства, скобки, двоеточия и т. д.
  • Я помещаю заголовки fieldname только в первую строку. Заголовки являются визуальным подспорьем для разработчика HTML и ключом для Javascript, позволяющим узнать имена полей и их порядок.
  • Разделитель записи: конец строки
  • Разделитель полей: двойные запятые. Кажется безопасным, и их легко напечатать. Я не ожидаю увидеть двойные запятые в каких-либо фактических данных. Осторожно, разработчик должен вводить пробел для любых пустых ячеек, чтобы предотвратить непреднамеренные двойные запятые. Программист может легко использовать другой разделитель, если он предпочитает, если он обновляет Javascript. Вы можете использовать одинарные запятые, если уверены, что в ячейке не будет встроенных запятых.
  • Блок данных скрыт с помощью атрибута hidden. CSS не нужен.
  • Это интервал, чтобы гарантировать, что он не занимает места на странице.

ЯВАСКРИПТ

Данные

Данные обрабатываются Javascript с двумя операторами разделения, сначала на разделителе новой строки, затем на разделителе с двойной запятой. Это помещает все это в 2D-массив. Мой JS использует обрезки, чтобы избавиться от лишних пробелов по мере необходимости.

Замена заполнителя

Обработка нескольких записей требует включения каждой записи в шаблон.

я использовал простую замену строк вместо строковых литералов.

Несколько шаблонов

Новая версия, которая поддерживает несколько шаблонов и возможность использовать один и тот же шаблон в нескольких местах на одной странице.

https://github.com/johnaweiss/HTML-микро-шаблоны

Будущее

Вдохновленный @MisterJojo, более ранняя версия моего решения использовала литералы шаблонов для замены. Однако это было немного сложнее и многословнее и, казалось, требовало использования eval. Поэтому я перешел на .replaceAll. Тем не менее, шаблонные литералы кажутся более подходящим методом для шаблонов, поэтому, возможно, я вернусь к этому.

Будущая версия может адаптироваться к любому пользовательскому разделителю полей, который разработчик HTML использует для блока данных.

Разделитель в виде доллара для заполнителей немного неудобен для ввода. Поэтому я заинтересован в поиске менее неудобного разделителя без альфа-канала, который не будет конфликтовать с HTML. Учитывая двойные скобки или фигурные скобки [[NAME]]

Возможно, есть более простые способы вытащить таблицу данных в JS.

Я читал, что компоненты хорошо работают с <template>, но я туда не заходил.

Имо, комитет JS должен разработать функцию переменных-заполнителей для тегов <template> и изначально обеспечить хранение данных в HTML. Было бы здорово, если бы что-то вроде этого решения было частью движка рендеринга.

Другие вопросы по теме