主頁 > 前端設計 > Angular里的RouterOutlet指令學習筆記

Angular里的RouterOutlet指令學習筆記

2020-12-10 18:08:51 前端設計

官網: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.

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”.

默認的名稱是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.

<router-outlet
  (activate)='onActivate($event)'
  (deactivate)='onDeactivate($event)'></router-outlet>

路由配置的物體

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的路由方法時,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.

要使用router,必須先從@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.

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 in
  redirectUrl: 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的原創文章,盡在:“汪子熙”:

汪子熙 CSDN認證博客專家 前端框架 Node.js SAP
JerryWang,2007年從電子科技大學計算機專業碩士畢業后加入SAP成都研究院作業至今,Jerry是SAP社區導師,SAP中國技術大使,2020年5月下旬,Jerry做了腦部腫瘤的開顱切除手術,對編程和人生又有了新的感悟,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/232595.html

標籤:其他

上一篇:新一代前端框架的探索與思考

下一篇:JS:使用mockjs生成測驗資料

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more