一:路由基礎
- 什么是路由:
在web開發中,路由的概念由來已久,簡而言之,就是利用URL的唯一性來指定特定的事物,這個事物可以是文件、狀態、數據等等。服務器端路由早已有之,隨著近幾年REST理念的流行,為更多的人接受和使用。而瀏覽器客戶端路由,則是隨著單頁應用 (SPA)的興起,才被越來越多的前端框架所實現。在Angular中,頁面由組件構成,因此URL和頁面的對應關系實質上就是URL和組件的對應關系。
restFul架構風格 linkhttp://www.ruanyifeng.com/blog/2011/09/restful
名詞:路由組件(含有路由的組件)
創建帶路由模塊的項目請使用:ng new xxx --routing
在Angular路由的工作流程
- 當用戶在瀏覽器輸入URL后,Angular講獲取該URL并將其解析生成一個UrlTree實例
- 在路由配置中尋找并激活UrlTree實例匹配的配置項(orutes)。
- 為配置項中指定的組件創建實例
- 將該組件渲染于路由組件的模板中<router-outlet>指令所在位置。
具體步驟:
- Routes路由配置項
- 設置<router-outlet>占位符
- 設置觸發轉跳功能(<a routerLink> / router.navigate())
具體對象以及參數信息如下圖
路由器部件 | 含義 |
---|---|
Router(路由器) | 為激活的URL顯示應用組件。管理從一個組件到另一個組價的導航 |
RouterModule(路由器模塊) | 一個獨立的Angular模塊,用于提供所需的服務提供商,以及用來在應用視圖之間進行導航的指令 |
Routes(路由數組) | 定義了一個路由數組,每一個都會把一個URL路徑映射到一個組件 |
Route(路由) | 定義路由器該如何根據URL模式(pattern)來導航到組件。大多數路由都由路勁和組件類構成。 |
RouterOutlet(路由出口) | 該指令(<router-outlet>)用來標記出路由器該在哪里顯示視圖。 |
RouterLink(路由鏈接) | 該指令用來把一個可點擊的HTML元素綁定到路由。點擊帶有綁定到字符串或鏈接參數數組的routerLink指令的元素就會觸發一次導航。 |
RouterLinkActive(活動路由鏈接) | 當HTML元素上或元素內的routerLink變為激活或非激活狀態時,該指令為這個HTML元素添加或移除CSS類。 |
ActivateRoute(激活的路由) | 為每個路由組件提供的一個服務,它包含特定于路由的信息,比如路由參數、靜態數據、解析數據、全局查詢參數和全局碎片(fragment) |
RouterState(路由器狀態) | 路由器的當前狀態包含了一顆由程序中激活的路由構成的樹。它包含一些用于遍歷路由樹的快捷方法。 |
鏈接參數數組 | 這個數組會被路由器解釋成一個路由操作指南。我們可以把一個RouterLink綁定到該數組,或者把它作為參數傳給Router.navigate方法。 |
路由組件 | 一個帶有RouterOutlet的Angular組件,它根據路由器的導航來顯示相應的視圖。 |
- 后端路由:
在express中路由長這樣:
router.get('/user', function(req, res){
res.send('hello world')
})
在Ruby中路由長這樣:
get''/user', to:'pages#user'
classPagesController<actionController::Base
defablout
render
end
end
- 路由策略:
路由策略決定Angular講使用URL的哪一部分和路由配置項的path屬性進行匹配。Angular提供了PathLocationStrategy 和 HashLocationStrategy兩種策略。
Path(Angular默認)策略時:http://localhost:4200/home
Hash策略時:http://localhost:4200/#/home
Hash策略特點:
- 瀏覽器向服務器發送請求時不會帶上hash部分的內容。只發http://localhost:4200
- 更改URL的hash部分不會向服務器重新發起請求。這樣子在跳轉的時候就不會引發頁面的刷新和應用的重新加載。
Path策略特點:
- 使用URL的path部分來進行路由的匹配,會將URL原封不動的發送給服務器。
Path優點:
- 為服務器渲染提供了可能。
Path條件:
- 瀏覽器需要支持HTML5的histroy.pushState()方法。
- 需要在服務器端進行配置,將所有的URL重定向到應用首頁。實際URL在服務器并不存在相對應的文件結構。
- 需要設置一個base路徑。Angular講以base路徑作為前綴。可以區分不同應用的不同請求。
- 重點:1、 當你要把Angular程序部署在對HTML5支持不足環境下時,請使用Hash策略。2、 當傳統的集成式部署的時候,請使用Hash策略。
- 路由跳轉:
對于Angular構建的單頁應用而言,頁面跳轉實質上就是一個配置項跳轉到另一個配置項的行為。
指令跳轉:[routerLink]指令,其值是需要跳轉的路徑。這個指令可以寫在任何HTML元素上。觸發是click事件。行為:1、攔截click事件,2、根據傳遞的值跳轉。
代碼跳轉:Router.navigate()方式。
- 注意事項:
不要在path參數中添加斜杠,請使用path:'home'
二:路由參數
Angular組件間傳遞數據的三種方式,我們今天來介紹二種路由參數。
- Path參數(使用最多)
顧名思義是通過解析URL的path部分來獲取參數。
- 配置路由配置項:例如path:'contact/:id'
- 修改我們的指令(代碼)的參數:"['/contact', 1]"
- 占位符不用修改
- 接收數據ActivatedRoute.snapshot.params['id']
- Query參數
在查詢參數中傳遞數據
- 路由配置項不用修改
- 修改我們的指令(代碼)的參數:"['/contact']"[queryParams]="{id: 1}"
- 占位符不用修改
- 接收數據ActivatedRoute.snapshot.queryParams['id']
- Data參數(基本不用)
直接在路由配置項中指定參數值
路由配置項:
{path:/content, component: ContentComponent, data:[{isContent:true}]指令(代碼)不用修改
占位符不用修改
ActivatedRoute.data[0][isContent]=true
參數訂閱和參數快照
參數快照:snapshot。 ngOnInit只會調用一次。
參數訂閱:會以數據流的形式來監控參數的變化。在我們的Router中可以不用取消訂閱,而在其他的訂閱中你需要手動的來取消。
三、重定向路由
我們有時候需要對初始化的地址,或者已經不存在的地址進行重定向,這是可以使用重定向路由的語法。使用方式:
- 路由配置項中使用redirectTo指向需要重定向的地址。
- 設置pathMatch可能的值為 full 或者 prefix
當值為full時候需要跟重定向的path完全匹配,當值為 prefix的時候匹配開頭。作用:
- 可以讓我們的首頁進來就跳轉到你需要展示的頁面比如(home)。
- 使用prefix 的時候可以讓我們快速的把整個路徑全部都統一處理。
場景:當我們的項目上線之后,用戶已經收藏了一堆堆的鏈接。而我們的項目由于版本更新或者迭代把原先的路徑廢除了,這個時候就可以快速重定向。
四、路由通配符
解決查找不到或者丟失頁面的情況。(比如用戶收藏你的網站地址,但是你們網站剛好又進行更新,那么有些鏈接就會丟失,這時候就需要通配符了)。步驟:
- 在路由表中:{ path: '**', component: NotFoundComponent }
五、子路由
一個組件可以被嵌入到另外一個組件中,從而建立起組件之間的多級嵌套關系。與此類似,Angular也允許一個路由組件被嵌入到另一個路由組件中,建立多級路由嵌套關系。
步驟:
- 配置路由配置項:例如
{
path: 'contact/:id', component: ContactComponent,children: [
{path: '', component: SiqiComponent},
{path: 'daocheng', component: DaochengComponent}
]
}
- 不用修改父路由的指令,而要添加子路由的指令在含有子路由的模板中。
- 需要添加子路由的占位符,在含有子路由的模板中。ContactComponent中
注意:子路由的指令需要配置. 例如:"['./derry']"
Matrix參數:矩陣URL標記法
特點:
可以配置我們路由可選參數:this.router.navigate(['/xxx', {id: userId, color: 'block'})
能夠精確定位我們不同層次的路由需要的同名的數據參數。
localhost:4200/contact/name/1 //無法區分不同的參數
localhost:4200/contact;id=1/name;id=2
六、輔助路由
Angular允許一個路由組件包含多個Outlet(路由插座),從而可以在一個路由組件中同時顯示多個組件。
主要Outlet(Primary Outlet)有且僅有一個,附屬Outlet(Auxiliary Outlet)可以有任意多個,各個附屬Outlet通過不同的命名加以區分。每一個Outlet均可以通過路由配置來指定可以顯示的組件,這使得Angular可以靈活地對各個組件進行組合,從而滿足不同場景需求。步驟:
- 路由配置項需要定義要被顯示在的插座的名稱例如:
{ path: 'chat', component: ChatComponent, outlet: 'aux'}
上面的aux是自己定義的名稱。
- 指令需要修改成如下的方式:
"[{outlets: {aux: ['chat']}}]"
- 占位符需要新建一個,其名稱為aux。
七、路由守衛
Angular的路由守衛(路由攔截),允許在從一個配置項跳轉到另外一個配置項之前執行指定的邏輯,并根據執行的結果來決定是否進行跳轉。Angular提供了五類路由攔截:
- CanActivate 激活守衛
功能:處理進入路由的情況
參數:
- ActivatedRouteSnapshot,表示所要激活的目標配置項(被使用到的路由的信息)。
- RouterStateSnapshot,表示應用當前所處的路由狀態,其包含了當前所需的所以配置項。
通過實現CanActivate接口創建守衛服務。該接口只包含了一個canActivate()方法,最簡單的情況,該方法返回true,則表示通過守衛。返回false時,表示不允許,則對守衛目標不允許激活(不允許訪問)。
場景: 防止我們的用戶去訪問一些他根本沒有權限訪問的內容。
- CanActivateChild 子路由激活守衛
本路由用于控制是否允許激活子路由配置項,其用法與CanActivate守衛相似,大家自行嘗試。具體案例參考官網。
- CanDeactivate 反激活守衛
功能:處理離開路由的情況
通過實現CanDeactivate接口創建守衛服務,跟CanActivate相比,該方法除了第一個參數為目標配置項對應組件的實例外,其余使用方式與CanAtivate()方法一樣。
場景:用戶在輸入寫非常關鍵的信息,或者進行保存前的操作的時候,我們要避免不小心退出了當前的頁面。
- Resolve 數據預加載守衛
通過實現Resolve<T>泛型接口創建守衛服務。該服務只有一個resolve()方法,用于執行數據預加載邏輯。該方法可以直接將數據返回,在異步情況下也可以通過Observable對象觸發。其返回的任何數據(包括false)都將存放于配置項的data參數部分,如果沒有預加載到期望的數據,只能通過代碼跳轉的方式來達到不激活目標配置項的目的。
場景:我們有時候加載表單內容的時候,會出現頁面已經出來了,但是數據還沒有加載完成。
- CanLoad 模塊加載守衛
通過實現CanLoad接口創建守衛服務,當Url匹配到延遲加載的配置項,canload守衛就會對其攔截判斷是否能加載。
八、懶加載
Angular應用由一個根模塊和任意多個特性模塊組成。由于一個大型的項目通常會包含許多的特性模塊,如果在首屏加載時便將所有的特性模塊加載進來,對于用戶體驗和服務器負載都會有影響。所以Angular提供了延遲加載(異步加載/懶加載),使得只有在真正需要使用到的時候才加載進來。
使用方式:
- {path: 'async', loadChildren: "app/async/async.module#AsyncModule"}
注意:懶加載的模塊,不能放在根模塊同級目錄下。