Полимер - Shadow DOM и стили

Shadow DOM - это новое свойство DOM, используемое для создания компонентов.

Example

В следующем коде компонент заголовка включает заголовок страницы и кнопку меню.

<header-demo>
   <header>
      <h1>
         <button>

Shadow DOM позволяет размещать потомков в поддереве с заданной областью видимости, которое известно как shadow tree.

<header-demo>
   #shadow-root
   <header>
      <h1>
      <button>

Корень теневого корня называется вершиной теневого дерева, а элемент, который прикреплен к дереву, называется теневым хостом (демонстрационный заголовок). Этот теневой хост включает свойство shadowRoot, которое определяет корень тени. Теневой корень идентифицирует элемент хоста с помощью свойства хоста.

Теневой DOM и композиция

Теневое дерево может быть отрисовано вместо дочерних элементов, если в теневой DOM есть элемент. Дочерние элементы элемента можно отобразить, добавив элемент <slot> в теневое дерево.

Например, используйте следующее теневое дерево для <header-demo>.

<header>
   <h1><slot></slot></h1>
   <button>Menu</button>
</header>

Добавьте дочерние элементы в элемент <my-header> как -

<header-demo>Shadow DOM</header-demo>

Заголовок заменяет элемент </slot> указанными выше дочерними элементами как -

<header-demo>
   <header>
      <h1>Shadow DOM</h1>
      <button>Menu</button>
   </header>
</header-demo>

Резервный контент

Резервный контент может отображаться, когда слоту не выделено ни одного узла. Например -

<my-element>
   #shadow-root
   <slot id = "myimgicon">
      <img src = "img-demo.png">
   </slot>
   <slot></slot>
<my-element>

Вы можете предоставить свой собственный значок для элемента как -

<my-element>
   <img slot = "myimgicon" src = "warning.png">
<my-element>

Многоуровневое распределение

Вы можете назначить элемент слота в слот, что называется многоуровневым распределением.

Например, возьмите два уровня теневого дерева, как показано ниже -

<parent-element>
   #shadow-root
      <child-element>
      <!-- display the light DOM children of parent-element inside child-element -->
      <slot id = "parent-slot">
	  
   <child-element>
      #shadow-root
         <div>
            <!-- Render the light DOM children inside div by using child-element -->
            <slot id = "child-slot">

Рассмотрим следующий код -

<parent-element>
   <p>This is light DOM</p>
<parent-element>

Структура сплющенного дерева выглядит следующим образом.

<parent-element>
   <child-element>
      <div>
         <slot id = "child-slot">
            <slot id = "parent-slot">
               <p>This is light DOM</p>

Shadow DOM использует следующие API слотов для проверки распределения:

  • HTMLElement.assignedSlot - Он выделяет слот для элемента и возвращает ноль, если элемент не назначен слоту.

  • HTMLSlotElement.assignedNodes - Он предоставляет список узлов вместе со слотом и возвращает распределенные узлы, когда вы устанавливаете для параметра сглаживания значение true.

  • HTMLSlotElement.slotchange - Это событие запускается, когда есть изменения в распределенных узлах слота.

Ретаргетинг событий

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

Example

В следующем примере показано использование ретаргетинга событий в Polymer.js. Создайте файл с именем index.html и поместите в него следующий код.

<!doctype html>
<html>
   <head>
      <title>Polymer Example</title>
      <script src = "bower_components/webcomponentsjs/webcomponents-lite.js"></script>
      <link rel = "import" href = "bower_components/polymer/polymer.html">
      <link rel = "import" href = "retarget-event.html">
   </head>
   
   <body>
      <template id = "myapp" is = "dom-bind">
         <retarget-event on-tap = "clicky"></retarget-event>
      </template>
      
      <script>
         var myval = document.querySelector('#myapp');
         myval.clicky = function(e) {
            console.log("The retargeted result:", Polymer.dom(myval));
            console.log("Normal result:", e);
         };
      </script>
   </body>
</html>

Теперь создайте еще один файл с именем retarget-event.html и включите следующий код.

<link rel = "import" href = "bower_components/polymer/polymer-element.html">

//it specifies the start of an element's local DOM
<dom-module id = "retarget-event">

   <template>
      <span>Click on this text to see result in console...</span>
   </template>

   <script>
      Polymer ({
         is: 'retarget-event',
      });
   </script>
</dom-module>

Output

Чтобы запустить приложение, перейдите в каталог созданного проекта и выполните следующую команду.

polymer serve

Теперь откройте браузер и перейдите к http://127.0.0.1:8081/. Ниже будет вывод.

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

Стиль Shadow DOM

Вы можете стилизовать теневую DOM, используя свойства стиля, которые наследуются от хоста к теневому дереву.

Example

<style>
   .mydemo { background-color: grey; }
</style>

<my-element>
#shadow-root
   <style>
      //this div will have blue background color
      div { background-color: orange; }
   </style>
   <div class = "mydemo">Demo</div>

Шаблоны DOM

Поддерево DOM может быть создано для элемента с помощью шаблонов DOM. Вы можете создать теневой корень для элемента и скопировать шаблон в теневое дерево, добавив шаблон DOM к элементу.

Шаблон DOM можно указать двумя способами:

  • Создайте элемент <dom-module>, который должен соответствовать имени элемента вместе с атрибутом id.

  • Определите элемент <template> внутри <dom-module>.

Example

<dom-module id = "my-template">
   <template>I am in my template!!!</template>

   <script>
      class MyTemplate extends Polymer.Element {
         static get is() { return  'my-template' }
      }
      customElements.define(MyTemplate.is, MyTemplate);
   </script>
