Cambios en NavigationEvent en Chrome 105

Joe Medley
Jo Medley

Chrome 105 presenta dos métodos nuevos en el NavigateEvent de la API de Navigation (introducido en 102) para mejorar los métodos que demostraron ser problemáticos en la práctica. intercept(), que permite a los desarrolladores controlar el estado después de la navegación, reemplaza a transitionWhile(), que resultó difícil de usar. El método scroll(), que se desplaza hasta un ancla especificado en la URL, reemplaza a restoreScroll(), que no funciona en todos los tipos de navegación.

En este artículo, explicaremos los problemas de ambos y la manera en que los nuevos métodos los solucionan.

El método NavigateEvent.trasitionWhile(), que se introdujo con la API de Navigation en Chrome 102, intercepta la navegación para las transiciones del cliente en apps de una sola página. Su primer argumento es una promesa que le indica al navegador y a otras partes de la aplicación web que finalizó.

Esto funcionó poco en la práctica. Considera este patrón de codificación común:

event.transitionWhile((async () => {
  doSyncStuff();
  await doAsyncStuff();
})());

Esto es funcionalmente equivalente al siguiente código. Hace que parte de la navegación se ejecute antes de que la API sepa que el desarrollador pretende interceptar la navegación.

doSyncStuff();
event.transitionWhile((async () => {
  await doAsyncStuff();
})());

Un ejemplo en el que esto puede arruinar una app es la lógica de restauración de desplazamiento, donde captura las posiciones de desplazamiento después del cambio del DOM, en lugar de antes.

Qué cambió

Para reemplazar transitionWhile(), la especificación actual presenta NavigateEvent.intercept(). El nuevo método toma un controlador además de las propiedades focusReset y scrollRestoration compatibles con transitionWhile(). El nuevo controlador siempre se ejecuta después de las confirmaciones de navegación y se capturan elementos como las posiciones de desplazamiento, lo que evita los problemas con transitionWhile().

El método transitionWhile() todavía está disponible, pero dejó de estar disponible y se quitará en Chrome 108.

Cómo usar intercept()

NavigateEvent.intercept() tiene las mismas restricciones que transitionWhile(), ya que no se puede llamar en todos los eventos de navegación. Las navegaciones de origen cruzado no se pueden interceptar ni las navegaciones entre documentos. Esto arrojará una DOMException del tipo "SecurityError".

Para usar intercept(), solo debes pasar el controlador personalizado cuando lo llames.

navigation.addEventListener("navigate", event => {
  event.intercept({
    async handler() {
      doSyncStuff();
      await doAsyncStuff();
    }
  });
});

Una navegación desde la parte superior de la página hasta un ancla (llama de /a a /a#id) se controla completamente por el navegador, incluso en una app de una sola página. Sin embargo, navegar a un ancla en otra "página" (de /a a /b#id), que es simple para apps de varias páginas, es más complicada para apps de una sola página. La app debe interceptar la navegación a /b#id con NavigateEvent.transitionWhile() y, luego, llamar a NavigateEvent.restoreScroll() para mostrar el ancla. Como se mencionó anteriormente, esto es difícil por el momento.

Qué cambió

En las apps de una sola página, ahora puedes controlar si el navegador controla el desplazamiento hasta un ancla o si lo hace tu código.

Cómo usar Scroll()

De forma predeterminada, el navegador intentará controlar el desplazamiento automáticamente una vez que se complete la intercepción. Si deseas controlar el desplazamiento por tu cuenta, establece scroll en "manual" y, luego, llama a NavigateEvent.scroll() cuando el navegador intente establecer la posición de desplazamiento.

navigation.addEventListener("manual", event => {
  scroll: "manual",
  event.intercept({
    async handler() {
      doSyncStuff();
      // Handle scrolling earlier than by default:
      event.scroll();
      await doAsyncStuff();
    }
  });
});

El método restoreScroll() todavía está disponible, pero dejó de estar disponible y se quitará en Chrome 108.

Conclusión

Esperamos actualizar pronto nuestro artículo sobre la API de Navigation. Mientras tanto, las especificaciones para esta API contienen mucha información específica para desarrolladores web.

Foto de Tim Gouw en Unsplash