Polymère - Shadow DOM et style

Shadow DOM est une nouvelle propriété de DOM utilisée pour la construction de composants.

Example

Dans le code suivant, le composant d'en-tête comprend le titre de la page et le bouton de menu.

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

Shadow DOM permet de localiser les enfants dans une sous-arborescence étendue, connue sous le nom de shadow tree.

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

La racine shadow-root est appelée comme le sommet de l'arbre d'ombre et l'élément qui est attaché à l'arbre est appelé hôte d'ombre (en-tête-démo). Cet hôte fantôme comprend une propriété appelée shadowRoot, qui spécifie la racine de l'ombre. La racine fantôme identifie l'élément hôte à l'aide d'une propriété hôte.

Shadow DOM et composition

L'arbre de l'ombre peut être rendu à la place des enfants de l'élément, s'il y a un élément dans le DOM de l'ombre. Les enfants de l'élément peuvent être rendus en ajoutant l'élément <slot> à l'arbre d'ombre.

Par exemple, utilisez l'arbre d'ombre suivant pour <header-demo>.

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

Ajoutez les enfants à l'élément <my-header> comme -

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

L'en-tête remplace l'élément </slot> par les enfants spécifiés ci-dessus comme -

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

Contenu de secours

Le contenu de secours peut être affiché lorsqu'aucun nœud n'est alloué à l'emplacement. Par exemple -

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

Vous pouvez fournir votre propre icône pour un élément comme -

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

Distribution à plusieurs niveaux

Vous pouvez allouer l'élément slot à un slot, qui est connu sous le nom de distribution multi-niveaux.

Par exemple, prenez deux niveaux d'un arbre d'ombre comme indiqué ci-dessous -

<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">

Considérez le code suivant -

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

La structure d'un arbre aplati ressemble à ce qui suit.

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

Shadow DOM utilise les API Slot suivantes pour vérifier la distribution -

  • HTMLElement.assignedSlot - Il alloue l'emplacement pour un élément et retourne null, s'il n'y a pas d'allocation d'un élément à un emplacement.

  • HTMLSlotElement.assignedNodes - Il fournit la liste des nœuds avec le slot et renvoie les nœuds distribués, lorsque vous définissez l'option aplatir sur true.

  • HTMLSlotElement.slotchange - Cet événement se déclenche lorsqu'il y a des changements dans les nœuds distribués du slot.

Reciblage d'événements

Il spécifie la cible de l'événement dans laquelle l'élément peut être représenté dans la même portée que l'élément d'écoute. Il fournit un événement à partir d'un élément personnalisé, qui semble provenir de la balise d'élément personnalisé, par opposition à un élément à l'intérieur.

Example

L'exemple suivant montre l'utilisation du reciblage d'événements dans Polymer.js. Créez un fichier appelé index.html et mettez-y le code suivant.

<!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>

Maintenant, créez un autre fichier appelé retarget-event.html et incluez le code suivant.

<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

Pour exécuter l'application, accédez au répertoire de projet créé et exécutez la commande suivante.

polymer serve

Ouvrez maintenant le navigateur et accédez à http://127.0.0.1:8081/. Voici la sortie.

Cliquez sur le texte ci-dessus et ouvrez la console pour voir un événement reciblé, comme illustré dans la capture d'écran suivante.

Style de l'ombre DOM

Vous pouvez styliser le DOM de l'ombre à l'aide des propriétés de style, qui héritent de l'hôte de l'arbre des ombres.

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>

Modèles DOM

Le sous-arbre DOM peut être créé pour un élément à l'aide du modèle DOM. Vous pouvez créer la racine d'ombre de l'élément et copier le modèle dans un arbre d'ombre en ajoutant un modèle DOM à un élément.

Le modèle DOM peut être spécifié de deux manières -

  • Créez un élément <dom-module>, qui doit correspondre au nom d'un élément avec un attribut id.

  • Définissez un élément <template> dans le <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>

Styliser le DOM Shadow d'un élément

Shadow DOM permet de styliser les éléments personnalisés en utilisant des propriétés de style telles que les polices, les couleurs de texte et les classes, sans l'appliquer en dehors de la portée de votre élément.

Stylisons l'élément hôte en utilisant le :hostselector (un élément attaché au shadow DOM est appelé en tant qu'hôte). Créez un fichier appelé polymer-app.html et ajoutez-y le code suivant.

<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>

Exécutez l'application comme indiqué dans le chapitre précédent et accédez àhttp://127.0.0.1:8000/. Voici la sortie.

Contenu fendu de style

Il est possible de créer slots dans le modèle d'un élément, qui sont occupés au moment de l'exécution.

Example

L'exemple suivant illustre l'utilisation de contenu fendu dans le modèle de l'élément. Créez un fichier index.html et ajoutez-y le code suivant.

<!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>

Créez maintenant un autre fichier appelé slotted-content.html et incluez le code suivant.

<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>

Exécutez l'application comme indiqué dans l'exemple précédent et accédez à http://127.0.0.1:8081/. Voici la sortie.

Utilisation des modules de style

Vous pouvez partager les styles entre les éléments avec des modules de style. Spécifiez les styles dans le module de style et partagez-les entre les éléments.

Example

L'exemple suivant montre comment utiliser le module de style entre les éléments. Créez un fichier index.html et ajoutez-y le code suivant.

<!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>

Créez un autre fichier appelé style-module.html avec le code suivant.

<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>

Maintenant, créez un autre fichier appelé colors-module.html , qui fournit les modules de style aux éléments comme indiqué dans le code suivant.

<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>

Exécutez l'application et accédez à http://127.0.0.1:8081/. Voici la sortie.

Utiliser les propriétés personnalisées

Les propriétés CSS personnalisées peuvent être utilisées pour styliser l'apparence de l'élément dans votre application à l'aide de l'élément Polymer. Les propriétés personnalisées fournissent des variables CSS en cascade, qui peuvent être utilisées en dehors de l'environnement des éléments personnalisés qui évitent de disperser les données de style dans une feuille de style.

Les propriétés personnalisées peuvent être définies de la même manière que les propriétés CSS standard, qui héritent de l'arborescence DOM composée. Dans l'exemple précédent, vous pouvez voir les propriétés CSS personnalisées définies pour les éléments.

Sous l'héritage CSS, s'il n'y a pas de style défini pour un élément, il héritera du style de son parent comme indiqué dans le code suivant.

<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>