Aviso: todo e qualquer conteúdo postado é com objetivo de relembrar ou manter os meus conhecimentos e espero que possa te ajudar na sua caminhada pelo aprendizado também. A ideia é a medida que for sobrando um tempo, ir acrescentando as informações relacionadas a esse tema nesse mesmo post, fazendo com que ele fique bem completo e sempre atualizado.
Caso você encontre alguma falha no post ou percebeu que faltou algo, me ajude a melhorar :)
A medida que vou convivendo e apoiando os desenvolvedores na sua caminhada, vou percebendo débitos técnicos e tento apoiar na evolução do conhecimento. Optei por me concentrar naqueles pontos que mais causam dor e dificuldade aos desenvolvedores no dia a dia, de acordo com a minha humilde percepção.
Uma dessas dificuldades é sobre a feature de roteamento do angular.
Portanto, vamos falar um pouco como funciona o módulo de navegação do angular, além de algumas features existentes.
Um breve resumo do passo a passo que o angular faz para realizar o roteamento de uma aplicação:
Por baixo dos panos, o Angular, o React ou o Vue usam a History API.
A History é uma interface do navegador que permite manipular o histórico de navegação do usuário sem recarregar a página. Ela foi introduzida com a especificação do HTML5 e oferece um conjunto de métodos para adicionar, modificar ou remover entradas do histórico do navegador, além de responder a mudanças no estado da navegação.
Veja:
repare que a cada mudança de rota, o objeto "history" vai sendo populado e identificando a nova rota.
Isso ocorre tanto com o uso do Location, quanto do Router:
_import { Location } from "@angular/common"_ _import { Router } from "@angular/router"_
Isso ocorre porque toda vez que navegamos para uma rota qualquer, o método history.pushState é invocado. Da mesma forma, o método history.replaceState é invocado toda vez que utilizamos o replaceUrl.
Uma observação importante é que apesar da History API conseguir suprir as necessidades mais básicas, a partir do momento que avançamos para o tópico de monitoramento de SPA, vemos que ela possui alguns problemas. Para sanar esses problemas, uma nova proposta de substituição dessa API está em andamento, que é a Navigation API. Ela ainda está em fase experimental e falaremos mais dela no post sobre monitoramento e performance de SPA.
Os frontends SPAs possuem 2 estratégias mais comuns de roteamento:
HashLocationStrategy(Hash mode) e PathLocationStrategy(History mode).
Para quem já trabalha com SPAs no dia-a-dia sabe bem a diferença mais básica das duas estratégias:
URLs "limpas": As URLs seguem o padrão tradicional de navegação na web, sem nenhum #. Por exemplo, /home, /about.
Exemplo de URL: https://example.com/home.
URLs com hash: As URLs incluem um # seguido do caminho. O que vem após o # não é enviado ao servidor e é tratado inteiramente pelo navegador.
Exemplo de URL: https://example.com/#/home.
Há alguns debates sobre o melhor uso de cada um. Alguns comentam sobre a estratégia de se utilizar o HashLocation somente em arquitetura SSR e outros que entendem que traz mais simplicidade e por isso o utilizam em todos os cenários, mas não vou entrar nesse detalhe. Fica a dica caso se interesse em procurar mais sobre a discussão.
Lembra do que comentamos lá em cima sobre a History API?
O que essa opção faz é garantir que o conteúdo seja renderizado na tela, mas sem acionar o método history.pushstate que é responsável por definir a URL do navegador. Só o status interno do Router que será atualizado.
Repare que,
o history.state possui tamanho == 1
E quando navego para uma próxima rota com o skipLocation ativo(
this.router.navigate(['componentA'], {skipLocationChange: true});
), ele não altera a url e nem o estado da api de histórico
no entanto, quando acessamos os eventos que o router emite, é possível ver que o estado interno do Router está atualizado
Método disponibilizado para permitir executar uma determinada ação antes do componentes ser carregado. Na imagem abaixo, eu mostro que o resolver é carregado primeiro, depois o componente é carregado e a informação é lida:
Exemplo de código
Crie o resolver:
@Injectable({ providedIn: 'root' }) export class TestResolver implements Resolve{ resolve(): Observable { return of('string retornada pelo resolver'); } }
Declare-o no arquivo de rotas:
{path: 'componentB', component: ComponentB, resolve: { testResolve: TestResolver} }
Receba os parâmetros no componente:
export class ComponentB { constructor(private router: Router, private activatedRoute: ActivatedRoute) { this.activatedRoute.data.subscribe(res => { console.log(res); }) }
Há outras formas de lidar com o problema que os "resolvers" se propõem a sanar. Lembre-se que resolver atua de forma síncrona. Ou seja, para que o componente seja carregado, primeiro o resolver terá que finalizar seu processamento. Isso pode levar a segundos de espera por parte do cliente e a usabilidade da aplicação não ficar tão interessante. Há um tópico bem interessa sobre o uso de resolvers e que você pode conferir aqui.
define quando executar guards e resolvers. Você que utilizou algum guard ou resolver, já deve ter se perguntando se daria pra poder acioná-los só após uma mudança de parâmetros na rota ou de queryParams ou algum outro customizado. Saiba que é possível, utilizando o runGuardsAndResolvers.
Pode declarar direto no arquivo de rotas:
{ path: 'example', component: ExampleComponent, resolve: { data: ExampleResolver }, canActivate: [AuthGuard], runGuardsAndResolvers: 'paramsOrQueryParamsChange' // Define quando executar guards e resolvers }
Você possui essas opções:
'pathParamsChange' | 'pathParamsOrQueryParamsChange' | 'paramsChange' | 'paramsOrQueryParamsChange' | 'always' | ((from: ActivatedRouteSnapshot, to: ActivatedRouteSnapshot) => boolean);
O método forRoot() configura o roteador no nível raiz da aplicação e disponibiliza todas as funcionalidades de roteamento. Com essa configuração, o angula saberá como gerenciar as rotas definidas e as diretivas de roteamento. É com base na declaração do forRoot que routerOutlet, routerLink e outros ficam disponíveis dentro da aplicação.
routerLink é uma diretiva usada para definir links de navegação.
e permite a navegação programática entre as diferentes rotas da aplicação. Quando clicado, o link navega para a rota especificada sem recarregar a página inteira.
Sintaxe: [routerLink]="['/path']"
routerLinkActive é uma diretiva usada para adicionar uma classe CSS ao elemento quando a rota associada está ativa, facilitando a aplicação de estilos ou classes diferentes aos links de navegação que correspondem à rota atualmente ativa, permitindo destacar visualmente o link ativo.
Exemplo:
Veja que quando a rota está ativa, a classe é imediatamente aplicada:
serviço disponibilizado que sempre retorna os dados da rota ativa no momento.
Ao declarar dentro do componente, você vai sempre obter os dados atuais relativos a rota do componente em que está sendo importado:
constructor(private router: Router, private activatedRoute: ActivatedRoute) { console.log(activatedRoute); }
O redirectTo, possui duas formas de realizar o roteamento: relativa e absoluta.
De acordo com a forma que você chama a rota:
a diferença é que ao usar um caminho absoluto, a busca pelo próximo objeto de configuração começará da raiz, ou seja, o primeiro array de rotas mais externo.
Enquanto que ao usar um caminho relativo, a pesquisa começará na primeira rota na matriz de onde a operação de redirecionamento começou.
relativo:
const routes: Routes = [ {path: 'componentA', component: ComponentA}, {path: 'componentB', component: ComponentB, children: [ { path: 'componentC', redirectTo: 'componentA' }, { path: 'componentA', component: ComponentA }, ] } ];
Ao usar dessa forma, quando eu estou no componentB, ele direcionará pro componentA, filho de B, formando assim a rota: "componentB/componentA"
Absoluto:
const routes: Routes = [ {path: 'componentA', component: ComponentA}, {path: 'componentB', component: ComponentB, children: [ { path: 'componentC', redirectTo: '/componentA' }, { path: 'componentA', component: ComponentA }, ] } ];
Já quando colocamos a barra("/"), ele começar a busca pelo raíz do arquivo de rotas e direcionará pro componentA da raíz:
Eu espero que tenha gostado e te ajudado a melhor a compreensão de algo ou até mesmo aberto caminhos para novos conhecimentos. Conto com você nas críticas e sugestões para irmos melhorando o conteúdo e mantendo sempre atualizado para a comunidade.
Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.
Copyright© 2022 湘ICP备2022001581号-3