1. Guard Types
Có bốn loại guards khác nhau chúng ta có thể sử dụng để bảo về routes của mình:
- CanActivate: Quyết định việc một route được kich hoạt.
- CanActivateChild: Quyết định việc children routes được kich hoạt
- CanDeactivate: Quyết định việc một route hủy kích hoạt
- CanLoad: Quyết định một module được lazy loading
Phụ thuộc trên cái gì chúng ta muốn làm, chúng ta có thể cần triển khai một hoặc một số guards nhất định, hoặc cũng có thể định nghĩa tất cả chúng. Hãy theo dõi cách làm thế nào để định nghĩa guards.
2. Định nghĩa Guards
Guards có thể được triển khai trong những cách khác nhau, nhưng sau tất cả nó sẽ là là function trả về một trong những kiểu sau
Observable<boolean>
, Promise<boolean>
hoặc boolean
2.1. Kiểu function
Để đăng kí một guard chúng ta cần định nghĩa một token và guard function. Dưới đây là một định nghĩa cực kì đơn giản cho guard:
@NgModule({
...
providers: [
provide: 'CanActivateGuard',
useValue: () => {
return true;
}
],
...
})
export class AppModule {}
Ở trên là định nghĩa một guard mà luôn trả về
true
, vì vậy chúng ta có thể include nó tới providers của AppModule luôn. Khi đã cấu hình nó trong AppModule chúng ta có thể sử dụng guard trong route config. Cấu hình route bên dưới có CanActivateGuard
được đính kèm:export const AppRoutes:RouterConfig = [
{
path: '',
component: SomeComponent,
canActivate: ['CanActivateGuard']
}
];
Như chúng ta có thể thấy, việc chúng ta cần làm là định nghĩa các guard tokens được gọi đến. Điều này cũng có nghĩa là chúng có thể triển khai nhiều guards để bảo vệ một route. Guards được thực thi theo thứ tự mà chúng được khai báo trên route.
2.2. Kiểu class
Đôi khi, một guard cần tương thích với dependency injection. Trong trường hợp này, nó có ý nghĩa để xác định guard như một class, bởi vì dependencies sau đó có thể đơn giản để injected. Chúng ta muốn để bảo vệ một route và user đã xác thực trước tiên. Chúng ta có thể muốn inject một AuthService để xác định liệu user đã xác thực hoặc chưa. Một class guard sẽ là lựa chọn hoàn hảo cho các vấn đề này.
Khi tạo một guard class, chúng ta implement hoặc
CanActivate
, CanDeactivate
, hoặc CanActivateChild
interfaces, điều này yêu cầu phải có một method canActivate()
, canActivateChild()
, hoặc canDeactivate()
tương ứng. Những methods này là khá tương đương với một guard function trong kịch bản ở trên. Ví dụ bên dưới thể hiện một guard implementation đơn giản:@Injectable()
export class AuthGuardService implements CanActivate, CanActivateChild {
constructor(
private authService: AuthService,
private router: Router
) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
return this.authService.authenticated().map((status) => {
if (status) {
return true;
}
this.router.navigate(["/admin/login"]);
return false;
});
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
return this.canActivate(route, state);
}
}
Ở ví dụ trên chúng ta có thể thấy,
AuthGuardService
implement cả CanActivate, CanActivateChild
, điều này hoàn toàn có thể thực hiện được. CanActivateChild
đơn giản là sử dụng lại logic của CanActivate, tuy nhiên thực tế các bạn hoàn toàn có thể mở rộng logic này. Tiếp đến, chúng ta khai báo AuthGuardService
với AppModule như bên dưới:@NgModule({
...
providers: [
AuthService,
AuthGuardService
]
})
export class AppModule {}
Bây giờ, chúng ta có thể dụng Guard trong routing config cho cả child route như ví dụ bên dưới:
RouterModule.forRoot([
{ path: "admin/login", component: LoginComponent },
{
path: "admin",
component: AdminComponent,
canActivate: [AuthGuardService],
children: [
{
path: "",
canActivateChild: [AuthGuardService],
children: [
{ path: "", redirectTo: "dashboard", pathMatch: "full" },
{ path: "dashboard", component: DashboardComponent },
{ path: "products", component: ProductComponent },
...
]
}
]
...
3. Deactivating Routes
Bây giờ chúng ta có thể thấy làm thế nào để
CanActivate
làm việc trong những kịch bản khác nhau, nhưng như đã đề cập trước đó, chúng ta có thêm một số guard interfaces có thể tận dụng. CanDeactivate
cho chúng ta lựa chọn để quyết định rời route hay không. Điều này rất hữa dụng nếu chúng ta muốn ngăn chặn người dùng làm mất những thay đổi chưa được save khi điền dữ liệu vào form và không may click trên button cancel.
Việc implement một
CanDeactivate
guard là rất tương tụ với CanActivate
. Tất cả những thứ cần làm là chúng ta tạo lại hoặc một function, hoặc một class cái mà implement CanDeactive
interface. Chúng ta có thể implement đơn giản như bên dưới:import { CanDeactivate } from '@angular/router';
import { CanDeactivateComponent } from './app/can-deactivate';
export class ConfirmDeactivateGuard implements CanDeactivate<CanDeactivateComponent> {
canDeactivate(target: CanDeactivateComponent) {
if(target.hasChanges()){
return window.confirm('Do you really want to cancel?');
}
return true;
}
}
Khai báo nó trong AppModule
@NgModule({
...
providers: [
...
ConfirmDeactivateGuard
]
})
export class AppModule {}
0 nhận xét:
Post a Comment