Skip to content

Latest commit

 

History

History
124 lines (74 loc) · 9.1 KB

File metadata and controls

124 lines (74 loc) · 9.1 KB

Импорты

Новая спецификация "HTML Imports" описывает, как вставить один документ в другой при помощи HTML-тега <link rel="import">.

[cut]

Зачем?

Мы ведь и так можем вставлять документ в документ, при помощи <iframe>, зачем нужен ещё какой-то импорт? Что не так с iframe?

...С iframe всё так. Однако, по своему смыслу iframe -- это отдельный документ.

  • Для iframe создаётся полностью своё окружение, у него свой объект window и свои переменные.
  • Если iframe загружен с другого домена, то взаимодействие с ним возможно только через postMessage.

Это хорошо, когда нужно действительно в одной странице отобразить содержимое другой.

А что, если нужно встроить другой документ как естественную часть текущего? С единым скриптовым пространством, едиными стилями, но при этом -- другой документ.

Например, это нужно для подгрузки внешних частей документа (веб-компонент) снаружи. И желательно не иметь проблем с разными доменами: если уж мы действительно хотим подключить HTML с одного домена в страницу на другом -- мы должны иметь возможность это сделать без "плясок с бубном".

Иначе говоря, <link rel="import"> -- это аналог <script>, но для подключения полноценных документов, с шаблонами, библиотеками, веб-компонентами и т.п. Всё станет понятнее, когда мы посмотрим детали.

Пример вставки

Синтаксис:

<link rel="import" href="http://site.com/document.html">
  • В отличие от <iframe> тег <link rel="import"> может быть в любом месте документа, даже в <head>.
  • При вставке через <iframe> документ показывается внутри фрейма. В случае с <link rel="import"> это не так, по умолчанию документ вообще не показывается.

HTML, загруженный через <link rel="import"> имеет отдельный DOM документа, но скрипты в нём выполняются в общем контексте страницы.

Файл, загруженный через <link rel="import">, обрабатывается, выполняются скрипты, строится DOM документа, но не показывается, а записывается в свойство link.import.

Мы сами решаем, где и когда его вставить.

В примере ниже <link rel="import" href="timer.html"> подключает документ timer.html и, после его загрузки, вызывает функцию show. Эта функция через link.import.querySelector('time') выбирает интересующую часть подгруженного документа и вставляет её в текущий:

[html src="import-show/index.html"]

В файле timer.html находится элемент и скрипт, который его "оживляет":

[html src="import-show/timer.html"]

[codetabs src="import-show" height=350]

Важные детали:

  • После загрузки все скрипты в подключённом timer.html выполняются в контексте основной страницы, так что timer и другие переменные станут глобальными переменными страницы.
  • Переменная document -- это документ основной страницы. Для доступа к импортированному, то есть текущему документу изнутри timer.html его можно получить как document.currentScript.ownerDocument.
  • Таймер в загруженном документе начинает работать сразу, новый документ оживает сразу после загрузки, хотя до переноса узлов в основной документ этого может быть и не видно.

В примере выше содержимым импорта управлял основной документ, но timer.html мог бы и показать сам себя вызовом document.body.appendChild(timer) или вызвать функцию с внешнего документа, так как у них единая область видимости. Тогда не понадобился бы никакой onload.

Ещё пример вставки, на этот раз документ только подключает <link>, а таймер вставляет себя сам:

[codetabs src="import-style" height="200"]

Обратим внимание -- стили импорта попадают в контекст страницы. В примере выше импорт добавил и стиль для #timer и сам элемент.

Веб-компоненты

Импорт задуман как часть платформы Web Components.

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

Пример:

<link rel="import" href="ui-tabs.html">
<link rel="import" href="ui-dialog.html">

<ui-tabs>...</ui-tabs>
<ui-dialog>...</ui-dialog>

В следующей главе мы разберём расширенный пример на эту тему.

Повторное использование

Повторный импорт с тем же URL использует уже существующий документ.

Если файл libs.html импортирован два раза, то CSS и скрипты из него подключатся и выполнятся ровно один раз.

Это можно использовать, чтобы не подгружать одинаковые зависимости много раз. И сама страница и её импорты, и их подимпорты, и так далее, могут подключать libs.html без опасения лишний раз перезагрузить и выполнить скрипты.

Например:

  • Главный файл index.html подключает документы:

    <link rel="import" href="ui-tabs.html">
    <link rel="import" href="ui-dialog.html">
    ...
  • ui-tabs.html подключает libs.html:

    <link rel="import" href="libs.html">
    ...template и код для табов...
  • ui-dialog.html также использует libs.html:

    <link rel="import" href="libs.html">
    ...template и код для диалогов...

Файл libs.html при этом будет подключен только один раз. Это позволяет не бояться лишнего дублирования библиотек, используемых при описании множества компонент.

Итого

Тег <link rel="import"> позволяет подключить любой документ к странице, причём:

  • Скриптовое пространство и стили со страницей будут общие.
  • Документ DOM -- отдельный, он доступен как link.import снаружи, а из внутреннего скрипта -- через document.currentScript.ownerDocument. Можно без проблем переносить элементы из главного документа в импорт и наоборот.
  • Импорты могут содержать другие импорты.
  • Если какой-то URL импортируется повторно -- подключается уже готовый документ, без повторного выполнения скриптов в нём. Это позволяет избежать дублирования при использовании одной библиотеки во множестве мест.