Szukaj…


Podstawowy routing

Router umożliwia nawigację między widokami na podstawie interakcji użytkownika z aplikacją.

Poniżej przedstawiono kroki wdrażania podstawowego routingu w Angular 2 -

Podstawowe środki ostrożności : upewnij się, że masz tag

    <base href='/'> 

jako pierwsze dziecko pod tagiem head w pliku index.html. Ten tag informuje, że folder aplikacji to katalog główny aplikacji. Angular 2 wiedziałby wtedy, aby uporządkować twoje linki.

Pierwszym krokiem jest sprawdzenie, czy wskazujesz poprawne / najnowsze zależności routingu w pliku package.json -

"dependencies": {
  ......
  "@angular/router": "3.0.0-beta.1",
  ......
}

Drugim krokiem jest zdefiniowanie trasy zgodnie z definicją klasy -

class Route {
  path : string
  pathMatch : 'full'|'prefix'
  component : Type|string
  .........
}

W pliku tras ( route/routes.ts ) zaimportuj wszystkie składniki, które musisz skonfigurować dla różnych ścieżek routingu. Pusta ścieżka oznacza, że widok jest ładowany domyślnie. „:” w ścieżce wskazuje parametr dynamiczny przekazany do załadowanego komponentu.

Trasy są udostępniane aplikacji poprzez wstrzykiwanie zależności. Metoda ProviderRouter jest wywoływana z parametrem RouterConfig, aby można go było wstrzykiwać do komponentów w celu wywołania określonych zadań routingu.

import { provideRouter, RouterConfig } from '@angular/router';
import { BarDetailComponent } from '../components/bar-detail.component';
import { DashboardComponent } from '../components/dashboard.component';
import { LoginComponent } from '../components/login.component';
import { SignupComponent } from '../components/signup.component';

export const appRoutes: RouterConfig = [
  { path: '', pathMatch: 'full', redirectTo: 'login' },
  { path: 'dashboard', component: DashboardComponent },
  { path: 'bars/:id', component: BarDetailComponent },
  { path: 'login', component: LoginComponent },
  { path: 'signup',   component: SignupComponent }
];

export const APP_ROUTER_PROVIDER = [provideRouter(appRoutes)];

Trzecim krokiem jest bootstrap dostawcy trasy.

W twoim main.ts (może to być dowolna nazwa. W zasadzie powinien to być twój główny plik zdefiniowany w systemjs.config)

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './components/app.component';
import { APP_ROUTER_PROVIDER } from "./routes/routes";

bootstrap(AppComponent, [ APP_ROUTER_PROVIDER ]).catch(err => console.error(err));

Czwarty krok polega na załadowaniu / wyświetleniu komponentów routera na podstawie dostępnej ścieżki. Dyrektywa jest używana do określenia kątowego miejsca załadowania komponentu. Aby użyć importu ROUTER_DIRECTIVES.

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

@Component({
  selector: 'demo-app',
  template: `
    ....................................
    <div>
      <router-outlet></router-outlet>
    </div>
    ....................................
  `,
  // Add our router directives we will be using
  directives: [ROUTER_DIRECTIVES]
})

Piąty krok polega na połączeniu innych tras. Domyślnie RouterOutlet ładuje komponent, dla którego w RouterConfig określono pustą ścieżkę. Dyrektywa RouterLink jest używana z tagiem kotwicy html do ładowania komponentów dołączonych do tras. RouterLink generuje atrybut href, który służy do generowania łączy. Na przykład:

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

@Component({
  selector: 'demo-app',
  template: `
    <a [routerLink]="['/login']">Login</a>
    <a [routerLink]="['/signup']">Signup</a>      
    <a [routerLink]="['/dashboard']">Dashboard</a>
    <div>
      <router-outlet></router-outlet>
    </div>
  `,
  // Add our router directives we will be using
  directives: [ROUTER_DIRECTIVES]
})
export class AppComponent { }

Teraz jesteśmy dobrzy w routingu do ścieżki statycznej. RouterLink obsługuje również ścieżkę dynamiczną, przekazując dodatkowe parametry wraz ze ścieżką.

import {Component} z '@ angular / core'; zaimportuj {ROUTER_DIRECTIVES} z „@ angular / router”;

