Mudanças noNavigateEvent no Chrome 105

Joe Medley
Joe Medley

O Chrome 105 apresenta dois novos métodos no NavigateEvent da API Navigation (lançada na versão 102) para melhorar métodos que se mostraram problemáticos na prática. A intercept(), que permite que os desenvolvedores controlem o estado após a navegação, substitui a transitionWhile(), que era difícil de usar. O método scroll(), que rola até uma âncora especificada no URL, substitui restoreScroll(), que não funciona para todos os tipos de navegação.

Neste artigo, explicarei os problemas com ambos e como os novos métodos corrigem esses problemas.

O método NavigateEvent.trasitionWhile(), introduzido com a API Navigation no Chrome 102, intercepta a navegação para transições do lado do cliente em apps de página única. Seu primeiro argumento é uma promessa que sinaliza ao navegador e a outras partes do aplicativo da Web que ela foi concluída.

Na prática, isso não funcionou. Considere este padrão de programação comum:

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

Ela é funcionalmente equivalente ao código abaixo. Isso faz com que parte da navegação seja executada antes que a API saiba que o desenvolvedor pretende interceptar a navegação.

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

Um exemplo em que isso pode estragar um app é na lógica de restauração de rolagem, em que ele captura posições de rolagem após a mudança do DOM, e não antes.

O que mudou

Para substituir transitionWhile(), a especificação atual introduz NavigateEvent.intercept(). O novo método usa um gerenciador além das propriedades focusReset e scrollRestoration compatíveis com transitionWhile(). O novo gerenciador sempre é executado após a confirmação da navegação e itens como posições de rolagem foram capturadas, evitando os problemas com transitionWhile().

O método transitionWhile() ainda está disponível, mas foi descontinuado e será removido no Chrome 108.

Como usar intercept()

O NavigateEvent.intercept() tem as mesmas restrições que o transitionWhile(), já que ele não pode ser chamado em todos os eventos de navegação. As navegações de origem cruzada não podem ser interceptadas, assim como as travessias entre documentos. Isso vai gerar uma DOMException do tipo "SecurityError".

Para usar intercept(), basta transmitir seu gerenciador personalizado ao chamá-lo.

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

Uma navegação, como aquela da parte de cima da página para um âncora (chame de mudança de /a para /a#id), é totalmente gerenciada pelo navegador, mesmo em um app de página única. No entanto, navegar até um âncora em outra "página" (/a para /b#id), que é simples para apps de várias páginas, é mais complicado para apps de uma única página. O app precisa interceptar a navegação para /b#id usando NavigateEvent.transitionWhile() e, em seguida, chamar NavigateEvent.restoreScroll() para exibir a âncora. Como mencionado acima, isso é difícil de fazer no momento.

O que mudou

Em apps de página única, agora é possível controlar se o navegador processa a rolagem para uma âncora ou se o código aceita.

Como usar o scroll()

Por padrão, o navegador tentará processar a rolagem automaticamente quando o manipulador de interceptação for realizado. Se você quiser gerenciar a rolagem por conta própria, defina scroll como "manual" e chame NavigateEvent.scroll() quando o navegador tentar definir a posição de rolagem.

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

O método restoreScroll() ainda está disponível, mas foi descontinuado e será removido no Chrome 108.

Conclusão

Esperamos atualizar em breve nosso artigo sobre a API Navigation. Enquanto isso, a especificação dessa API contém muitas informações específicas para desenvolvedores Web.

Foto de Tim Gouw no Unsplash (links em inglês)