No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Shadow DOM

9/22
Recursos

Aportes 13

Preguntas 3

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

una pregunta:
no se ve penalizado el SEO cuando se usa shadowDOM? si bien el navegador puede saber cual es el contenido del elemento, lo sabe el indexador de google?
sabe lo que es un h1 si est谩 dentro de un shadowDOM?

Si desean visualizar el c贸digo html que se encuentra en los archivos .JS instalen la extensi贸n
**es6-string-html **
para visual studio code y coloque el comentario antes de codear en etiquetas como muestro en la imagen a continuaci贸n:

https://i.imgur.com/wbL6voa.png

Shadow DOM

Con esta implementaci贸n podremos solucionar los problemas con los estilos css que se rescriben por temas de especificidad.

Generando como un encapsulado, un dom independiente dentro de nuestro dom global, esto que quiere decir que todo lo que coexista en nuestro dom independiente no va existir dentro de nuestro dom global.

class myElement extends HTMLElement{
  
  constructor(){
    super();
    //Venimos al constructor que es donde generamos la instancia de esta api
      //Agregamos shadow down (API) y lo ponemos en modo open
    this.attachShadow({mode:"open"})
    
  }

  getTemplate(){

    const template = document.createElement('template');
    template.innerHTML = `
      <section>

        <h2>Hola mundo!</h2>
        <div>

          <p> Soy text ejemplo<p>
        
        </div>
      
      </section>

      ${this.getStyles()}

    `;
    return template
  }

  getStyles(){
    return`

      <style>
        h2{

          color:red;
        }
      </style>
    
    `
  }

  render(){

    //Ahora poder renderizar nuestros templates tenemos que cambiar el contexto
     //Donde agregamos nuestro template ya que lo estabamos agregando al dom global
      //Ahora debemos agregarlo en nuestro shadow dom que es otro contexto diferene
    this.shadowRoot.appendChild(this.getTemplate().content.cloneNode(true))

  }

  
  connectedCallback(){

    this.render();
    

  }

}

customElements.define('my-element', myElement);

Es importante activar el shadow dom para poderlo visualmente en nuestro inspector de elementos
.

Shadow DOM

El API de DOM Shadow es un parte clave para esto, proporcionando una forma de enlazar un DOM oculto y separado a un elemento. Este art铆culo cubre los aspectos b谩sicos para utilizar Shadow DOM.

El Shadow聽DOM permite adjuntar arboles聽DOM ocultos a elementos en el 谩rbol DOM regular, este 谩rbol Shadow DOM comienza con un elemento聽Shadow Root,聽debajo del聽cual se puede adjuntar聽cualquier elemento que desee, de la misma manera que el DOM normal.

Hay algunos conceptos de Shadow DOM que deben ser tomados en cuenta:

  • Shadow host: El nodo regular del DOM al que es atado el shadow DOM.
  • Shadow tree: El 谩rbol DOM dentro del shadow DOM.
  • Shadow boundary: El punto en el que el shadow DOM termina聽y el DOM regular comienza.
  • Shadow root: El nodo ra铆z del 谩rbol Shadow.

Puede adjuntar un shadow root a cualquier elemento utilizamos el m茅todo聽Element.attachShadow (). 脡ste聽toma como par谩metro un objeto聽que contiene una propiedad mode con dos posibles valores:聽open o closed.

open: Significa que puede acceder聽al shadow DOM usando JavaScript en el contexto principal de la p谩gina. Por ejemplo, usando la propiedad Element.shadowRoot

closed: Significa que no se puede acceder al shadow Dom desde afuera, como con la etiqueta video.

Ohhh vale, ya v铆 en donde se usa el template, ese template que est谩 ahi en el HTML no sirve para nada, el que s铆 sirve es el que creamos con el createElement jaja.
.
Aun as铆 me sigue causando conflicto que tenemos que usar innerHTML para poder meter el contenido del template xc

Shadow DOM

Shadow DOM se puede entender como un DOM independiente de el Documento principal, ya que los estilos que escribamos ac谩 no afectan los elementos externos del DOM principal.
.

Esto nos ayuda a tener mejores pr谩cticas con CSS ya que no tendremos un colapso de estilos y evitaremos usar cosas como el !important.
.

Veamos con nuestro ejemplo anterior como implementarlo:

class MyElement extends HTMLElement {
  constructor ( ) {
    super();
    this.attachShadow({
      /* Permite interactuar con el componente viendo lo que tenemos
      dentro del mismo en una #shadow-root */
      mode: 'open'
    })
  }
	...
}

Si vemos ahora nuestro navegador, no veremos el componente, esto debido a que ya esta creado este DOM paralelo, pero en la estructura de HTML en el inspector nos muestra que hay un Shadow root

Entonces 驴Como lo renderizamos? Sencillo, simplemente en el m茅todo render debemos cambiar la manera como lo renderizamos en HTML. Esto lo haremos con la propiedad shadowRoot.

class MyElement extends HTMLElement {
  constructor ( ) {
		...
    })
  }
	
	...
  render() {
		/* Le decimos que acceda a la propiedad **shadowRoot** para que
		pueda renderizar el contenido del componente */
    this.shadowRoot.append(this.getTemplate().content.cloneNode(true));
  }
	...
}

Y si vemos ahora nuestro navegador, nuestro componente estar谩 renderizado 馃榿.

En esta URL hay una muy buena explicaci贸n sobre el funcinamiento del Shadow DOM y sus opciones.
https://www.todojs.com/shadow-dom-a-fondo/

muy interesante la clase

Apuntes de esta clase:

<h4>Shadow DOM</h4>

