Adiós a jQuery
Después de formar parte de nuestro producto desde el principio, ha llegado el momento de decir adiós a jQuery.
jQuery es una biblioteca de JavaScript que encapsula una gran cantidad de funcionalidad nativa de JavaScript en un conjunto alternativo de funciones con una liberal rociada de azúcar sintáctico.
JavaScript y los estándares de los navegadores han evolucionado significativamente a lo largo de la historia de XenForo. Hubo un momento en que hubiera sido impensable utilizar otra cosa. En un pasado no muy lejano, jQuery era prácticamente esencial incluso para poder encontrar un elemento específico con un nombre de clase específico, o para poder soportar las aparentemente interminables peculiaridades de las ahora antiguas versiones de Internet Explorer y otros.
Además, es una librería considerable, con un peso de más de 30 KB que se añaden a cada carga de página, y ¿cuánto de esa librería estábamos usando realmente?
Bueno, como desarrollador que personalmente revisó y reescribió casi 40.000 líneas de código, mucho menos de lo que se podría pensar. Y de las características de lenguaje de jQuery que estábamos utilizando, muchas cosas son un simple cambio directo a una función nativa de JavaScript que, hace mucho tiempo, podría no haber existido en absoluto, o demasiado nueva para haber obtenido suficiente soporte del navegador.
Reconocemos que habrá algunos puntos de dolor para los desarrolladores existentes que tienen el código basado en jQuery, pero, en verdad, siempre y cuando usted no está manteniendo en cualquier lugar cerca de las 40.000 líneas de código que estamos, debe ser una transición relativamente suave. Pero, si te quedas completamente atascado, siempre puedes volver a añadir jQuery si lo deseas, pero te recomendamos evitarlo si puedes. Y eliminar jQuery como dependencia puede comenzar ahora si está planeando hacer cambios al código existente antes de que XenForo 2.3 sea lanzado. Desaconsejamos encarecidamente escribir código nuevo que utilice directamente la funcionalidad de jQuery en este momento.
Si es necesario, podemos entrar en más detalles técnicos más adelante sobre los cambios que hemos hecho, pero aquí hay algunos puntos destacados.
Nota: La siguiente sección se adentra bastante en los detalles de desarrollo, así que pasa a la siguiente sección si esto no te interesa.
Variables de ámbito de bloque
Aunque no está estrictamente relacionado con jQuery, vale la pena señalar que ya no usamos
var
para definir variables en favor de
let
y
const
. Esto hace que el ámbito de las variables sea más claro y que el código sea menos propenso a errores y más predecible.
Seleccionar elemento(s)
La selección de elementos del DOM es probablemente la operación más frecuente que se realiza en JavaScript y, por lo tanto, se trata de un cambio significativo que, aunque ligeramente más verboso, hace que el código sea mucho más claro y menos propenso a errores.
jQuery / XF 2.2
JavaScript:
var $element = $('.someClassName')
if ($element.length)
{
// you have an object containing one or more elements; you can call various methods which will interact with this element or elements
}
JavaScript / XF 2.3
JavaScript:
const element = document.querySelector('.someClassName')
if (element)
{
// you have an instance of HTMLElement, if more elements exist with the same selector, you have the first element
}
// ... or
const elements = document.querySelectorAll('someClassName')
if (elements.length)
{
// you have a NodeList object containing one or more HTMLElement objects
}
Funciones de flecha
De nuevo, aunque no están relacionadas con jQuery, ahora verás que las
funciones de flecha se utilizan tanto como sea posible. Además de ser sintácticamente más fáciles de usar que las funciones anónimas tradicionales, no crean nuevos enlaces para palabras clave como
this
.
jQuery / XF 2.2
JavaScript:
var self = this
var callback = function (foo)
{
self.doSomething(foo)
}
JavaScript / XF 2.3
JavaScript:
const callback = (foo) =>
{
this.doSomething(foo)
}
// ...or
const callback = (foo) => this.doSomething(foo)
Gestión de eventos
Algunas funcionalidades proporcionadas por jQuery eran difíciles de dejar atrás, y la mayoría de esos métodos realmente útiles han sido reescritos y portados a vanilla JavaScript como métodos adicionales a nuestro objeto
XF
. No menos importante es la gestión de eventos de jQuery que soporta eventos namespaced y proporciona una forma más intuitiva de eliminar oyentes de eventos de un elemento que no requiere una referencia a la devolución de llamada del evento original.
jQuery / XF 2.2
JavaScript:
var $element = $('.someClassName')
$element.on('namespace.click', function (e)
{
e.preventDefault()
$element.off('namespace.click')
});
JavaScript / XF 2.3
JavaScript:
const element = document.querySelector('.someClassName')
if (element)
{
XF.on(element, 'namespace.click', e =>
{
e.preventDefault()
XF.off(element, 'namespace.click')
})
}
AJAX
Esto no ha cambiado mucho desde XenForo 2.2 porque todavía tenemos una envoltura
XF.ajax()
para usar como método de ayuda pero, entre bastidores, en lugar de usar el método
$.ajax()
de jQuery (que es una envoltura alrededor de
XMLHttpRequest
) hemos migrado para usar la más moderna
API Fetch.
Lo principal a tener en cuenta aquí es que los métodos
Promise disponibles a partir del resultado de llamar a XF.ajax() tienen nombres ligeramente diferentes a los que tenían con jQuery.
jQuery / XF 2.2
JavaScript:
var t = this
XF.ajax('some-url', data, callback)
.always(function ()
{
t.loading = false
})
JavaScript / XF 2.3
JavaScript:
XF.ajax('some-url', data, callback)
.finally(() =>
{
this.loading = false
})
Almacenamiento de datos arbitrarios para un elemento
Algunas de las características de jQuery, aunque potentes, a veces pueden parecer incoherentes o ambiguas. Una de estas características es el método de datos disponible en los objetos jQuery. Dependiendo de su uso, puede manifestar diferentes comportamientos. Considere el siguiente ejemplo:
jQuery / XF 2.2
JavaScript:
var $element = $('.someClassName').first() // <span class="someClassName" data-foo="1"></span>
var foo = $element.data('foo') // reads the data-foo attribute from the element in the DOM
var bar = $element.data('bar') // attempts to read the data-bar attribute from the element which doesn't exist, but the internal data store may have a value set
$element.data('bar', [1, 2, 3]) // sets the bar key in the internal data store to an array
$element.data('foo', '100') // the foo entry in the internal data store for this element now returns 100, ignoring the data-foo attribute which remains unchanged in the actual DOM
En XenForo, sigue existiendo la necesidad de almacenar datos arbitrarios, especialmente datos que no siempre son una cadena. Sin embargo, nuestros enfoques actuales son más predecibles y coherentes:
JavaScript / XF 2.3
JavaScript:
const element = document.querySelector('.someClassName') // <span class="someClassName" data-foo="1"></span>
const foo = element.dataset.foo // reads the data-foo attribute from the DOM
element.dataset.foo = '100' // sets the data-foo attribute in the DOM
XF.DataStore.set(element, 'bar', [1, 2, 3]) // a new XF.DataStore class is introduced for reading / storing arbitrary, non-string data
const bar = XF.DataStore.get(element, 'bar') // returns an array: [1, 2, 3]
Objetivos del controlador
Tenemos una variable especial que pasamos a todos los manejadores de elementos/eventos que actualmente es
this.$target
. Tenga en cuenta que esto se convierte en
this.target
en XF 2.3 ya que convencionalmente el prefijo
$
en los nombres de variables se utiliza normalmente para denotar un objeto jQuery. En XF 2.3
this.target
representa un objeto
HTMLElement
.
Para encontrar hijos del objetivo, esto es un poco más consistente con vanilla JavaScript que con jQuery:
jQuery / XF 2.2
JavaScript:
var $child = this.$target.find('.someChild').first() // returns the first child element which matches the someChild class
JavaScript / XF 2.3
JavaScript:
const child = this.target.querySelector('.someChild') // returns the first child element which matches the someChild class; this will be a HTMLElement; note it uses the same querySelector method rather than a separately named method
Apoyo a la migración
Aunque, como es comprensible, algunos de los métodos personalizados de XF 2.3 no estarán disponibles hasta el lanzamiento, te animamos a que empieces a migrar todo el código posible ahora para utilizar vanilla JavaScript siempre que sea posible.
Si crees que necesitas ayuda para convertir el código a vanilla JavaScript, tenemos aproximadamente 40.000 líneas de experiencia entre todos e intentaremos responder a las preguntas en el foro de
discusiones de desarrollo de XenForo siempre que podamos.