Angular里的RouterOutlet指令学习笔记
官網:https://angular.io/api/router/RouterOutlet#description
Acts as a placeholder that Angular dynamically fills based on the current router state.
RouterOutlet作為place holder,Angular會基于當前路由狀態動態地填充內容進來。
使用的selector正是router-outlet. 如下圖第60行代碼所示。
Each outlet can have a unique name, determined by the optional name attribute. The name cannot be set or changed dynamically. If not set, default value is “primary”.
每個router-outlet可以分配一個name,默認的名稱是primary.
<router-outlet></router-outlet> <router-outlet name='left'></router-outlet> <router-outlet name='right'></router-outlet>A router outlet emits an activate event when a new component is instantiated, and a deactivate event when a component is destroyed.
當一個新的Component被實例化時,routerOutlet 會發送一個activate事件。應用程序可以監聽這個事件。
<router-outlet(activate)='onActivate($event)'(deactivate)='onDeactivate($event)'></router-outlet>路由配置對象: Route Object
Each definition translates to a Route object which has two things: a path, the URL path segment for this route; and a component, the component associated with this route.
The router draws upon its registry of definitions when the browser URL changes or when application code tells the router to navigate along a route path.
當瀏覽器的url發生變化,或者應用程序調用router的路由方法時,Angular router就根據這些注冊的定義,進行新Component的繪制。
When the browser’s location URL changes to match the path segment /XXX, then the router activates an instance of the YComponent and displays its view.
例如,當瀏覽器地址欄的url變成/XXX時,router激活XXX對應的Component Y的一個實例,然后顯示其視圖。
In order to use the Router, you must first register the RouterModule from the @angular/router package.
要使用Angular 路由功能,必須先從@angular/router包里導入RouterModule:
Define an array of routes, appRoutes, and pass them to the RouterModule.forRoot() method.
定義一個包含路由信息的數組,傳入RouterModule.forRoot方法里。
The RouterModule.forRoot() method returns a module that contains the configured Router service provider, plus other providers that the routing library requires.
RouterModule.forRoot方法返回一個新的module,包含了配置好的Router service provider,加上其他路由庫實現需要的provider.
You might have noticed that the CLI adds RouterModule.forRoot(routes) to the AppRoutingModule imports array. This lets Angular know that the AppRoutingModule is a routing module and forRoot() specifies that this is the root routing module. It configures all the routes you pass to it, gives you access to the router directives, and registers the Router service. Use forRoot() only once in the application, inside the AppRoutingModule.
Once the application is bootstrapped, the Router performs the initial navigation based on the current browser URL.
當Angular應用完成初始化之后,Router基于當前瀏覽器的默認url,進行初始跳轉動作。
RouterModule provides the Router service, as well as router directives, such as RouterOutlet and routerLink.
RouterModule提供Router服務,Router directive,比如RouterOutlet和RouterLink.
The root application module imports RouterModule so that the application has a Router and the root application components can access the router directives.
Root應用module導入RouterModule,這樣應用可以使用Router服務,并且應用Component可以訪問router指令。
Any feature modules must also import RouterModule so that their components can place router directives into their templates.
任何feature module都必須導入RouterModule,只有這樣,feature module包含的Component才能在其template里使用router指令。
If the RouterModule didn’t have forRoot() then each feature module would instantiate a new Router instance, which would break the application as there can only be one Router. By using the forRoot() method, the root application module imports RouterModule.forRoot(…) and gets a Router, and all feature modules import RouterModule.forChild(…) which does not instantiate another Router.
Router實例的單例原則。
How forRoot() works
forRoot() takes a service configuration object and returns a ModuleWithProviders, which is a simple object with the following properties:
- ngModule: in this example, the GreetingModule class
- providers: the configured providers
例子:
const appRoutes: Routes = [{ path: 'crisis-center', component: CrisisListComponent },{ path: 'heroes', component: HeroListComponent }, ];@NgModule({imports: [BrowserModule,FormsModule,RouterModule.forRoot(appRoutes,{ enableTracing: true } // <-- debugging purposes only)],declarations: [AppComponent,HeroListComponent,CrisisListComponent,],bootstrap: [ AppComponent ] }) export class AppModule { }Registering the RouterModule.forRoot() in the AppModule imports array makes the Router service available everywhere in the application.
在AppModule imports數組里注冊RouterModule.forRoot的返回結果,確保Router服務在應用的任意位置都能被使用。
The root AppComponent is the application shell. It has a title, a navigation bar with two links, and a router outlet where the router renders components.
The router outlet serves as a placeholder where the routed components are rendered.
router outlet就是一個占位符,用來存放被路由的Component.
Add a wildcard route to intercept invalid URLs and handle them gracefully. A wildcard route has a path consisting of two asterisks. It matches every URL. Thus, the router selects this wildcard route if it can’t match a route earlier in the configuration. A wildcard route can navigate to a custom “404 Not Found” component or redirect to an existing route.
wildcard route就是一個優雅的路由錯誤處理機制。
{ path: '**', component: PageNotFoundComponent }如何設置默認路由?
使用redirectTo屬性:
const appRoutes: Routes = [{ path: 'crisis-center', component: CrisisListComponent },{ path: 'heroes', component: HeroListComponent },{ path: '', redirectTo: '/heroes', pathMatch: 'full' },{ path: '**', component: PageNotFoundComponent } ];使用Angular CLI創建啟用了routing功能的Component:
ng generate module my-module --routing
This tells the CLI to include the @angular/router npm package and create a file named app-routing.module.ts. You can then use routing in any NgModule that you add to the project or app.
const appRoutes: Routes = [{ path: 'crisis-center', component: CrisisListComponent },{ path: 'heroes', component: HeroListComponent },{ path: '', redirectTo: '/heroes', pathMatch: 'full' },{ path: '**', component: PageNotFoundComponent } ];@NgModule({imports: [RouterModule.forRoot(appRoutes,{ enableTracing: true } // <-- debugging purposes only)],exports: [RouterModule] }) export class AppRoutingModule {}路由時的參數傳遞
<a [routerLink]="['/hero', hero.id]">路由url:localhost:4200/hero/15.
The router extracts the route parameter (id:15) from the URL and supplies it to the HeroDetailComponent via the ActivatedRoute service.
Router將路由參數id:15從url里提取出來,通過ActivatedRoute服務傳遞到路由的目的Component中去。
如何使用ActivatedRoute
constructor(private route: ActivatedRoute,private router: Router,private service: HeroService ) {}從ActivatedRoute中提取出參數id:
ngOnInit() {this.hero$ = this.route.paramMap.pipe(switchMap((params: ParamMap) =>this.service.getHero(params.get('id')))); }When the map changes, paramMap gets the id parameter from the changed parameters.
當參數map發生變化時,上面代碼的paramMap從變化的參數里獲得id參數。
The switchMap operator does two things. It flattens the Observable that HeroService returns and cancels previous pending requests. If the user re-navigates to this route with a new id while the HeroService is still retrieving the old id, switchMap discards that old request and returns the hero for the new id.
switchMap操作符做的兩件事情:將Observable<hero>的返回類型,平整化為Hero,同時cancel之前pending的請求。如果用戶重新跳轉到這條路由路徑,而HeroService仍然在讀取前一個id,則old的請求被discard.
為什么要用Observable包裹Param?
In this example, you retrieve the route parameter map from an Observable. That implies that the route parameter map can change during the lifetime of this component.
暗示了存儲路由參數的map有可能在該Component生命周期內發生變化。
By default, the router re-uses a component instance when it re-navigates to the same component type without visiting a different component first. The route parameters could change each time.
默認情況下,當我們反復跳轉到一個同樣的UI時,router重用該UI Component實例。
You wouldn’t want the router to remove the current HeroDetailComponent instance from the DOM only to re-create it for the next id as this would re-render the view. For better UX, the router re-uses the same component instance and updates the parameter.
Router重用Component實例,只是替換parameter值。
Since ngOnInit() is only called once per component instantiation, you can detect when the route parameters change from within the same instance using the observable paramMap property.
ngOnInit在Component整個生命周期里只會觸發一次,所以我們可以用Observable包裹過的paramMap屬性,來檢測參數值的變化。
This application won’t re-use the HeroDetailComponent. The user always returns to the hero list to select another hero to view. There’s no way to navigate from one hero detail to another hero detail without visiting the list component in between. Therefore, the router creates a new HeroDetailComponent instance every time.
如果是list-detail風格的應用,我們無法從一個明細頁面跳轉到另一個明細頁面,中間必須通過list頁面的中轉。因此,router每次被迫創建新的明細頁面Component實例。
When you know for certain that a HeroDetailComponent instance will never be re-used, you can use snapshot.
route.snapshot provides the initial value of the route parameter map. You can access the parameters directly without subscribing or adding observable operators as in the following:
從route.snapshot能獲取route參數的初始值。
ngOnInit() {const id = this.route.snapshot.paramMap.get('id');this.hero$ = this.service.getHero(id); }snapshot only gets the initial value of the parameter map with this technique. Use the observable paramMap approach if there’s a possibility that the router could re-use the component. This tutorial sample app uses with the observable paramMap.
如果router會重用一個Component,這意味著paramMap在Component生命周期會發生變化,此時要用Observable包裹后的paramMap來檢測這種變化。
為什么我們需要Route Guard
- Perhaps the user is not authorized to navigate to the target component.
- Maybe the user must login (authenticate) first.
- Maybe you should fetch some data before you display the target component.
- You might want to save pending changes before leaving a component.
- You might ask the user if it’s OK to discard pending changes rather than save them.
通過路由守衛的返回值確定路由是否繼續。
- If it returns true, the navigation process continues.
- If it returns false, the navigation process stops and the user stays put.
- If it returns a UrlTree, the current navigation cancels and a new navigation is initiated to the UrlTree returned.
CanActivate: requiring authentication
Applications often restrict access to a feature area based on who the user is. You could permit access only to authenticated users or to users with a specific role. You might block or limit access until the user’s account is activated.
The CanActivate guard is the tool to manage these navigation business rules.
用于實現權限檢查。
看一個例子:
實現一個AuthGuard:
import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';@Injectable({providedIn: 'root', }) export class AuthGuard implements CanActivate {canActivate(next: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean {console.log('AuthGuard#canActivate called');return true;} }在app module里導入這個AuthGuard,維護到Routes數組元素的canActivate屬性里:
import { AuthGuard } from '../auth/auth.guard';const adminRoutes: Routes = [{path: 'admin',component: AdminComponent,canActivate: [AuthGuard],children: [{path: '',children: [{ path: 'crises', component: ManageCrisesComponent },{ path: 'heroes', component: ManageHeroesComponent },{ path: '', component: AdminDashboardComponent }],}]} ];@NgModule({imports: [RouterModule.forChild(adminRoutes)],exports: [RouterModule] }) export class AdminRoutingModule {}一個模擬登錄的service:
import { Injectable } from '@angular/core';import { Observable, of } from 'rxjs'; import { tap, delay } from 'rxjs/operators';@Injectable({providedIn: 'root', }) export class AuthService {isLoggedIn = false;// store the URL so we can redirect after logging inredirectUrl: string;login(): Observable<boolean> {return of(true).pipe(delay(1000),tap(val => this.isLoggedIn = true));}logout(): void {this.isLoggedIn = false;} }The ActivatedRouteSnapshot contains the future route that will be activated and the RouterStateSnapshot contains the future RouterState of the application, should you pass through the guard check.
If the user is not logged in, you store the attempted URL the user came from using the RouterStateSnapshot.url and tell the router to redirect to a login page—a page you haven’t created yet. Returning a UrlTree tells the Router to cancel the current navigation and schedule a new one to redirect the user.
更多Jerry的原創文章,盡在:“汪子熙”:
總結
以上是生活随笔為你收集整理的Angular里的RouterOutlet指令学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 寄存器和立即数和内存单元
- 下一篇: MinDoc 编译安装(linux环境)