Szukaj…


Uwagi

Istnieje kilka innych sztuczek, które możemy zrobić z routerem (takich jak ograniczenie dostępu), ale można je omówić w osobnym samouczku.

Jeśli potrzebujesz nowej trasy, po prostu zmodyfikuj app.routes.ts i wykonaj następujące kroki:

  1. Zaimportuj komponent
  2. Dodaj do tablicy routes . Pamiętaj o dodaniu nowej path i component .

Bootstrapping

Teraz, gdy trasy są zdefiniowane, musimy poinformować naszą aplikację o trasach. Aby to zrobić, uruchom program, który wyeksportowaliśmy w poprzednim przykładzie.

Znajdź konfigurację bootstrap (powinna być w main.ts , ale twój przebieg może się różnić ).

//main.ts

import {bootstrap} from '@angular/platform-browser-dynamic';

//Import the App component (root component)
import { App } from './app/app';

//Also import the app routes
import { APP_ROUTES_PROVIDER } from './app/app.routes';

bootstrap(App, [
  APP_ROUTES_PROVIDER,
])
.catch(err => console.error(err));

Konfigurowanie gniazda routera

Teraz, gdy router jest skonfigurowany, a nasza aplikacja wie, jak obsługiwać trasy, musimy pokazać rzeczywiste skonfigurowane przez nas komponenty.

Aby to zrobić, skonfiguruj szablon / plik HTML dla komponentu (aplikacji) najwyższego poziomu w następujący sposób:

//app.ts

import {Component} from '@angular/core';
import {Router, ROUTER_DIRECTIVES} from '@angular/router';

@Component({
    selector: 'app',
    templateUrl: 'app.html',
    styleUrls: ['app.css'],
    directives: [
        ROUTER_DIRECTIVES,
    ]
})
export class App {
    constructor() {
    }
}

<!-- app.html -->

<!-- All of your 'views' will go here -->
<router-outlet></router-outlet>

Element <router-outlet></router-outlet> zmieni zawartość podaną trasą. Innym dobrym aspektem tego elementu jest to, że nie musi to być jedyny element w kodzie HTML.

Na przykład: Załóżmy, że chcesz mieć pasek narzędzi na każdej stronie, który pozostaje stały między trasami, podobnie jak wygląda przepełnienie stosu. Możesz zagnieździć <router-outlet> pod elementami, aby zmienić tylko niektóre części strony.

Zmiana tras (za pomocą szablonów i dyrektyw)

Teraz, gdy trasy są skonfigurowane, potrzebujemy sposobu, aby faktycznie zmienić trasy.

W tym przykładzie pokazano, jak zmieniać trasy za pomocą szablonu, ale można zmienić trasy w TypeScript.

Oto jeden przykład (bez wiązania):

<a routerLink="/home">Home</a>

Jeśli użytkownik kliknie ten link, przekieruje do /home . Router wie, jak obsługiwać /home , więc wyświetli komponent Home .

Oto przykład z powiązaniem danych:

<a *ngFor="let link of links" [routerLink]="link">{{link}}</a>

Który wymagałby istnienia tablicy zwanej links , więc dodaj to do app.ts :

public links[] = [
    'home',
    'login'
]

Spowoduje to zapętlenie tablicy i dodanie elementu <a> z dyrektywą routerLink = wartość bieżącego elementu w tablicy, tworząc to:

 <a routerLink="home">home</a>
 <a routerLink="login">login</a>

Jest to szczególnie przydatne, jeśli masz wiele linków, a może linki muszą być ciągle zmieniane. Pozwalamy Angularowi zająć się pracowitym dodawaniem linków, po prostu dostarczając mu wymagane informacje.

W tej chwili links[] jest statyczny, ale można podawać dane z innego źródła.

Ustawianie tras

UWAGA: Ten przykład jest oparty na wersji 3.0.0.-beta.2 @ angular / router. W chwili pisania tego tekstu jest to najnowsza wersja routera.

Aby użyć routera, zdefiniuj trasy w nowym pliku TypeScript takim jak ten

//app.routes.ts

import {provideRouter} from '@angular/router';

