bonus new member

https://librolibre.net/

https://lookingforlilith.org/

slot bet 100

slot

slot bet 100

https://lsphalal.id/data/?angka=inatogel

pasporbet

https://www.salemoregonhairsalon.com/

Un enfoque de carga diferida para elementos personalizados | trucos CSS

somos fans de Elementos personalizados Su diseño los hace particularmente susceptible a la carga diferidaque puede ser beneficioso para el rendimiento.

Inspirado por a un colega experimentos, recientemente me propuse escribir un cargador automático simple: cada vez que aparece un elemento personalizado en el DOM, queremos cargar la implementación correspondiente si aún no está disponible. El navegador luego se encarga de actualizar dichos elementos a partir de ahí.

Probablemente no necesites todo esto; generalmente hay un enfoque más simple. Usadas con delicadeza, las técnicas que se muestran aquí pueden ser una adición útil a su caja de herramientas.

Para mantener la coherencia, queremos que nuestro cargador automático también sea un elemento personalizado, lo que también significa que podemos configurarlo fácilmente a través de HTML. Pero primero, identifiquemos estos elementos personalizados sin resolver, paso a paso:

class AutoLoader extends HTMLElement {
  connectedCallback() {
    let scope = this.parentNode;
    this.discover(scope);
  }
}
customElements.define("ce-autoloader", AutoLoader);

Suponiendo que hayamos cargado este módulo de antemano (usando async es ideal), podemos soltar un <ce-autoloader> elemento en <body> de nuestro documento. Esto iniciará inmediatamente el proceso de descubrimiento para todos los hijos de la <body>que ahora constituye nuestro elemento principal. Podemos limitar el descubrimiento a un subárbol de nuestro documento agregando <ce-autoloader> en su lugar, al elemento contenedor correspondiente; de ​​hecho, incluso podemos tener múltiples instancias para diferentes subárboles.

Por supuesto, todavía tenemos que implementar esto discover método (como parte de AutoLoader clase anterior):

discover(scope) {
  let candidates = [scope, ...scope.querySelectorAll("*")];
  for(let el of candidates) {
    let tag = el.localName;
    if(tag.includes("-") && !customElements.get(tag)) {
      this.load(tag);
    }
  }
}

Aquí verificamos nuestro elemento padre junto con cada hijo individual (*). Si es un elemento personalizado, como lo indican las etiquetas de guión, pero aún no se ha actualizado, intentaremos cargar la definición correspondiente. Consultar el DOM de esta manera puede ser costoso, por lo que debemos tener un poco de cuidado. Podemos facilitar la carga en el hilo principal aplazando este trabajo:

connectedCallback() {
  let scope = this.parentNode;
  requestIdleCallback(() => {
    this.discover(scope);
  });
}

requestIdleCallback aún no es compatible universalmente, pero podemos usar requestAnimationFrame como opción de respaldo:

let defer = window.requestIdleCallback || requestAnimationFrame;

class AutoLoader extends HTMLElement {
  connectedCallback() {
    let scope = this.parentNode;
    defer(() => {
      this.discover(scope);
    });
  }
  // ...
}

Ahora podemos proceder a la implementación de lo que falta. load método de inyección dinámica de un <script> elemento:

load(tag) {
  let el = document.createElement("script");
  let res = new Promise((resolve, reject) => {
    el.addEventListener("load", ev => {
      resolve(null);
    });
    el.addEventListener("error", ev => {
      reject(new Error("failed to locate custom-element definition"));
    });
  });
  el.src = this.elementURL(tag);
  document.head.appendChild(el);
  return res;
}

elementURL(tag) {
  return `${this.rootDir}/${tag}.js`;
}

Tenga en cuenta la convención codificada en elementURL.El src La URL del atributo implica que hay un directorio donde se encuentran todas las definiciones de elementos personalizados (por ejemplo, <my-widget>/components/my-widget.js). Podemos idear estrategias más complejas, pero esto es lo suficientemente bueno para nuestros propósitos. Redirigir esta URL a un método separado permite subclasificar proyectos específicos cuando sea necesario:

class FancyLoader extends AutoLoader {
  elementURL(tag) {
    // fancy logic
  }
}

De cualquier manera, tenga en cuenta que confiamos en this.rootDirAquí es donde entra en juego la configurabilidad antes mencionada. Agreguemos la herramienta get correspondiente:

get rootDir() {
  let uri = this.getAttribute("root-dir");
  if(!uri) {
    throw new Error("cannot auto-load custom elements: missing `root-dir`");
  }
  if(uri.endsWith("https://css-tricks.com/")) { // remove trailing slash
    return uri.substring(0, uri.length - 1);
  }
  return uri;
}

Usted podría estar pensando en observedAttributes ahora, pero eso realmente no hace las cosas más fáciles. Más actualización root-dir en tiempo de ejecución parece algo que nunca necesitaremos.

Artículo Recomendado:  ¿Cómo elegí una biblioteca de animación para mi proyecto? trucos CSS

Ahora podemos, y debemos, configurar nuestro directorio con elementos: <ce-autoloader root-dir="/components">.

Con eso, nuestro cargador automático puede hacer su trabajo. Excepto que solo funciona una vez, para elementos que ya existen cuando se inicializa el cargador automático. Probablemente también querremos tener en cuenta los elementos agregados dinámicamente. aquí es donde MutationObserver entra en vigor:

connectedCallback() {
  let scope = this.parentNode;
  defer(() => {
    this.discover(scope);
  });
  let observer = this._observer = new MutationObserver(mutations => {
    for(let { addedNodes } of mutations) {
      for(let node of addedNodes) {
        defer(() => {
          this.discover(node);
        });
      }
    }
  });
  observer.observe(scope, { subtree: true, childList: true });
}

disconnectedCallback() {
  this._observer.disconnect();
}

De esta manera, el navegador nos notifica cada vez que aparece un nuevo elemento en el DOM, o mejor dicho, nuestro subárbol correspondiente, que luego usamos para reiniciar el proceso de descubrimiento. (Podría argumentar que estamos reinventando elementos personalizados aquí, y sería bastante justo).

Nuestro cargador automático ahora es completamente funcional. Las mejoras futuras pueden abordar posibles condiciones de carrera y explorar optimizaciones. Pero es probable que esto sea lo suficientemente bueno para la mayoría de los escenarios. ¡Déjame saber en los comentarios si tienes un enfoque diferente y podemos comparar notas!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir