Mudanças noNavigateEvent no Chrome 105

Joe medley
Joe Medley

O Chrome 105 introduz dois novos métodos no NavigateEvent da API Navigation (introduzido na versão 102) para melhorar métodos que se mostraram problemáticos na prática. intercept(), que permite que os desenvolvedores controlem o estado após a navegação, substitui transitionWhile(), que é 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 os corrigem.

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. O primeiro argumento é uma promessa que sinaliza ao navegador e a outras partes do aplicativo da Web que ele foi concluído.

Isso não funcionou bem na prática. Considere este padrão comum de codificação:

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

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

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

Um exemplo em que isso pode atrapalhar um app é na lógica de restauração de rolagem, em que ele captura as 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 capturados, 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 transitionWhile(), já que não pode ser chamado em todos os eventos de navegação. As navegações de origem cruzada não podem ser interceptadas, nem as travessias entre documentos. Isso vai gerar uma DOMException do tipo "SecurityError".

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

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

Uma navegação da parte superior da página para uma âncora (chamá-la de mover de /a para /a#id) é processada completamente pelo navegador, mesmo em um único app de página. No entanto, navegar para uma âncora em outra "página" (de /a para /b#id), que é simples para apps de várias páginas, é mais complicado para apps de página única. O app precisa interceptar a navegação para /b#id usando NavigateEvent.transitionWhile() e, em seguida, chamar NavigateEvent.restoreScroll() para mostrar a âncora. Como mencionado acima, isso é difícil de fazer atualmente.

O que mudou

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

Como usar a função scroll()

Por padrão, o navegador tentará processar a rolagem automaticamente depois que o manipulador de interceptações for executado. Se você quiser processar 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 da Web.

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