Estoy trabajando en un componente web y tengo problemas para conectar la función JS que aleatoriza los colores. Lo que he logrado hasta ahora son diferentes estilos para el elemento DOM global y DOM sombra <h3> (oración 1 y oración 2 respectivamente). Lo que necesito es el elemento shadow DOM <h3> para aplicar colores aleatorios de la matriz que se encuentra en la función changeColor(). ¿Alguna idea sobre cómo puedo incorporar la función en el shadow DOM?
const template = document.createElement('template'); template.innerHTML = ` <style> h3 { color: coral; } </style> <h3>Sentence 2 </h3> `; class UserCard extends HTMLElement { constructor() { super(); this.attachShadow({mode: 'open'}); this.shadowRoot.appendChild(template.content.cloneNode(true)); } }; window.customElements.define('user-card', UserCard); function changeColor() { let num = 0; let arr = ['#FFD640;', '#fdff76', '#f0cd59', '#fa9624', '#fa6824', '#a33f11']; window.setInterval(function () { num = (num + 1) % 4; document.querySelector('h3').style.color = arr[Math.floor(Math.random() * arr.length)]; }, 1000); } <!DOCTYPE html> <html lang = "en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Web Components Example</title> </head> <body> <h3>Sentence 1</h3> <user-card> <script src="userCard.js"></script> </user-card> </body> </html>Yo lo acortaría a:
customElements.define('user-card', class extends HTMLElement { constructor() { super().attachShadow({mode:"open"}) .innerHTML = "<style>h3{color:coral}</style><h3>Sentence 2 </h3>"; let arr = ['#FFD640;', '#fdff76', '#f0cd59', '#fa9624', '#fa6824', '#a33f11']; setInterval(() => { let newColor = arr[Math.floor(Math.random() * arr.length)]; this.shadowRoot.querySelector('h3').style.color = newColor; }, 100); } }); <user-card></user-card>class separada solo se requiere cuando necesita usarla varias vecessuper conjuntos Y devuelve el alcance 'esto', para que pueda encadenarloattachShadow establece Y devuelve this.shadowRoot , para que pueda encadenarlo<templates> solo tiene sentido para HTML más complejo, use .innerHTML para las cosas fácilessetInterval en this.changeColor (requerido si desea finalizar el ciclo) Pero luego lo está llamando como una función... vea: https://developer.mozilla.org/en-US/ docs/Web/API/setIntervalOtra opción sería pasar el context para querySelector a changeColor , con document como predeterminado si no se pasa ningún contexto. De esta manera, changeColor se vuelve más flexible y al mismo tiempo conserva la compatibilidad con versiones anteriores.
const template = document.createElement('template'); template.innerHTML = ` <style> h3 { color: coral; } </style> <h3>Sentence 2 </h3> `; class UserCard extends HTMLElement { constructor() { super(); this.attachShadow({mode: 'open'}); this.shadowRoot.appendChild(template.content.cloneNode(true)); changeColor(this.shadowRoot); } }; window.customElements.define('user-card', UserCard); function changeColor(context = document) { let num = 0; let arr = ['#FFD640;', '#fdff76', '#f0cd59', '#fa9624', '#fa6824', '#a33f11']; window.setInterval(function () { num = (num + 1) % 4; context.querySelector('h3').style.color = arr[Math.floor(Math.random() * arr.length)]; }, 1000); } <!DOCTYPE html> <html lang = "en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Web Components Example</title> </head> <body> <h3>Sentence 1</h3> <user-card> <script src="userCard.js"></script> </user-card> </body> </html>Defina los colores en la clase como una propiedad. Cree una función o un captador para recuperar el elemento h3 de Shadow DOM para facilitar el acceso.
Los elementos personalizados tienen ciclos de vida, lo que significa que tiene ciertos métodos que se llamarán en ciertos momentos según el contexto. Se llamará a connectedCallback cuando el elemento se coloque dentro del DOM principal y se asegurará de que su componente esté renderizado y listo. Allí llame a su lógica setInterval . Cambie la declaración de function() a una función de flecha () => para asegurarse de que this palabra clave apunte al componente.
const template = document.createElement('template'); template.innerHTML = ` <style> h3 { color: coral; } </style> <h3>Sentence 2</h3> `; class UserCard extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); } colors = ['#FFD640', '#fdff76', '#f0cd59', '#fa9624', '#fa6824', '#a33f11']; get heading() { return this.shadowRoot.querySelector('h3'); } connectedCallback() { window.setInterval(() => { this.heading.style.color = this.colors[Math.floor(Math.random() * this.colors.length)]; }, 1000); } }; window.customElements.define('user-card', UserCard); <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Web Components Example</title> </head> <body> <h3>Sentence 1</h3> <user-card></user-card> <script src="userCard.js"></script> </body> </html>