Polímero - Shadow DOM y Styling

Shadow DOM es una nueva propiedad de DOM utilizada para construir componentes.

Example

En el siguiente código, el componente de encabezado incluye el título de la página y el botón de menú.

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

Shadow DOM permite ubicar a los niños en un subárbol con ámbito, que se conoce como shadow tree.

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

La raíz de la raíz de la sombra se llama como la parte superior del árbol de la sombra y el elemento que se adjunta al árbol se llama host de la sombra (encabezado-demo). Este host de sombra incluye una propiedad llamada shadowRoot, que especifica la raíz de sombra. La raíz oculta identifica el elemento del host mediante una propiedad del host.

Shadow DOM y composición

El árbol de sombra se puede representar en lugar de los elementos secundarios del elemento, si hay un elemento en el DOM de sombra. Los elementos secundarios del elemento se pueden representar agregando el elemento <slot> al árbol de sombra.

Por ejemplo, use el siguiente árbol de sombras para <header-demo>.

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

Agregue los hijos al elemento <my-header> como -

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

El encabezado reemplaza el elemento </slot> con los elementos secundarios especificados anteriormente como -

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

Contenido de reserva

El contenido de reserva se puede mostrar cuando no hay nodos asignados a la ranura. Por ejemplo

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

Puede proporcionar su propio icono para un elemento como:

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

Distribución multinivel

Puede asignar el elemento de ranura a una ranura, lo que se conoce como distribución multinivel.

Por ejemplo, tome dos niveles de un árbol de sombras como se muestra a continuación:

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

Considere el siguiente código:

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

La estructura de un árbol aplanado se parece a la siguiente.

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

Shadow DOM utiliza las siguientes API de ranuras para verificar la distribución:

  • HTMLElement.assignedSlot - Asigna la ranura para un elemento y devuelve nulo, si no hay asignación de un elemento a una ranura.

  • HTMLSlotElement.assignedNodes - Proporciona la lista de nodos junto con la ranura y devuelve los nodos distribuidos, cuando establece la opción aplanar en verdadero.

  • HTMLSlotElement.slotchange - Este evento se activa cuando hay cambios en los nodos distribuidos de la ranura.

Retargeting de eventos

Especifica el destino del evento en el que el elemento se puede representar en el mismo ámbito que el elemento de escucha. Proporciona un evento de un elemento personalizado, que parece provenir de la etiqueta del elemento personalizado, a diferencia de un elemento dentro.

Example

El siguiente ejemplo muestra el uso de retargeting de eventos en Polymer.js. Cree un archivo llamado index.html y coloque el siguiente código en él.

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

Ahora, cree otro archivo llamado retarget-event.html e incluya el siguiente código.

<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

Para ejecutar la aplicación, navegue hasta el directorio del proyecto creado y ejecute el siguiente comando.

polymer serve

Ahora abra el navegador y navegue hasta http://127.0.0.1:8081/. Lo siguiente será la salida.

Haga clic en el texto anterior y abra la consola para ver un evento reorientado como se muestra en la siguiente captura de pantalla.

Estilo Shadow DOM

Puede diseñar el DOM de sombra utilizando las propiedades de estilo, que heredan del host al árbol de sombra.

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>

Plantillas DOM

El subárbol DOM se puede crear para un elemento utilizando la plantilla DOM. Puede crear la raíz de sombra para el elemento y copiar la plantilla en un árbol de sombra agregando la plantilla DOM a un elemento.

La plantilla DOM se puede especificar de dos formas:

  • Cree un elemento <dom-module>, que debe coincidir con el nombre de un elemento junto con un atributo id.

  • Defina un elemento <template> dentro del <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>

Aplicar estilo a la sombra DOM de un elemento

Shadow DOM permite diseñar los elementos personalizados utilizando propiedades de estilo como fuentes, colores de texto y clases, sin aplicarlo fuera del alcance de su elemento.

Diseñemos el elemento anfitrión usando el :hostselector (un elemento adjunto a la sombra DOM se llama como el host). Cree un archivo llamado polímero-app.html y agregue el siguiente código en él.

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

Ejecute la aplicación como se muestra en el capítulo anterior y navegue hastahttp://127.0.0.1:8000/. Lo siguiente será la salida.

Estilo de contenido ranurado

Es posible crear slots en la plantilla de un elemento, que están ocupados en tiempo de ejecución.

Example

El siguiente ejemplo muestra el uso de contenido ranurado en la plantilla del elemento. Cree un archivo index.html y agregue el siguiente código en él.

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

Ahora cree otro archivo llamado slotted-content.html e incluya el siguiente código.

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

Ejecute la aplicación como se muestra en el ejemplo anterior y navegue hasta http://127.0.0.1:8081/. Lo siguiente será la salida.

Usar módulos de estilo

Puede compartir los estilos entre elementos junto con módulos de estilo. Especifique los estilos en el módulo de estilo y compártalos entre los elementos.

Example

El siguiente ejemplo muestra cómo utilizar el módulo de estilo entre los elementos. Cree un archivo index.html y agregue el siguiente código en él.

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

Cree otro archivo llamado style-module.html con el siguiente código.

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

Ahora, cree un archivo más llamado colors-module.html , que proporciona los módulos de estilo a los elementos como se muestra en el siguiente código.

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

Ejecute la aplicación y navegue hasta http://127.0.0.1:8081/. Lo siguiente será la salida.

Usar propiedades personalizadas

Las propiedades CSS personalizadas se pueden usar para diseñar la apariencia del elemento en su aplicación usando el elemento Polymer. Las propiedades personalizadas proporcionan variables CSS en cascada, que se pueden usar fuera del entorno de elementos personalizados que evitan que los datos de estilo se dispersen a través de una hoja de estilo.

Las propiedades personalizadas se pueden definir de forma similar a las propiedades CSS estándar, que heredan del árbol DOM compuesto. En el ejemplo anterior, puede ver las propiedades CSS personalizadas definidas para los elementos.

Según la herencia CSS, si no hay un estilo definido para un elemento, heredará el estilo de su padre como se muestra en el siguiente código.

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