【Angular】路由 Route导航

时间:2021-10-30 12:04:02

在路由开始之前,先补一下Angular的一些基础知识:
概念:

  • 组件:是Angular应用的基础构建块,可以理解为是一段带有逻辑和数据的html
  • 模块:用来将应用中不同的部分组织成一个Angular框架,可理解的单元
  • 指令:允许向html元素中添加自定义行为
  • 服务:用来封装可重用的业务逻辑

框架认识:
【Angular】路由 Route导航


Angular Route导航
用到路由时,最常用的对象有

  • Routes:路由配置,保存哪个URL对应展示哪个组件,以及在哪个RouterOutlet中展示组件
  • RouterOutlet:在HTML中标记路由内容呈现位置的占位符指令
  • Router:负责在运行时执行路由的对象,可通过调用期navigate()和navigateByUrl()方法来导航到一个指定的路由
  • Routerlink:在HTML中声明路由导航用到的指令
  • ActivatedRoute:当前激活的路由对象,保存着当前路由的信息,如路由地址,路由参数等
一:定义路由
{
path: '',
component:HomeComponent
},
{
path:'product',
component:ProductComponent
}
  • 以上定义了两个路由:path:‘’表示默认路由自动跳转到HomeComponent组件
  • path:‘’路径不能以‘/’开头,方便在导航时使用相对和绝对路径

      定义根路由:RouterModule.forRoot(routes)

二:路由导航类型


      使用命令导航[routerLink]
            如导航到home主页<a [routerLink]="['/product']">商品页面</a>


      使用代码导航
            1.先在构造函数中添加Router:
                  constructor(private router:Router){}
            2.在指定方法中添加导航代码:
                  this.router.navigate(['/product']);


三:在html中定位插座的位置

       <router-outlet></router-outlet >

以上步骤以能成功导航

四:通用路由

      为了防止程序崩溃,所以设置一个通用路由,即当输入不存的URL时,导航到指定页面

{
path:'*',
component:Code404Component
}

       因为路由具有先匹配者优先的原则,所以配置路由时通用路由应该放在所有路由的后面

五:在路由中传递数据


      在URL中传递数据
      1.路由配置

{
path:'product/:id',
component:ProductComponent
}

      2.在跳转路由入口时传递实际的数值
            [routerLink]="['/product',1]"
            或
            this.router.navigate(['/product',1])


      在查询参数中传递数据
      1.[routerLink]="['/product']" [queryParams]="{id:1}"
      2.接收数据
            先在构造函数中声明ActivatedRoute对象
            constructor(private routeInfo:ActivatedRoute) { }
            然后在ngOnInit()接收参数

  ngOnInit() {
//参数快照方式
this.productId = this.routeInfo.snapshot.queryParams["id"];
//参数订阅方式,写在匿名函数中
this.routeInfo.params.subscribe((params:Params) => this.productId=params["id"]);
}

      使用参数订阅方式,是因为当有多个方式跳转到同一路由时,但是传递的参数不同,但是ngOnInit()只有在第一次创建对象时才执行,由于我们接收参数时又是写在ngOnInit()里面的,所以如果使用参数快照的方式,只有第一次导航路由时参数被传进来了,以后再导航该路由时,参数都传不进来了,因为不执行ngOnInit()方法了


六:重定向路由

      使用情况:
             在用户访问一个特定的地址时,将其重定向到另一个指定的地址
       如:
              www.aaa.com => www.aaa.com/product
              ww.aaa.com/x => www.aaa.com/y

      比如:在设置路由时,默认空路径,导航到HomeComponent,但是这样不符合规范,路径名最好是组件名,

{
path: 'home',
component:HomeComponent
}

      然后可以用路由重定向,当到默认路径下时,重导向到home路径下

   {
// 路由重定向
path:'',
redirectTo:'/home',
pathMatch:'full'
}
七:子路由

      1.想给谁添加子路由就在谁的路由配置下添加children
      如:

    path:'product',
component:ProductComponent,
// 定义子路由
children:[
{
path:'',
component:ProductDescComponent
}
]

       2.在父路由的html中添加一个子路由的插座

八:主路由和辅助路由

      1.配置辅助路由出口:一个页面只能有一个路由插座,这是还想一块显示隐藏多个组件,这时就可以定义一个辅助路由

<router-outlet></router-outlet >
<router-outlet name="aux"></router-outlet>

       辅助路由与主路由不同的是,要添加一个name属性

       2.然后配置路由

 {
path:'chat',
component:ChatComponent,
outlet:'aux'
}

      3.最后定义辅助路由入口
             [routerLink]="[{outlets:{primary:'home', aux:'chat'}}]"
      要表明是谁的辅助路由,即主路由:primary

九: 路由守卫

  • CanActivate:处理导航到某路由的情况
  • CanDeactivate:处理从当前路由离开的情况
  • Resolve:在路由激活之前获取路由数据

CanActivate:在满足一定条件下才能进入下一个路由
      1.首先定义守卫,实现CanActivate接口

export class LoginGuard implements CanActivate{
canActivate(){
let loggedIn:boolean = Math.random() < 0.5;
if(!loggedIn){
console.log("用户未登录");
}
return loggedIn;
}
}

      2.然后在要跳转到的路由配置中,添加canActivate:[LoginGuard]


CanDeactivate<返回到的路由组件> :处理从当前路由离开的情况
      1.首先定义守卫,实现CanDeactivate<>接口

export class UnsavedGuard implements CanDeactivate<ProductComponent>{
canDeactivate(component: ProductComponent){
return window.confirm("你还没有保存,确定要离开吗?");
}
}

      2.然后在要跳转到的路由配置中,添加canDeactivate:[UnsavedGuard]


Resolve<返回的东西>:在路由激活之前获取路由数据
      1.定义守卫

@Injectable()
export 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");//返回Product对象
} else {
this.router.navigate(['/home']);
return undefined;
}
}
注意项:
导入@Injectable()装饰器
构造函数中定义Router对象
返回的是Product对象,所以要在要跳转到的路由的组件中定义Product类
export class Product {
constructor(public id:number,public name:string){}
}

      2.然后在要跳转到的路由配置中,添加 resolve:{ product:ProductResolve}
      3.最后在要激活的路由控制器中接收数据

export class ProductComponent implements OnInit {

private productId:number;
private productName:string;

constructor(private routeInfo:ActivatedRoute) { }

ngOnInit() {
//订阅传进来的数据
this.routeInfo.data.subscribe((data:{product:Product}) =>{
this.productId = data.product.id;
this.productName = data.product.name;
});
}
}

      设置Resolve路由的原因:防止在有插值绑定的html中,在数据没常见来时页面已加载的情况


例子

下面是有关路由知识的例子:
      链接: https://pan.baidu.com/s/1nvj7gmd 密码:rsak

总结

完成一个路由跳转的步骤:

  1. 定义路由插座
  2. 配置路由
  3. 定义路由入口