Restaurar a busca pela navegação do navegador

JavaScriptBeginner
Pratique Agora

Introdução

Palavra-chave, categoria, ordem e página de Fieldnote já podem viajar em uma URL. O controlador preparado substitui a entrada atual do histórico após cada busca. Isso mantém os links diretos úteis, mas perde a visualização anterior: quem faz várias buscas não consegue voltar com Back de forma confiável. Você distinguirá ações novas de restauração e fará o histórico do navegador funcionar.

Este laboratório independente prepara os arquivos completos de seleção, normalização e URL do anterior; nenhuma VM antiga é necessária. Você precisa do contrato de quatro estados do laboratório anterior e de funções, objetos, seleção DOM e eventos JavaScript básicos. Aprenderá pushState, replaceState, popstate e por que compartilhar exige a URL, não uma preferência antiga ou um objeto de histórico em memória. Não há requisições assíncronas nem roteadores de framework. Os 40 minutos são estimativa do autor.

Use Workspace e Fieldnote. Edite somente /home/labex/project/fieldnote/work/app.js. Preserve selection.js, state.js, url.js, catalog.js, view.js, HTML/CSS, Study independente e o serviço. O renderizador preparado mostra título, descrição, data, horário e local próprios de cada evento selecionado. O site permanece em inglês. Links funcionam apenas enquanto a rota pública desta VM está disponível; isto não é publicação na Internet.

Criar visitas para mudanças confirmadas do usuário

Neste passo, você manterá a inicialização em uma entrada e criará outra quando o leitor confirmar uma busca ou página diferente.

Em Fieldnote, escolha Open Study view in a new page. É uma página independente, não a aba integrada do produto. Leia print & fold, Make, Soonest first, página 2. Escolha Previous, mude Keyword para sound + light, Category para Listen, Sort by para Title A–Z e acione Search. A página volta a 1. Use Back do navegador, não Previous do site: ele restaura palavra, categoria, ordem, página e registros completos anteriores. Forward restaura a vista nova. É o exemplo normal, não completa seu trabalho.

Abaixo está Study independente antes das alterações. Seu href compartilhado descreve a mesma página visível; não completa Work.

Study independente de novembro

Feche Study e escolha Open Work view in a new page na entrada de Fieldnote. Os arquivos possuem todas as funções de G1, mas o controlador ainda substitui entradas. Vá para Workspace. cd define o diretório deste terminal persistente; cat lê sem modificar:

cd /home/labex/project/fieldnote/work
cat app.js

A função show chama normalize, cria uma URL com stateURL, substitui o endereço e pede a draw para mostrar registros selecionados. Os auxiliares vêm de state.js, url.js, view.js, selection.js, já preparados. Preserve essa ordem distinguindo duas razões para mostrar uma vista.

history.pushState(null, '', url) adiciona uma entrada da mesma origem e altera o endereço sem solicitar página nova. replaceState atualiza apenas a entrada atual. O primeiro argumento é um estado associado opcional; usamos null porque tudo já está na URL. A string vazia é o argumento de título não utilizado da API. Nenhuma chamada dispara popstate por si só. O próximo passo trata o percurso real do histórico. A normalização inicial usa replace para não criar uma entrada extra além da navegação normal de abrir o link. Busca e botões usam push quando a URL confirmada muda; reenviar uma vista igual não precisa duplicar a entrada.

document.querySelector('form') encontra o formulário preparado. form.elements.q acessa o controle chamado q. preventDefault impede a navegação padrão do formulário para que o controlador atualize a vista. Um listener roda quando o evento indicado ocorre. A sintaxe spread {...current, page: ...} copia os campos atuais e depois troca a página, conservando filtros confirmados. Editar somente um controle é rascunho até Search; botões usam o estado confirmado.

Salve esta substituição completa. cat > app.js substitui só esse arquivo. O here-document entre aspas <<'JS' mantém o conteúdo literal; termine com JS sozinho em uma linha:

cat > app.js <<'JS'
const form = document.querySelector('form');
let current;
function show(raw, mode) {
  current = normalize(raw);
  const url = stateURL(current);
  if (mode === 'push' && url.href !== location.href) {
    history.pushState(null, '', url);
  } else if (mode === 'replace') {
    history.replaceState(null, '', url);
  }
  draw(current, matches(current));
}
form.addEventListener('submit', event => {
  event.preventDefault();
  show({q: form.elements.q.value, category: form.elements.category.value,
    sort: form.elements.sort.value, page: 1}, 'push');
});
document.querySelector('#previous').addEventListener('click', () =>
  show({...current, page: current.page - 1}, 'push'));
document.querySelector('#next').addEventListener('click', () =>
  show({...current, page: current.page + 1}, 'push'));
show(readURL(), 'replace');
document.documentElement.dataset.ready = 'true';
JS

&& exige as duas condições: somente um push solicitado com endereço diferente cria visita. else if escolhe substituição na inicialização. Arquivos preparados seguem responsáveis pela normalização e só pelas quatro chaves; caminho real do proxy, parâmetros extra e fragmento permanecem. O marcador final data-ready informa que o controlador terminou o desenho inicial. Um campo HTML visível não demonstra que o JavaScript terminou.

