路由的例子
通过超链接导航
新建一个项目,ng new router --routing
然后用webstorm打开项目
import { NgModule } from '@angular/core';
import { Routes,RouterModule } from '@angular/router';
const routes: Routes = [
{
path:'',children: []
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],exports: [RouterModule],providers:[]
})
export @H_404_46@class AppRoutingModule { }
在app.module.ts中也会多引入AppRoutingModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],imports: [
BrowserModule,FormsModule,HttpModule,AppRoutingModule
],providers: [],bootstrap: [AppComponent]
})
export @H_404_46@class AppModule { }
在app.component.html中会加入router-outlet
<h1>
{{title}}
</h1>
<router-outlet></router-outlet>
新生成两个组件ng g component home,ng g component product
然后修改app-routing.modules.ts,为了保证通用性,这里写地址的时候不要在前面加上/
const routes: Routes = [
{path:'',component:HomeComponent},{path:'product',component:ProductComponent}
];
修改app.component.html
<a [routerLink]="['/']">主页</a>
<a [routerLink]="['/product']">商品详情</a>
<router-outlet></router-outlet>
当我访问localhost:4200的时候显示的是home works!,当我点击商品详情,会显示product works!并且地址变成了localhost:4200/product
通过触发事件导航
修改app.component.html
<a [routerLink]="['/']">主页</a>
<a [routerLink]="['/product']">商品详情</a>
<input type="button" value="商品详情" (click)="toProductDetails()">
<router-outlet></router-outlet>
import { Component } from '@angular/core';
import {Router} from "@angular/router";
@Component({
selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css']
})
export @H_404_46@class AppComponent {
title = 'app';
constructor(private router: Router){}
toProductDetails(){
this.router.navigate(['/product']);
}
}
运行程序,点击按钮,下边就会显示product works!
配置404页面路由
修改app-routing.module.ts
const routes: Routes = [
{path:'',component:ProductComponent},{path:'**',component:Code404Component}
];
显示路由是从上往下匹配地址,如果把{path:’**’,component:Code404Component}放到前面不管访问那个页面都会显示code404了。所以具有通用性的路由要放到最后边。
在路由中传递数据
在查询参数中传递数据
/product?id=1&name=2 => ActivatedRoute.queryParams[id]
在路由路径中传递数据
{path:/product/:id} =>/product/1 => ActivatedRoute.queryParams[id]
在路由配置中传递数据
{path:/product,component:ProductComponent,date[{isProd:true}]}
=> ActivatedRoute.data[0][isProd]
在查询参数中传递数据
修改app.component.html
<a [routerLink]="['/product']" [queryParams]="{id:1}">商品详情</a>
这样点击这个连接的时候地址就会为http://localhost:4200/product?id=1
修改product.component.ts
import {Component,OnInit} from '@angular/core';
import {ActivatedRoute} from "@angular/router";
@Component({
selector: 'app-product',templateUrl: './product.component.html',styleUrls: ['./product.component.css']
})
export @H_404_46@class ProductComponent implements OnInit {
private productId: number;
constructor(private routeInfo: ActivatedRoute) {
}
ngOnInit() {
this.productId = this.routeInfo.snapshot.queryParams["id"];
}
}
修改product.component.html
<p>
这里是商品信息组件
</p>
<p>
商品ID是:{{productId}}
</p>
在路由路径中传递数据
修改app-routing.module.ts
{path:'product/:id',component:ProductComponent},
修改app.component.html
<a [routerLink]="['/product',1]">商品详情</a>
修改product.component.ts
this.productId = this.routeInfo.snapshot.params["id"];
参数快照和参数订阅
修改app.component.ts,加了一个参数2
this.router.navigate(['/product',2]);
启动程序。我点击了主页链接后再点商品详情链接。我点击主页链接,然后点击商品详情按钮。都很正常,链接和下面显示的商品id都对应的上。
但是,当我点击商品详情链接之后,再点击商品详情按钮。地址栏由1变成了2,但下边显示的商品id却还是1。
从home组件到product组件会重新创建product组件重新调用ngOnInit方法。
从product组件到product组件,不会重新创建product组件,所以不会重新调用ngOnInt方法。
之前我们使用的都是snapshot,参数快照。
修改product.component.ts
this.routeInfo.params.subscribe((params: Params)=>this.productId=params["id"]);
弄了一个匿名函数把传进来的params参数赋值给productId
这样做了之后就没有之前的问题了。
虽然商品详情组件没有被创建,但是参数变了,而我订阅了那个参数,每次我都能接受到改变了的那个值,然后把这个值赋值为productId。
在以后写代码中如果确定不会从自身路由到自身就可以用参数快照的方式。
重定向路由
修改app-routing.module.ts
const routes: Routes = [
{path:'',redirectTo:'/home',pathMatch:'full'},{path:'home',{path:'product/:id',component:Code404Component}
];
当我访问localhost:4200的时候会重定向到home
修改app.component.html
<a [routerLink]="['/home']">主页</a>
子路由
{path:'home',component:HomeComponent,children:[ { path:'',component:XxxComponent },{ path:'/yyy',component:YyyComponent }
]}
创建商品描述组件ng g component productDesc
创建销售员信息组件ng g component sellerInfo
修改product-desc.component.html
<p>
这是一个牛X的商品!
</p>
修改seller-info.component.html
<p> 销售员ID是:{{sellerId}} </p>
修改seller-info.component.ts
import { Component,OnInit } from '@angular/core';
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-seller-info',templateUrl: './seller-info.component.html',styleUrls: ['./seller-info.component.css']
})
export @H_404_46@class SellerInfoComponent implements OnInit {
private sellerId:number;
constructor(private routeInfo:ActivatedRoute) { }
ngOnInit() {
this.sellerId=this.routeInfo.snapshot.params["id"];
}
}
修改app-routing.module.ts
{path:'product/:id',children:[ {path:'',component:ProductDescComponent},{path:'seller/:id',component:SellerInfoComponent}
]},
修改product.component.html
<p> 这里是商品信息组件 </p> <p> 商品ID是:{{productId}} </p> <a [routerLink]="['./']">商品描述</a> <a [routerLink]="['./seller',99]">销售员信息</a> <router-outlet></router-outlet>
/是从跟路由开始找,./是从当前路由开始找。
路由信息都是在模块层的,组件本身不知道关于路由的信息。
辅助路由
<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>
{path:'xxx',component:XxxComponent,outlet:"aux"}
{path:'yyy',component:YyyComponent,outlet:"aux"}
<a [routerLink]="['/home',{outlets:{aux:'xxx'}}]">Xxx</a> <a [routerLink]="['/product',{outlets:{aux:'yyy'}}]">Yyy</a>
以前一个组件中只可以定义一个插座,而现在可以定义多个插座。
辅助路由案例整体思路
<router-outlet name="aux"></router-outlet>
新创建一个组件ng g component chat
修改chat.component.html
<textarea placeholder="请输入聊天内容" class="chat"></textarea>
修改chat.component.css
@H_404_46@.chat{ background:green; height:100px; width:30%; float: left; Box-sizing:border-Box; }
修改product.component.html
<div class="product"> <p> 这里是商品信息组件 </p> <p> 商品ID是:{{productId}} </p> <a [routerLink]="['./']">商品描述</a> <a [routerLink]="['./seller',99]">销售员信息</a> <router-outlet></router-outlet> </div>
修改product.component.css
@H_404_46@.product{ background:yellow; height:100px; width:70%; float: left; Box-sizing:border-Box; }
修改home.component.html
<div class="home">
<p>
这里是主页组件
</p>
</div>
修改home.component.css
@H_404_46@.home{ background:red; height:100px; width:70%; float: left; Box-sizing:border-Box; }
修改app-routing.module.ts
{path:'',pathMatch:'full'},{path:'chat',component:ChatComponent,outlet:'aux'},
修改app.component.html
<a [routerLink]="['/home']">主页</a>
<a [routerLink]="['/product',1]">商品详情</a>
<input type="button" value="商品详情" (click)="toProductDetails()">
<a [routerLink]="[{outlets:{aux:'chat'}}]">开始聊天</a>
<a [routerLink]="[{outlets:{aux:null}}]">结束聊天</a>
<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>
修改app.component.html
<a [routerLink]="[{outlets:{primary:'home',aux:'chat'}}]">开始聊天</a>
当我点击开始聊天时,主路由会显示为home。
路由守卫
应用场景:
- 只有当用户已经登录并拥有某些权限时才能进入某些路由。
- 一个由多个表单组件组成的向导,例如注册流程,用户只有在当前路由的组件中填写了满足要求的信息才可以导航到下一个路由
- 当用户未执行保存操作而试图离开当前导航时提醒用户
三种路由守卫
- CanActivate:处理导航到某路由的情况
- CanDeactivate:处理从当前路由离开的情况
- Resolve:在路由激活之前获取路由数据
CanActivate守卫
app,右键,新建一个目录,名字为guard,右键guard,新建一个TypeScript文件,名字为login.guard.ts,填写代码
import {CanActivate} from "@angular/router";
export @H_404_46@class LoginGuard implements CanActivate {
canActivate() {
let loggedIn: boolean = Math.random() < 0.5;
if (!loggedIn) {
console.log("用户未登陆");
}
return loggedIn;
}
}
修改app-routing.module.ts
{path:'product/:id',component:SellerInfoComponent}
],canActivate:[LoginGuard]},@NgModule({ imports: [RouterModule.forRoot(routes)],exports: [RouterModule],providers:[LoginGuard] })
CanDeactivate守卫
右键guard,新建一个TypeScript文件,名字为unsave.guard.ts
填写代码
import {ProductComponent} from "../product/product.component";
import {CanDeactivate} from "@angular/router";
export @H_404_46@class UnsavedGuard implements CanDeactivate<ProductComponent>{
canDeactivate(component: ProductComponent){
return window.confirm("你还没有保存,确定要离开么?");
}
}
修改app-routing.module.ts
{path:'product/:id',component:SellerInfoComponent}
],canActivate:[LoginGuard],canDeactivate:[UnsavedGuard]},providers:[LoginGuard,UnsavedGuard] })
resolve守卫
解决的问题,在显示页面之前,页面中的数据显示的时候可能有延迟,这样显示数据的地方会都显示空。
右键guard,新建一个TypeScript文件,名字为product.resolve.ts
import {Resolve,ActivatedRouteSnapshot,RouterStateSnapshot,Router} from "@angular/router";
import {Product} from "../product/product.component";
import {Observable} from "rxjs";
import {Injectable} from "@angular/core";
@Injectable()
export @H_404_46@class ProductResolve implements Resolve<Product>{
constructor(private router:Router){}
resolve(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): Observable<Product> | Promise<Product> | Product {
let productId:number=route.params["id"];
if(productId==1){
return new Product(1,"iPhone7")
}else{
this.router.navigate(['/home']);
return undefined;
}
}
}
修改product.component.ts
import {Component,OnInit} from '@angular/core';
import {ActivatedRoute,Params} from "@angular/router";
@Component({
selector: 'app-product',styleUrls: ['./product.component.css']
})
export @H_404_46@class ProductComponent implements OnInit {
private productId: number;
private productName:string;
constructor(private routeInfo: ActivatedRoute) {
}
ngOnInit() {
this.routeInfo.params.subscribe((params: Params)=>this.productId=params["id"]);
this.routeInfo.data.subscribe((data:{product:Product})=>{
this.productId=data.product.id;
this.productName=data.product.name
});
}
}
export @H_404_46@class Product{
constructor(public id:number,public name:string){}
}
修改product.component.html
<div class="product">
<p>
这里是商品信息组件
</p>
<p>
商品ID是:{{productId}}
</p>
<p>
商品名称是:{{productName}}
</p>
<a [routerLink]="['./']">商品描述</a>
<a [routerLink]="['./seller',99]">销售员信息</a>
<router-outlet></router-outlet>
</div>
改造在线竞拍应用
步骤:
- 创建商品详情组件,显示商品的图片和标题
- 重构代码,把轮播图组件和商品列表组件封装到新的Home组件
- 配置路由,在导航到商品详情组件时传递商品的标题参数
- 修改App组件,根据路由显示Home组件或商品详情组件
- 修改商品列表组件,给商品标题添加带routLink指令的链接,导航到商品详情路由
新建组件ng g component productDetail
修改product-detail.component.ts
import { Component,OnInit } from '@angular/core';
import{ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-product-detail',templateUrl: './product-detail.component.html',styleUrls: ['./product-detail.component.css']
})
export @H_404_46@class ProductDetailComponent implements OnInit {
productTitle:string;
constructor(private routeInfo:ActivatedRoute) { }
ngOnInit() {
this.productTitle=this.routeInfo.snapshot.params["prodTitle"];
}
}
修改product-detail.component.html
<div> <img src="http://placehold.it/820x230"> <h4>{{productTitle}}</h4> </div>
创建home组件,ng g component home
把app.component.css的内容剪切到home.component.css
把app.component.html中的以下内容复制到home.component.html
<div class="row carousel-container">
<app-carousel></app-carousel>
</div>
<div class="row">
<app-product></app-product>
</div>
并添加
<router-outlet></router-outlet>
到原来的位置
修改app.module.ts
const routeConfig:Routes=[
{path:'',{path:'product/:prodTitle',component:ProductDetailComponent}
]
imports: [
BrowserModule,RouterModule.forRoot(routeConfig)
],
修改product.component.html,增加routerLink
<h4><a [routerLink]="['/product'],product.title">{{product.title}}</a></h4>
原文链接:https://www.f2er.com/angularjs/145790.html