Esto nos ayudar谩 evitar problemas de estilos reescribiendose. Esto se lograr谩 por el encapsulado.

Pensemos en ShadowDOM como un DOM independiente adentro del DOM global, es por esto que los estilos estilos ser谩n independientes en cada uno.

this.attachShadow({mode: 'open'}); //*Casi siempre todos los componentes tiene que venir en modo abierto.
this.shadowRoot.append(this.getTemplate().content.cloneNode(true));
    //* Aqu铆 tenemos que especificar `shadowRoot` para que se agregue al DOM y se vea reflejado en el navegador

El tema de especifidad es un tema importante durante la declaracion de estilos y comprenderlo nos ayuda eliminarnos la pregunta de por que se rompio algo

https://platzi.com/clases/1665-preprocesadores/22294-selectores-de-css/
Esta clase me gusto y se aborda todo el tema de especifidad

Personalmente no me gusta usar el innerHTML (al inicio me gustaba porque era mas facil), ahora prefiero usar las herramientas del DOM asi que usandolas el codigo quedaria algo asi:

class MyShadowElement extends HTMLElement {
  constructor(){
    super();
    const shadowRoot = this.attachShadow({mode: "open"})
  }
  getTemplate() {
    let template = document.createElement('template');
    let header = document.createElement('header');
    let title = document.createElement('h1');
    title.innerText = 'My web Component';
    header.append(title);
    template.content.append(header);

    template.content.append(this.getStyles());

    return template;
  }
  getStyles() {
    const style = document.createElement('style');

    style.textContent = `
      header {
        box-sizing: border-box;
        width: 100%;
        height: 5rem;
        display: grid;
        place-items: center;
        background-color: orange;
        border-radius: 3px;
        padding: 15px;
      }
      h1 {
        color: purple;
        font-family: monospace;
        margin: 0;
      }
    `;
    return style;
  }
  render() {
    let template = this.getTemplate().content.cloneNode(true);
    this.shadowRoot.appendChild(template);
  }
  connectedCallback(){
    this.render();
  }
}
customElements.define('my-shadow-element', MyShadowElement);
麓麓麓

馃 鈥淐reado con la ayuda de una IA.鈥

Creaci贸n del componente personalizado

Para crear un componente personalizado en JavaScript, primero debes definir una clase que extienda la clase HTMLElement. Esta clase representa el nuevo elemento HTML personalizado.

class MyElement extends HTMLElement {
  // ...
}

Constructor

El constructor se llama cuando se crea una instancia del elemento personalizado. Puedes utilizarlo para realizar cualquier configuraci贸n necesaria, como adjuntar un shadow DOM.

constructor() {
  super(); // Llamada al constructor de la clase base
  this.attachShadow({ mode: "open" }); // Adjuntar shadow DOM
}

Shadow DOM

El Shadow DOM es una caracter铆stica de HTML que permite adjuntar un DOM separado y encapsulado a un elemento personalizado. Para crear un Shadow DOM, se utiliza el m茅todo attachShadow(), que permite encapsular la estructura del DOM y los estilos CSS, previniendo conflictos y manteniendo mayor claridad en el c贸digo.

this.attachShadow({ mode: "open" });

Generaci贸n de contenido

Para generar el contenido de un elemento personalizado, puedes crear una plantilla de HTML y utilizarla para generar el shadow DOM.

getTemplate() {
  const template = document.createElement('template');
  template.innerHTML = `
    <section>
      <h2 class="title">Soy un t铆tulo</h2>
      <div>
        <p>Soy un p谩rrafo</p>
      </div>
    </section>
    ${this.getStyles()}
  `;
  return template;
}

En este ejemplo, la funci贸n getTemplate() genera una plantilla que incluye un t铆tulo h2 y un p谩rrafo p. La funci贸n getStyles() se llama para incluir estilos personalizados.
.

Estilos personalizados

Puedes incluir estilos personalizados en un elemento personalizado utilizando el m茅todo getStyles(). Este m茅todo retorna un string con un bloque de estilos CSS que se incluir谩 en la plantilla de HTML.

getStyles() {
  return `
    <style>
      h2 {
        color: purple;
      }
    </style>
  `;
}

Renderizado

Una vez que has generado la plantilla de HTML, puedes utilizar la funci贸n render() para renderizar el contenido en el shadow DOM.

render() {
  this.shadowRoot.append(this.getTemplate().content.cloneNode(true))
}

La funci贸n render() llama al m茅todo append() en el shadow root del elemento personalizado para agregar el contenido generado por getTemplate() al 谩rbol DOM.
.

Conexi贸n al DOM

La funci贸n connectedCallback() se llama cuando el elemento personalizado se agrega al 谩rbol DOM. Puedes utilizar esta funci贸n para realizar cualquier configuraci贸n adicional, como renderizar el contenido.

connectedCallback() {
  this.render();
}

En este ejemplo, la funci贸n connectedCallback() llama a la funci贸n render() para renderizar el contenido del elemento personalizado.
.

Definici贸n del elemento personalizado

Finalmente, debes definir el nuevo elemento personalizado utilizando el m茅todo customElements.define(). Esto te permite utilizar el elemento en tu p谩gina web.

customElements.define('my-element', MyElement);

En este ejemplo, el nombre del elemento personalizado es my-element y la clase que lo define es MyElement.
.

Uso del elemento personalizado

Una vez que has definido tu elemento personalizado, puedes utilizarlo en cualquier p谩gina web. Para hacerlo, simplemente agrega el nuevo elemento personalizado a tu HTML como cualquier otro elemento HTML.

<my-element></my-element>

Esto es una locura!!!