</dom-module>

Стиль теневого DOM элемента

Shadow DOM позволяет стилизовать пользовательские элементы, используя свойства стиля, такие как шрифты, цвета текста и классы, не применяя его за пределами области действия вашего элемента.

Давайте стилизуем элемент хоста, используя :hostселектор (элемент, прикрепленный к теневой DOM, называется хостом). Создайте файл с именем полимер-app.html и добавьте в него следующий код.

<link rel = "import" href = "../../bower_components/polymer/polymer-element.html">

<dom-module id = "polymer-app">
   <template>
      <style>
         :host {
            color:#33ACC9;
         }
      </style>
      <h2>Hello...[[myval]]!</h2>	
  </template>

  <script>
      class PolymerApp extends Polymer.Element {
         static get is() { return 'polymer-app'; }
         static get properties() {
            return {
               myval: {
                  type: String, value: 'Welcome to Tutorialspoint!!!'
               }
            };
         }
      }

      window.customElements.define(PolymerApp.is, PolymerApp);
   </script>
</dom-module>

Запустите приложение, как показано в предыдущей главе, и перейдите кhttp://127.0.0.1:8000/. Ниже будет вывод.

Содержимое со стилем

Возможно создание slots в шаблоне элемента, которые заняты во время выполнения.

Example

В следующем примере показано использование содержимого в шаблоне элемента. Создайте файл index.html и добавьте в него следующий код.

<!doctype html>
<html>
   <head>
      <title>Polymer Example</title>
      <link rel = "import" href = "bower_components/polymer/polymer.html">
      <link rel = "import" href = "slotted-content.html">
   </head>
   
   <body>
      <slotted-content>
         <div slot = "text">This is Polymer.JS Slotted Content Example</div>
      </slotted-content> 
   </body>
</html>

Теперь создайте еще один файл с именем slotted-content.html и включите следующий код.

<link rel = "import" href = "bower_components/polymer/polymer-element.html">

<dom-module id = "slotted-content">
   <template>
      <style>
         ::slotted(*) {
            font-family: sans-serif;
            color:#E94A9D;
         }
      </style>
      
      <h2>Hello...[[prop1]]</h2>
      <h3>
         <div><slot name='text'></slot></div>
      </h3>
   </template>
   
   <script>
      Polymer ({
         is: 'slotted-content', properties: {
            prop1: {
               type: String,
               value: 'Welcome to Tutorialspoint!!',
            },
         },
      });
   </script>
</dom-module>

Запустите приложение, как показано в предыдущем примере, и перейдите к http://127.0.0.1:8081/. Ниже будет вывод.

Использование модулей стилей

Вы можете использовать стили между элементами вместе с модулями стилей. Укажите стили в модуле стиля и поделитесь ими между элементами.

Example

В следующем примере показано, как использовать модуль стиля между элементами. Создайте файл index.html и добавьте в него следующий код.

<!doctype html>
<html>
   <head>
      <title>Polymer Example</title>
      <link rel = "import" href = "bower_components/polymer/polymer.html">
      <link rel = "import" href = "style-module.html">
   </head>
   
   <body>
      <style-module></style-module> 
   </body>
</html>

Создайте еще один файл с именем style-module.html со следующим кодом.

<link rel = "import" href = "bower_components/polymer/polymer-element.html">

<dom-module id = "style-module">
   <template>
      <!-- here, including the imported styles from colors-module page -->
      <style include="colors-module"></style>
      <style>
         :host {
            font-family: sans-serif;
            color: green;    
         }
      </style>
      
      <h2>Hello...[[prop1]]</h2>
      <p class = "color1">Sharing styles with style modules 1...</p>
      <p class = "color2">Sharing styles with style modules 2...</p>
      <p class = "color3">Sharing styles with style modules 3...</p>
   </template>
   
   <script>
      Polymer ({
         is: 'style-module', properties: {
            prop1: {
               type: String, value: 'Welcome to Tutorialspoint!!',
            },
         },
      });
   </script>
</dom-module>

Теперь создайте еще один файл с именем colors-module.html , который предоставляет модули стилей для элементов, как показано в следующем коде.

<link rel = "import" href = "bower_components/polymer/polymer-element.html">

<dom-module id = 'colors-module'>
   <template>
      <style>
         p.color1 {
            color: #EA5AA5;
         }
         p.color2 {
            color: #4B61EA;
         }
         p.color3 {
            color: #D3AA0A;
         }
      </style>
   </template>
</dom-module>

Запустите приложение и перейдите к http://127.0.0.1:8081/. Ниже будет вывод.

Использовать настраиваемые свойства

Пользовательские свойства CSS можно использовать для стилизации внешнего вида элемента в вашем приложении с помощью элемента Polymer. Настраиваемые свойства предоставляют каскадные переменные CSS, которые можно использовать вне среды настраиваемых элементов, которые не допускают разброса данных стиля по таблице стилей.

Пользовательские свойства могут быть определены аналогично стандартным свойствам CSS, которые наследуются от составного дерева DOM. В предыдущем примере вы можете увидеть настраиваемые свойства CSS, определенные для элементов.

При наследовании CSS, если для элемента не определен стиль, он унаследует стиль от своего родителя, как показано в следующем коде.

<link rel = "import" href = "components/polymer/myelement-style.html">
<myelement-style>
   <style is = "myelement-style">
      p {
         color: var(--paper-red-900);
      }
      paper-checkbox {
         --paper-checkbox-checked-color: var(--paper-red-900);
      }
   </style>
</myelement-style>

<body>
   <p><paper-checkbox>Check Here</paper-checkbox></p>
</body>