@Component({
  selector: 'demo-app',
  template: `
        <ul>
          <li *ngFor="let bar of bars | async">
            <a [routerLink]="['/bars', bar.id]">
              {{bar.name}}
            </a>
          </li>
        </ul>
    <div>
      <router-outlet></router-outlet>
    </div>
  `,
  // Add our router directives we will be using
  directives: [ROUTER_DIRECTIVES]
})
export class AppComponent { }

RouterLink przyjmuje tablicę, w której pierwszy element jest ścieżką do routingu, a kolejne elementy do parametrów routingu dynamicznego.

Trasy podrzędne

Czasami sensowne jest zagnieżdżanie widoków lub tras między sobą. Na przykład na pulpicie nawigacyjnym chcesz wyświetlić kilka widoków podrzędnych, podobnych do kart, ale zaimplementowanych za pośrednictwem systemu routingu, aby wyświetlać projekty użytkowników, kontakty, wiadomości e-mail. W celu obsługi takich scenariuszy router pozwala nam definiować trasy potomne.

Najpierw dostosowujemy nasz RouterConfig z góry i dodajemy trasy podrzędne:

import { ProjectsComponent } from '../components/projects.component';
import { MessagesComponent} from '../components/messages.component';

export const appRoutes: RouterConfig = [
  { path: '', pathMatch: 'full', redirectTo: 'login' },
  { path: 'dashboard', component: DashboardComponent,
    children: [
      { path: '', redirectTo: 'projects', pathMatch: 'full' },
      { path: 'projects', component: 'ProjectsComponent' },
      { path: 'messages', component: 'MessagesComponent' }
    ] },
  { path: 'bars/:id', component: BarDetailComponent },
  { path: 'login', component: LoginComponent },
  { path: 'signup',   component: SignupComponent }
];

Teraz, gdy zdefiniowaliśmy nasze trasy potomne, musimy upewnić się, że te trasy potomne mogą być wyświetlane w naszym DashboardComponent , ponieważ do tego miejsca dodaliśmy dzieci. Wcześniej dowiedzieliśmy się, że komponenty są wyświetlane w <router-outlet></router-outlet> . Podobnie deklarujemy inny RouterOutlet w DashboardComponent :

import { Component } from '@angular/core';

@Component({
  selector: 'dashboard',
  template: `
    <a [routerLink]="['projects']">Projects</a>
    <a [routerLink]="['messages']">Messages</a>   
    <div>
      <router-outlet></router-outlet>
    </div>
  `
})
export class DashboardComponent { }

Jak widać, dodaliśmy kolejny RouterOutlet w którym będą wyświetlane trasy potomne. Zwykle wyświetlana jest trasa z pustą ścieżką, jednak ustawiamy przekierowanie do trasy projects , ponieważ chcemy, aby była ona wyświetlana natychmiast po załadowaniu trasy dashboard . To powiedziawszy, potrzebujemy pustej trasy, w przeciwnym razie pojawi się błąd:

Cannot match any routes: 'dashboard'

Dodając pustą trasę, czyli trasę z pustą ścieżką, zdefiniowaliśmy punkt wejścia dla routera.

ResolveData

W tym przykładzie pokazano, jak rozwiązać dane pobrane z usługi przed renderowaniem widoku aplikacji.

Używa kątowej / routera 3.0.0-beta.2 w momencie pisania

users.service.ts

...
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { User } from './user.ts';



@Injectable()
export class UsersService {

    constructor(public http:Http) {}

    /**
     * Returns all users
     * @returns {Observable<User[]>}
     */
    index():Observable<User[]> {

        return this.http.get('http://mywebsite.com/api/v1/users')
            .map((res:Response) => res.json());
    }

    /**
     * Returns a user by ID
     * @param id
     * @returns {Observable<User>}
     */
    get(id:number|string):Observable<User> {

        return this.http.get('http://mywebsite.com/api/v1/users/' + id)
            .map((res:Response) => res.json());
    }
}

users.resolver.ts

...
import { UsersService } from './users.service.ts';
import { Observable } from 'rxjs/Rx';
import {
    Resolve,
    ActivatedRouteSnapshot,
    RouterStateSnapshot
} from "@angular/router";




@Injectable()
export class UsersResolver implements Resolve<User[] | User> {

    // Inject UsersService into the resolver
    constructor(private service:UsersService) {}

    resolve(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<User[] | User> {
        // If userId param exists in current URL, return a single user, else return all users
        // Uses brackets notation to access `id` to suppress editor warning, may use dot notation if you create an interface extending ActivatedRoute with an optional id? attribute
        if (route.params['id']) return this.service.get(route.params['id']);
        return this.service.index();
    }
}

users.component.ts

To jest komponent strony z listą wszystkich użytkowników. Będzie działał podobnie dla komponentu strony ze szczegółami użytkownika, zastąpi data.users data.user lub dowolnym data.user kluczem zdefiniowanym w app.routes.ts (patrz poniżej)

...
import { ActivatedRoute} from "@angular/router";



@Component(...)
export class UsersComponent {

    users:User[];


    constructor(route: ActivatedRoute) {
        route.data.subscribe(data => {
            // data['Match key defined in RouterConfig, see below']
            this.users = data.users;
        });
    }

    /**
     * It is not required to unsubscribe from the resolver as Angular's HTTP
     * automatically completes the subscription when data is received from the server
     */
}

app.routes.ts

...
import { UsersResolver } from './resolvers/users.resolver';



export const routes:RouterConfig = <RouterConfig>[
    ...
    {
        path: 'user/:id',
        component: UserComponent,
        resolve: {
            // hence data.user in UserComponent
            user: UsersResolver
        }
    },
    {
        path: 'users',
        component: UsersComponent,
        resolve: {
            // hence data.users in UsersComponent, note the pluralisation
            users: UsersResolver
        }
    },
    ...
]
...

app.resolver.ts

Opcjonalnie możesz połączyć wiele resolwerów razem.

WAŻNE: Usługi używane w resolverie muszą zostać zaimportowane jako pierwsze, w przeciwnym razie pojawi się komunikat „Brak dostawcy dla błędu .. Resolver”. Pamiętaj, że usługi te będą dostępne na całym świecie i nie będziesz musiał już deklarować ich u providers żadnego komponentu. Anuluj subskrypcję subskrypcji, aby zapobiec wyciekom pamięci

...
import { UsersService } from './users.service';
import { UsersResolver } from './users.resolver';

export const ROUTE_RESOLVERS = [
    ...,
    UsersService,
    UsersResolver
]

main.browser.ts

Resolwery muszą być wstrzykiwane podczas ładowania.

...
import {bootstrap} from '@angular/platform-browser-dynamic';
import { ROUTE_RESOLVERS } from './app.resolver';

bootstrap(<Type>App, [
    ...
    ...ROUTE_RESOLVERS
])
.catch(err => console.error(err));

Trasa z dziećmi

W przeciwieństwie do oryginalnej dokumentacji, odkryłem, że jest to sposób na prawidłowe zagnieżdżenie tras potomnych w pliku app.routing.ts lub app.module.ts (w zależności od twoich preferencji). To podejście działa w przypadku korzystania z pakietu WebPack lub SystemJS.

Poniższy przykład pokazuje trasy dla domu, domu / licznika oraz domu / licznika / pobierania danych. Pierwsza i ostatnia trasa to przykłady przekierowań. Wreszcie na końcu przykładu znajduje się właściwy sposób na wyeksportowanie trasy do zaimportowania w osobnym pliku. Np. app.module.ts

W celu dalszego wyjaśnienia, Angular wymaga posiadania ścieżki bez ścieżki w tablicy potomnej, która zawiera komponent nadrzędny, do reprezentowania trasy nadrzędnej. Jest to trochę mylące, ale jeśli pomyślisz o pustym adresie URL dla trasy podrzędnej, zasadniczo byłby to ten sam adres URL, co trasa nadrzędna.

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";

import { HomeComponent } from "./components/home/home.component";
import { FetchDataComponent } from "./components/fetchdata/fetchdata.component";
import { CounterComponent } from "./components/counter/counter.component";

const appRoutes: Routes = [
    {
        path: "",
        redirectTo: "home",
        pathMatch: "full"
    },
    {
        path: "home",            
        children: [
            {
                path: "",
                component: HomeComponent
            },
            {
                path: "counter",                    
                children: [
                    {
                        path: "",
                        component: CounterComponent
                    },
                    {
                        path: "fetch-data",
                        component: FetchDataComponent                            
                    }
                ]
            }
        ]
    },
    {
        path: "**",
        redirectTo: "home"
    }
];

@NgModule({
    imports: [
        RouterModule.forRoot(appRoutes)
    ],
    exports: [
        RouterModule
    ]
})
export class AppRoutingModule { }

Świetny przykład i opis za pośrednictwem Siraj



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