Dejando de usar jQuery.once

3 minutos

La web poco a poco está dejando de usar jQuery, principalmente por qué JavaScript en sus nuevas versiones incluye muchas de las cosas que solemos usar de jQuery, aquí tienes un enlace a un sitio muy interesante que te muestra como puedes reemplazar ciertas funciones de jQuery con JavaScript puro https://youmightnotneedjquery.com/.

¿Para qué se usa jQuery.once?

Antes de explicar esto es necesario entender que para integrar nuestro código de JavaScript en Drupal es recomendado usar los Drupal.behaviors, esto hace que se ejecute cuando la página ha terminado de cargar o cuando nuevos elementos son agregados al DOM.

Esto quiere decir que si nuevos elementos llegan a la página por AJAX entonces tu código vuelve a ser ejecutado, esto es útil en muchos casos, pero en otros casos realmente necesitas que sea ejecutado solo una vez. Por poner un ejemplo para este sitio uso la librería sticky-js para fijar la información lateral, como es un bloque específico el que quiero fijar es necesario que el JavaScript se ejecute una sola vez.

¿Cómo se usa jQuery.once?

Al definir nuestra librería en el *.libraries.yml se debe tener como dependencias core/jquery y core/jquery.once

mi-libreria:
  version: 1.x
  js:
    mi-libreria.js: {}
  dependencies:
    - core/drupal
    - core/jquery
    - core/jquery.once

Y nuestro js la usa así:

(function ($, Drupal) {
  Drupal.behaviors.sticky = {
    attach: function (context, settings) {
      $('body', context).once('sticky', function () {
        var sticky = new Sticky('.sticky-el');
      });
    }
  };
}(jQuery, Drupal));

Lo que hace este código es agregar una clase al elemento donde se aplica el once, así la próxima vez que se ejecuten los Drupal.behaviors esta clase será encontrada y el código no se volverá a ejecutar.

Podemos hacerlo sin jQuery

(function (Drupal) {
  Drupal.behaviors.sticky = {
    attach: function (context, settings) {
      const body = context.querySelector('body');
      if (!body.classList.contains('sticky-processed')) {
        var sticky = new Sticky('.sticky-el');
        body.classList.add('sticky-processed');
      }
    }
  };
})(Drupal);

Se ve un poco más de código, pero está haciendo exactamente lo mismo sin depender de jQuery, entonces podemos dejar de usar la dependencia en la definición de nuestra librería.

La nueva once API

Desde la versión 9.2.0 de Drupal podemos usar esta nueva API que está incluida en el core, es el reemplazo de jQuery.once con la que nuestro código quedaría de la siguiente manera.

Al definir nuestra librería se debe tener como dependencia core/once

mi-libreria:
  version: 1.x
  js:
    mi-libreria.js: {}
  dependencies:
    - core/drupal
    - core/once

Y nuestro js la usa así:

(function (Drupal, once) {
  Drupal.behaviors.sticky = {
    attach: function (context) {
      once('sticky', 'body', context).forEach(function () {
        var sticky = new Sticky('.sticky-el');
      });
    }
  };
})(Drupal, once);
 

La función once puede recibir hasta 3 argumentos, aunque solo 2 son requeridos:

  1. Un identificador.
  2. Un selector para el elemento donde se aplicara, esto se puede escribir como cualquier selector de CSS.
  3. (Opcional) un contexto, en mi caso prefiero usarlo para que mi código no tenga que buscar cada vez en todo el documento.

Conclusión

Con el fin de mejorar el rendimiento de tu sitio es mejor evitar depender de jQuery y comenzar usar las herramientas que Drupal y JavaScript nos ofrecen en sus nuevas versiones.

Jidrone Drupal Developer
J. Ivan Duarte
Drupal Senior Developer

Share