Volte à página independente e atualize. Busque print & fold, Make, Soonest first, depois escolha Next. Observe a edição do mapa e o evento de North room na página 2. Mude para sound + light, Listen, Title A–Z e envie: página 1 com dois eventos de som distintos. Acione Open this view in a new page e atualize a página nova. Ela deve manter Title A–Z e datas/locais corretos. Preferência em cache não é necessária; os quatro valores pertencem à URL, inclusive ordenação não padrão. Feche a página nova e mantenha a original.

Ainda não espere que Back redesenhe Work: existem entradas, mas falta o listener de restauração. Execute Check deste passo. Ele verifica URL direta, visitas úteis e substituição inicial sem exigir o listener do próximo. Se uma errata JavaScript interromper atualizações, use cat app.js, compare o bloco completo, substitua e atualize. Salvar a correção não limpa o catálogo e não exige reiniciar a VM.

Restaurar visualizações com Back e Forward reais

Neste passo, você lerá a URL depois de uma navegação real e provará que outro contexto do navegador reconstrói a mesma vista.

Back e Forward mudam a entrada atual. O navegador emite popstate ao percorrer entradas aplicáveis do mesmo documento; chamar pushState não emite esse evento. Escute o evento real, leia a URL, normalize e desenhe. Não faça push no listener: isso criaria uma nova visita em vez de restaurar a existente. A URL também funciona sem event.state na memória, como ao abrir diretamente. Não use localStorage como autoridade nem guarde a ordenação apenas em um objeto de histórico.

Mude para Workspace. Acrescente um listener ao arquivo salvo antes. Diferentemente de >, >> acrescenta sem apagar o conteúdo. Execute o bloco uma vez; se acrescentar duas vezes por engano, substitua app.js pelo bloco completo anterior e acrescente uma vez.

cat >> app.js <<'JS'
window.addEventListener('popstate', () => show(readURL(), 'replace'));
JS

O callback de seta executa no percurso nativo do histórico. Ele reutiliza show, portanto controles, ordem de registros, rótulo de página, limites desativados e href real combinam com a nova URL atual. Substituir pode normalizar entradas equivalentes, mas não acrescentar uma entrada. O percurso do aluno não simula eventos nem usa atalhos invisíveis de teste.

Volte à página de trabalho original. Para uma entrada inicial clara, abra na barra de endereços a URL real /work/ com esta consulta, preservando origem e caminho:

?edition=november&q=print%20%26%20fold&category=make&sort=title&page=2#directory-title

É o estado A: Title A–Z, página 2, Print & Fold: map edition, depois Print & Fold: tiny type. Leia horários e locais. Crie B com Previous: página 1 traz os dois Print & Fold simples, depois Print & Fold: colour. Crie C enviando sound + light, Listen, Soonest first: página 1 de 1, duas datas distintas. As ações devem preservar edition e o fragmento. Alterar filtros reinicia a página.

Use Back real duas vezes: C → B → A. A cada entrada compare todos os campos, página, títulos ordenados e data/horário/local de cada evento. Depois Forward duas vezes: A → B → C. Repita mais uma vez esse ciclo Back/Back/Forward/Forward. Restaurar não pode adicionar visitas silenciosamente nem perder a cadeia de avanço. Trocar a aba do produto não percorre histórico; Previous do site pagina resultados, não é Back do navegador.

Em C, acione o link real Open this view in a new page. A nova página deve mostrar o mesmo estado confirmado. Atualize e compare. O verificador também abre o link exato em um contexto limpo sem localStorage ou histórico antigos. No navegador normal, a nova página é outra aba, não garantia de isolamento de todo o armazenamento. Não é necessária API de área de transferência nem mensagem Copied não testada.

Volte à página original, use Back até B e atualize. Ela deve manter B porque lê a URL. Uma palavra alterada mas não enviada é rascunho descartado ao atualizar. Teste explicitamente: digite unsubmitted draft sem Search, atualize e observe a palavra confirmada de B restaurada. Para um erro comum, envie prnit, leia a mensagem válida sem resultados, corrija para print & fold, Make e envie. Resultado vazio não deve inventar um cartão alternativo.

Em largura de desktop, perto de 768 e 390 pixels, compare cartões completos, controles e link. Use Tab e Enter para uma busca e inspecione o foco; mantenha a estrutura responsiva preparada. Execute Check. Ele roda seu frontend sem mudanças em um ambiente isolado, testa Back/Forward reais e contexto limpo, compara cada registro visível ao catálogo independente e preserva a área de trabalho ativa. Não cria conta nem publica um site permanente.

Resumo

Você separou ações novas confirmadas de restauração inicial ou histórica. Back/Forward reais, links diretos compartilhados e atualização usam agora o mesmo estado guiado pela URL e eventos completos. O desafio transfere isso para outro catálogo e tamanho de página sem acrescentar roteador, paginação de backend ou dependência de armazenamento privado.