import {Home} from './routes/home/home';
import {Profile} from './routes/profile/profile';

export const routes = [
    {path: '', redirectTo: 'home'},
    {path: 'home', component: Home},
    {path: 'login', component: Login},
];

export const APP_ROUTES_PROVIDER = provideRouter(routes);

W pierwszym wierszu importujemy program provideRouter , abyśmy mogli powiadomić naszą aplikację o trasach podczas fazy ładowania.

Home i Profile to tylko dwa elementy jako przykład. Musisz zaimportować każdy potrzebny Component jako trasę.

Następnie wyeksportuj tablicę tras.

path : ścieżka do komponentu. NIE POTRZEBUJESZ UŻYCIA ”/ ........ Angular zrobi to automatycznie

component : komponent, który ma zostać załadowany podczas dostępu do trasy

redirectTo : Opcjonalne . Jeśli musisz automatycznie przekierowywać użytkownika, gdy uzyska on dostęp do określonej trasy, podaj to.

Na koniec eksportujemy skonfigurowany router. zapewni provideRouter zwróci dostawcę, który możemy zwiększyć, aby nasza aplikacja wiedziała, jak obsługiwać każdą trasę.

Kontrolowanie dostępu do trasy lub z trasy

Domyślny router kątowy umożliwia bezwarunkową nawigację do iz dowolnej trasy. Nie zawsze jest to pożądane zachowanie.

W scenariuszu, w którym użytkownik może warunkowo zezwolić na nawigację na trasę lub z trasy, można użyć Strażnika trasy, aby ograniczyć to zachowanie.

Jeśli twój scenariusz pasuje do jednego z poniższych, rozważ użycie Strażnika trasy,

  • Użytkownik musi być uwierzytelniony, aby przejść do komponentu docelowego.
  • Użytkownik musi mieć uprawnienia do nawigacji do komponentu docelowego.
  • Komponent wymaga asynchronicznego żądania przed inicjalizacją.
  • Komponent wymaga danych wejściowych od użytkownika, zanim opuścisz go.

Jak działają strażnicy trasy

Route Guards działają, zwracając wartość logiczną, aby kontrolować zachowanie nawigacji routera. Jeśli zostanie zwrócona wartość true , router będzie kontynuował nawigację do komponentu docelowego. W przypadku zwrócenia wartości false router odmówi nawigacji do komponentu docelowego.


Interfejsy ochrony trasy

Router obsługuje wiele interfejsów ochronnych:

  • CanActivate : występuje między nawigacją trasy.
  • CanActivateChild : występuje między nawigacją trasy do trasy podrzędnej.
  • CanDeactivate : występuje podczas nawigowania poza bieżącą trasą.
  • CanLoad : występuje między nawigacją trasy do modułu funkcji ładowanego asynchronicznie.
  • Rozwiązanie : służy do pobierania danych przed aktywacją trasy.

Interfejsy te można wdrożyć w swojej straży, aby przyznać lub usunąć dostęp do niektórych procesów nawigacji.


Synchroniczni kontra asynchroniczni strażnicy tras

Strażnicy trasy umożliwiają operacjom synchronicznym i asynchronicznym warunkowe sterowanie nawigacją.

Synchronous Route Guard

Synchroniczny strażnik trasy zwraca wartość logiczną, na przykład poprzez obliczenie natychmiastowego wyniku, w celu warunkowego sterowania nawigacją.

import { Injectable }     from '@angular/core';
import { CanActivate }    from '@angular/router';

@Injectable()
export class SynchronousGuard implements CanActivate {
  canActivate() {
    console.log('SynchronousGuard#canActivate called');
    return true;
  }
}

Asynchroniczna ochrona trasy

W przypadku bardziej złożonego zachowania strażnik trasy może asynchronicznie blokować nawigację. Asynchroniczny strażnik trasy może zwrócić Obserowalną lub Obietnicę.

Jest to przydatne w sytuacjach takich jak oczekiwanie na dane wejściowe użytkownika w celu udzielenia odpowiedzi na pytanie, oczekiwanie na pomyślne zapisanie zmian na serwerze lub oczekiwanie na odbiór danych pobranych ze zdalnego serwera.

