Angular 2
라우팅 (3.0.0 이상)
수색…
비고
라우터로 할 수있는 몇 가지 트릭 (액세스 제한 등)이 있지만 별도의 자습서에서 설명 할 수 있습니다.
새로운 경로가 필요한 경우 app.routes.ts
를 수정하고 다음 단계를 따르십시오.
- 구성 요소 가져 오기
-
routes
배열에 추가하십시오. 새path
및component
를 포함해야합니다.
부트 스트랩
이제 경로가 정의되었으므로 애플리케이션에 경로를 알릴 필요가 있습니다. 이렇게하려면 이전 예제에서 내 보낸 공급자를 부트 스트랩하십시오.
부트 스트랩 구성을 찾으십시오 ( main.ts
있어야하지만 마일리지는 다를 수 있음 ).
//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));
라우터 콘센트 구성
이제 라우터가 구성되었고 애플리케이션에서 경로를 처리하는 방법을 알고 있으므로 구성한 실제 구성 요소를 표시해야합니다.
이렇게하려면 다음과 같이 최상위 (app) 구성 요소에 맞게 HTML 템플릿 / 파일을 구성하십시오.
//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>
<router-outlet></router-outlet>
요소는 주어진 경로의 내용을 전환합니다. 이 요소에 대한 또 다른 좋은 점은 HTML에서 유일한 요소 일 필요 는 없다는 것입니다.
예 : 스택 오버 플로우가 보이는 것과 비슷하게 경로간에 일정한 모든 페이지에 툴바가 필요하다고 가정 해 보겠습니다. 요소 아래에 <router-outlet>
중첩하여 페이지의 특정 부분 만 변경되도록 할 수 있습니다.
경로 변경 (템플릿 및 지시문 사용)
경로가 설정되었으므로 실제로 경로를 변경하는 방법이 필요합니다.
이 예제는 템플릿을 사용하여 경로를 변경하는 방법을 보여 주지만 TypeScript에서 경로를 변경할 수 있습니다.
다음은 한 가지 예입니다 (바인딩없이).
<a routerLink="/home">Home</a>
사용자가 해당 링크를 클릭하면 /home
라우트됩니다. 라우터는 /home
을 처리하는 방법을 알고 있으므로 Home
구성 요소를 표시합니다.
다음은 데이터 바인딩 예제입니다.
<a *ngFor="let link of links" [routerLink]="link">{{link}}</a>
어떤 links
가 존재하는 배열이 필요합니다, 그래서 이것을 app.ts
추가하십시오 :
public links[] = [
'home',
'login'
]
이것은 배열을 반복하며 routerLink
지시문 = 배열의 현재 요소 값으로 <a>
요소를 추가하여 다음과 같이 routerLink
.
<a routerLink="home">home</a>
<a routerLink="login">login</a>
이는 링크가 많거나 링크를 끊임없이 변경해야하는 경우 특히 유용합니다. Angular는 필요한 정보를 제공함으로써 링크를 추가하는 바쁜 작업을 처리하도록했습니다.
현재 links[]
는 정적이지만 다른 소스의 데이터를 피드 할 수 있습니다.
경로 설정
참고 :이 예제는 @ angle / router의 3.0.0.-beta.2 릴리스를 기반으로합니다. 글을 쓰는 시점에서 이것은 최신 버전의 라우터입니다.
라우터를 사용하려면 새 TypeScript 파일에서 경로를 정의하십시오
//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);
첫 번째 행에서는 provideRouter
부트 스트랩 단계에서 경로가 무엇인지 애플리케이션에 알릴 수 있습니다.
Home
Profile
은 예로서 단지 두 가지 구성 요소입니다. 필요한 각 Component
를 경로로 가져와야합니다.
그런 다음 경로 배열을 내 보냅니다.
path
: 구성 요소의 경로입니다. '/ ........'을 사용할 필요가 없습니다. Angular가 자동으로이 작업을 수행합니다.
component
: 경로에 액세스 할 때로드 할 구성 요소
redirectTo
: 선택 사항 입니다. 사용자가 특정 경로에 액세스 할 때 자동으로 사용자를 리디렉션해야하는 경우이를 제공하십시오.
마지막으로 구성된 라우터를 내 보냅니다. provideRouter
는 우리가 응용 프로그램이 각 경로를 처리하는 방법을 알고 있도록 boostrap 할 수있는 공급자를 반환합니다.
경로에서 또는 경로로의 액세스 제어
기본 각도 라우터는 임의의 경로에서 무조건 탐색 할 수 있습니다. 이것은 항상 원하는 동작이 아닙니다.
사용자가 조건부로 경로를 탐색 할 수있는 시나리오에서는 경로 가드를 사용하여이 동작을 제한 할 수 있습니다.
시나리오가 다음 중 하나에 해당되면 루트 가드 (Route Guard)
- 사용자는 대상 구성 요소로 이동하기 위해 인증을 받아야합니다.
- 사용자는 대상 구성 요소로 이동할 수있는 권한이 있어야합니다.
- 구성 요소를 초기화하기 전에 비동기 요청이 필요합니다.
- 구성 요소가 멀리 이동하기 전에 사용자 입력이 필요합니다.
루트 경비원의 업무 방식
Route Guards는 라우터 탐색 동작을 제어하기 위해 부울 값을 반환하여 작동합니다. true 가 반환되면 라우터는 대상 구성 요소에 대한 탐색을 계속합니다. false 가 반환되면 라우터는 대상 구성 요소에 대한 탐색을 거부합니다.
라우트 가드 인터페이스
라우터는 여러 가드 인터페이스를 지원합니다.
- CanActivate : 경로 탐색간에 발생합니다.
- CanActivateChild : 경로 탐색과 하위 경로 사이에서 발생합니다.
- CanDeactivate : 현재 경로에서 벗어날 때 발생합니다.
- CanLoad : 비동기 적으로로드 된 형상 모듈로 경로 탐색 사이에 발생합니다.
- 해결 : 경로 활성화 전에 데이터 검색을 수행하는 데 사용됩니다.
이러한 인터페이스는 네비게이션의 특정 프로세스에 대한 액세스 권한을 부여하거나 제거하기 위해 구현할 수 있습니다.
동기 대 비동기 경로 가드
Route Guards는 동기식 및 비동기식 조작이 조건부로 탐색을 제어 할 수 있도록합니다.
동기식 라우트 가드
동기 라우트 가드는 조건부로 탐색을 제어하기 위해 즉시 결과를 계산하여 부울을 반환합니다.
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
@Injectable()
export class SynchronousGuard implements CanActivate {
canActivate() {
console.log('SynchronousGuard#canActivate called');
return true;
}
}
비동기 경로 가드
보다 복잡한 동작을 위해 라우트 보호 장치가 탐색을 비동기 적으로 차단할 수 있습니다. 비동기 라우트 가드는 Observable 또는 Promise를 반환 할 수 있습니다.
이는 사용자 입력이 질문에 대한 응답을 기다리거나, 서버에 변경 사항을 저장하기 위해 대기하거나, 원격 서버에서 가져온 데이터를 수신하기를 기다리는 것과 같은 상황에 유용합니다.
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;
});
}
}
라우트 구성에 가드 추가
파일 app.routes
보호 된 경로는 canActivate
가 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] }
}
앱 부트 스트랩에 사용될 APP_ROUTER_PROVIDERS 내보내기
export const APP_ROUTER_PROVIDERS = [
AuthGuard,
provideRouter(routes)
];
앱 부트 스트랩에서 가드 사용
main.ts 파일 (또는 boot.ts )
위의 예제를 고려하십시오.
- 가드 생성 (Guard 생성)
- 경로 구성에 Guard를 추가합니다 ( 경로 에 대해 Guard가 구성된 다음 APP_ROUTER_PROVIDERS 가 내보내 짐 ).
다음과 같이 Guard에 부트 스트랩을 연결할 수 있습니다.
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));
리졸버 및 가드 사용
첫 번째 페이지로드시 현재 사용자를 잡으려면 route config에 최상위 가드를 사용하고 백엔드에서 인증 된 사용자 인 currentUser
의 값을 저장하는 리졸버를 사용합니다.
구현의 단순화 된 버전은 다음과 같습니다.
다음은 최상위 경로입니다.
export const routes = [
{
path: 'Dash',
pathMatch : 'prefix',
component: DashCmp,
canActivate: [AuthGuard],
resolve: {
currentUser: CurrentUserResolver
},
children: [...[
path: '',
component: ProfileCmp,
resolve: {
currentUser: currentUser
}
]]
}
];
다음은 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);
}
}
다음은 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);
}
}
다음은 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;
}
}