Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
123 lines (73 sloc) 9.09 KB

Импорты

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

Зачем?

Мы ведь и так можем вставлять документ в документ, при помощи <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 импортируется повторно -- подключается уже готовый документ, без повторного выполнения скриптов в нём. Это позволяет избежать дублирования при использовании одной библиотеки во множестве мест.