Как использовать пользовательские элементы с шаблоном?

Я пытался понять, как работают веб-компоненты, поэтому я попытался написать небольшое приложение, которое я обслуживал на веб-сервере (протестировано в Chrome, который поддерживает rel = "import"):

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset = "utf-8" />
    <link rel = "import" href = "my-app.html" />
  </head>
  <body>
    <my-app />
  </body>
</html>

my-app.html:

<template id = "template">
  <div>Welcome to my app!</div>
</template>

<script>
class MyApp extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({mode: "open"});
    const template = document.getElementById("template");
    const clone = document.importNode(template.content, true);
    shadow.appendChild(clone);
  }
}
customElements.define("my-app", MyApp);
</script>

Но, похоже, это не работает. Тег <my-app /> вообще не отображается в DOM, и я получаю эту ошибку в консоли:

Uncaught TypeError: Cannot read property 'content' of null

Что я не могу получить узел template? Что я делаю неправильно?

Я также хотел бы знать, разрешено ли мне писать HTML-документ без шаблонного кода (doctype, head, body,...), потому что он предназначен для описания компонента, а не всего документа, который будет использоваться как есть. . Разрешено ли это спецификациями HTML5 и/или правильно интерпретируется большинством браузеров?

Спасибо за помощь.

имейте в виду, что <link rel = "import">` исчезает и больше не должен использоваться. Модули ES6 — один из способов заменить его.

Intervalia 04.05.2019 21:06

Да, но модули IMO ES6 используются для импорта модулей JS, а не HTML.

JacopoStanchi 04.05.2019 21:09

Верно. Это означает, что тег <template> больше не нужен для компонентов. Вы можете создать функцию render(), которая возвращает литеральную строку шаблона, которая может встраивать ваши данные, или использовать что-то вроде npmjs.com/package/component-build-tools.

Intervalia 04.05.2019 21:16

Мне становится немного грустно. Во-первых, потому что я предпочитаю синтаксис файла .vue синтаксису компонента React, а во-вторых, потому что метод render() возвращает даже не JSX, а строку шаблона, что означает, что в вашей IDE не будет выделений HTML и все такое. .

JacopoStanchi 04.05.2019 21:20
Улучшение производительности загрузки с помощью 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 страниц, которые помогут...
0
4
923
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Находясь внутри шаблона, не используйте глобальное значение document:

<template id = "template">
  <div>Welcome to my app!</div>
</template>

<script>
class MyApp extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({mode: "open"});

    // while inside the imported HTML, `currentDocument` should be used instead of `document`
    const currentDocument = document.currentScript.ownerDocument;
    // notice the usage of `currentDocument`
    const template = currentDocument.querySelector('#template');

    const clone = document.importNode(template.content, true);
    shadow.appendChild(clone);
  }
}
customElements.define("my-app", MyApp);
</script>

Демонстрация плункера: https://plnkr.co/edit/USvbddEDWCSotYrHic7n?p=preview



PS: отмечает совместимость с com здесь, хотя я предполагаю, что вы знаете, что импорт HTML будет объявлен устаревшим очень скоро.

Спасибо за Ваш быстрый ответ. Почему импорт HTML устарел? Будет ли чем их заменить?

JacopoStanchi 04.05.2019 21:04

Если вы используете хром, взгляните на консоль: [Устаревшее] Импорт HTML устарел и будет удален в M73 примерно в марте 2019 года. Вместо этого используйте модули ES. Дополнительные сведения см. в статье chromestatus.com/features/5144752345317376. Альтернативой на данный момент являются модули ES. Это скорее решение на чистом javascript.

acdcjunior 04.05.2019 21:12

Но как мы можем продолжать импортировать HTML-шаблоны?

JacopoStanchi 04.05.2019 21:14

Подробнее о том, почему здесь: полимер-проект.org/blog/…. В основном это связано с тем, что спецификация никогда не была единообразно реализована основными браузерами, и сообщество пришло к выводу, что до широкого распространения она была плохой.

acdcjunior 04.05.2019 21:15

Вы хотите продолжать использовать HTML-шаблоны или спрашиваете о «новой лучшей» альтернативе?

acdcjunior 04.05.2019 21:16

Мне нравится Vue.js, поэтому я хотел изначально использовать что-то, похожее на синтаксис файла .vue, но если есть более элегантный способ сделать это, я весь внимание.

JacopoStanchi 04.05.2019 21:17

Я мог бы указать некоторые ресурсы модуля ES, но я гарантирую, что использование Vue.js будет лучшим решением (лучше документация, больше примеров в Интернете) прямо сейчас. Эти спецификации веб-компонентов часто меняются (например, импорт HTML устарел), и, если у вас нет веских причин (например, упрямый работодатель) для выбора нативных веб-компонентов, я бы полностью остановился на Vue.js. Кроме того, если или когда веб-компоненты станут действительно зрелым стабильным стандартом, наверняка будут способы генерировать/мигрировать веб-компоненты из кода vue.

acdcjunior 04.05.2019 21:21

@acdcjunior На самом деле я пишу эссе об IPFS, протоколе, предназначенном для замены HTTP и полностью бессерверном. Я спрашивал себя, как продолжать создавать шаблоны без веб-серверов, и дело в том, что даже интерфейсные фреймворки, такие как Vue или React, нуждаются в сервере Node. Вот почему я хотел задокументировать собственные решения, такие как веб-компоненты.

JacopoStanchi 04.05.2019 21:24

Vue/React на самом деле не нуждается в сервере узла. Продуктом приложения vue/react может быть всего один большой файл .js (также известный как «пакет»), который импортируется на страницу с помощью обычного тега <script> и включает в себя все (даже встроенные HTML и CSS). Только Vue/React ОЧЕНЬ нужен сервер узла, если вы хотите выполнять рендеринг на стороне сервера, но эта функция не всегда нужна (мягко говоря).

acdcjunior 04.05.2019 21:29

Да, я знаю, особенно Vue можно использовать на стороне браузера, но использование компонентов становится намного сложнее. Короче говоря, вы не можете использовать файлы .vue в браузере.

JacopoStanchi 04.05.2019 21:34

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