import { Injectable }     from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable }     from 'rxjs/Rx';
import { MockAuthenticationService } from './authentication/authentication.service';

@Injectable()
export class AsynchronousGuard implements CanActivate {
    constructor(private router: Router, private auth: MockAuthenticationService) {}

    canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>|boolean {
        this.auth.subscribe((authenticated) => {
            if (authenticated) {
                return true;
            }
            this.router.navigateByUrl('/login');
            return false;
        });
    }
}

Dodaj strażnika do konfiguracji trasy

Plik app.routes

Chronione trasy mogą być canActivate ze Guard

import { provideRouter, Router, RouterConfig, CanActivate } from '@angular/router';

//components
import { LoginComponent } from './login/login.component';
import { DashboardComponent } from './dashboard/dashboard.component';

export const routes: RouterConfig = [
    { path: 'login', component: LoginComponent },
    { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }    
}

Wyeksportuj APP_ROUTER_PROVIDERS do użycia w bootstrapie aplikacji

export const APP_ROUTER_PROVIDERS = [
    AuthGuard,
    provideRouter(routes)
];

Użyj Guard w bootstrapie aplikacji

Plik main.ts (lub boot.ts )

Rozważ powyższe przykłady:

  1. Utwórz strażnika (gdzie tworzona jest strażnik) i
  2. Dodaj strażnika do konfiguracji trasy (gdzie Zabezpieczenie jest skonfigurowane dla trasy, a następnie eksportowane są APP_ROUTER_PROVIDERS ),
    możemy połączyć bootstrap z Guard w następujący sposób
import { bootstrap } from '@angular/platform-browser-dynamic';
import { provide } from '@angular/core';

import { APP_ROUTER_PROVIDERS } from './app.routes';    
import { AppComponent } from './app.component';

bootstrap(AppComponent, [
    APP_ROUTER_PROVIDERS
])
.then(success => console.log(`Bootstrap success`))
.catch(error => console.log(error));

Używanie Resolvers i Strażników

Używamy zabezpieczenia najwyższego poziomu w konfiguracji trasy, aby złapać bieżącego użytkownika przy ładowaniu pierwszej strony, oraz resolvera do przechowywania wartości currentUser , który jest naszym uwierzytelnionym użytkownikiem z backendu.

Uproszczona wersja naszej implementacji wygląda następująco:

Oto nasza trasa na najwyższym poziomie:

export const routes = [
{
  path: 'Dash',
  pathMatch : 'prefix',
  component: DashCmp,
  canActivate: [AuthGuard],
  resolve: {
      currentUser: CurrentUserResolver
  },
  children: [...[
    path: '',
    component: ProfileCmp,
    resolve: {
        currentUser: currentUser
    }
  ]]
  }
];

Oto nasza AuthService

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/do';

@Injectable()
export class AuthService {
  constructor(http: Http) {
    this.http = http;

    let headers = new Headers({ 'Content-Type': 'application/json' });
    this.options = new RequestOptions({ headers: headers });
  }
  fetchCurrentUser() {
    return this.http.get('/api/users/me')
      .map(res => res.json())
      .do(val => this.currentUser = val);
 }
}

Oto nasz AuthGuard :

import { Injectable } from '@angular/core';
import { CanActivate } from "@angular/router";
import { Observable } from 'rxjs/Rx';

import { AuthService } from '../services/AuthService';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(auth: AuthService) {
    this.auth = auth;
  }
  canActivate(route, state) {
    return Observable
      .merge(this.auth.fetchCurrentUser(), Observable.of(true))
      .filter(x => x == true);
  }
}

Oto nasz CurrentUserResolver :

import { Injectable } from '@angular/core';
import { Resolve } from "@angular/router";
import { Observable } from 'rxjs/Rx';

import { AuthService } from '../services/AuthService';

@Injectable()
export class CurrentUserResolver implements Resolve {
  constructor(auth: AuthService) {
    this.auth = auth;
  }
  resolve(route, state) {
    return this.auth.currentUser;
  }
}


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow