ionic4/angular路由配置与导航传参

前言

  • 由于angular官网路由与导航章节介绍的内容太多、太复杂,本文本着实用的目的介绍angular路由的常用配置及导航传参
  • 阅读本文前,建议先阅读[ionic官网路由与导航内容

路由配置

  • 常见的路由配置如下代码,配置说明看代码上的注释,后面还有重难点说明
import { RouterModule } from '@angular/router';

@NgModule({
  imports: [
  ...
  RouterModule.forRoot([
    // 若app启动地址为http://localhost:8100/,则访问LoginPage
    { path: '', component: LoginPage },

    // 访问http://localhost:8100/main,则跳转至mainPage
    { path: 'main', component: mainPage },

    // loadChildren懒加载,参数值是相对模块文件所在路径
    // 访问http://localhost:8100/register,才去加载资源
    // 建议app一级页面使用component,二级页面均使用loadChildren
    {path: 'register', loadChildren: './pages/login/register/register.module#RegisterPageModule'}

     // 访问http://localhost:8100/detail/2,则访问DetailPage,id为动态参数
     {path: 'detail/:id', component: DetailPage },

     // 访问main/666重定向到mainPage
     {path: 'main/666', redirectTo: '/main',  pathMatch: 'full' },

     // pathMatch: 'prefix',访问main/666、main/xxx、main/abc,均跳转到mainPage
     {path: 'main', redirectTo: '/main',  pathMatch: 'prefix' },

     // 路径匹配不到则访问NotFoundPage
     {path: '**', component: NotFoundPage },

     // children(父子路由配置)
     // 访问/tabs跳转到TabsPage,TabsPage只是一个底部导航。也相当于web网站的顶部导航或左侧导航
     // 所以需要访问/tabs/demo,才会显示导航和内容
     // 访问/tabs/tab1/test,显示导航和testPage,test模块使用loadChildren懒加载
    {
        path: 'tabs',
        component: TabsPage,
        children: [
            {path: 'demo', component: DemoPage},
            {path: 'tab1', component: Tab1Page},
            {path: 'tab1/test', loadChildren: './pages/tab1/test/test.module#TestPageModule'},
            {path: 'mine', component: MinePage}
        ]
    }

  ])
  ],
})
  • 使用component,需要在对应的模块declarations中声明组件
  • 使用loadChildren加载子模块,路径是相对相对路径,相对于父模块文件所在路径;什么时候会用loadChildren配置?
    在web端界面一般顶部或左侧有导航,下面或右侧显示内容,在app端一般底部有tab导航,上面显示内容;如下配置,TabsPage就是导航界面,children配置内容界面路由
    {
        path: 'tabs',
        component: TabsPage,
        children: [
            {path: 'demo', component: DemoPage},
            {path: 'mine', component: MinePage}
        ]
    }
  • 根模块是forRoot子模块是forChild,如下图所示
  • 建议app一级页面使用component配置,二级页面使用loadChildren,如下图是我的路由配置,TabsPage是导航页面,Tab1Page、DemoPage、MinePage是一级页面,其余是二级页面
    考虑多人开发,若同时修改一份路由文件,会经常冲突,所以按业务分类多个配置文件,所以下图出现...tab1Routes、...demoRoutes、 ...mineRoutes,完整代码点这里
  • redirectTo重定向有个坑,假如配置如下,由于TabPage使用component配置,则应用启动时就会加载TabPage,当你后来导航到/test,则会重定向到TabPage,此时TabPage就会初始化第二次,如果你在constructor()中对全局对象做过修改那就回修改第二次
    我当时在tabs.page.ts文件中订阅android返回按钮事件,就订阅了两次,而且只能在真机调试中发现,坑很深
const routes: Routes = [
    {path: 'test', redirectTo: 'tab',  pathMatch: 'full' },
    {path: 'tab',  component: TabPage}
];
  • 刚开始对路由配置不熟悉,应尽量避免使用path: ''配置,尤其类似下面的重定向,要不然会让你懵逼
 { path: '', redirectTo: '/path', pathMatch: 'full'}

如下gif图,从tab2跳转到test页面,点击返回,竟然返回到了tab1页面,如下图2注释默认生成的path: ''路由即可


图2

  • 如下图红色框内代码,是给页面动态添加返回按钮,当页面是根页面时,返回按钮不显示;当ion-back-button添加defaultHref属性后,即使是根页面或按F5刷新页面也会显示返回按钮,点击返回按钮返回到指定页面
        <ion-buttons slot="start">
            <ion-back-button defaultHref="/tabs/tab1"></ion-back-button>
        </ion-buttons>

导航

  • 如下是最基本的路由配置
    { path: 'main', component: mainPage }
  • 在html中和ts中导航到mainPage 方法如下
    <ion-button routerLink="/main">next page</ion-button>
    <ion-button [routerLink]="['/main']">next page</ion-button>
     constructor(public router: Router, public nav: NavController) {}
     next() {
        this.router.navigateByUrl('/main');
        this.router.navigate(['/main']);
        this.nav.navigateForward('/main');
     }
  • 返回方式如下。返回和上面的“navigate”方法动画是不一样的
    goBack() {
        this.nav.pop(); // 返回到上一个页面
        this.nav.back(); // 同上
        this.nav.navigateBack('/'); // 可以指定返回的页面路径
    }

  • 如下是url带参数的路由配置
    {path: 'detail/:id', component: DetailPage }
  • 在html中和ts中导航到DetailPage 方法如下,注意参数是在数组内,不是方法内
    <ion-button [routerLink]="['/detail', 6]">next page</ion-button>
     constructor(public router: Router) {}
     next() {
        this.router.navigate(['/detail, 6']);
     }
  • 接收url参数两种方法,注意这里用的是ActivatedRoute不是Router
  constructor(private route: ActivatedRoute) {
      const params = this.route.snapshot.params;
      console.log(params.id);
      
      this.route.params.subscribe(res => {
          console.log(res.id);
      });
  }

  • 导航传递对象参数
this.router.navigateByUrl('/main?page=1&size=10');
this.router.navigate(['/main'], {queryParams: {page: 1, size: 10}});

注意这样传参是接收不到的
this.nav.navigateByUrl('/main', {queryParams: {page: 1, size: 10}});

  • 接收参数两种方法
    constructor(private route: ActivatedRoute) {
        const queryParams = this.route.snapshot.queryParams;
        console.log(queryParams);
        
        this.route.queryParams.subscribe(res => {
            console.log(res);
        });
    }
  • 还有其他传递参数的方法。如发布订阅事件,使用Service,全局对象,本地存储等

其他

  • 默认情况下,应用登录成功后跳转到主页,这时候点击返回按钮又返回到登录页,这是不科学的。所以需要使用如下NavController.navigateRoot方法设置主页面为顶层页面
constructor(public nav: NavController) {}
login() {
    this.nav.navigateRoot('/tabs/tab1');
}
  1. CanActivate路由入口守卫:访问页面前执行业务处理,可以用于访问鉴权,先判断是否有权限访问该页面
  2. CanDeactivate路由出口守卫:离开页面前执行业务处理,如用户填写了表单未保存,点击了返回,可以提示是否保存
  3. 路由动画NavController在ionic3也有,ionic4继续存在,就是封装了返回/前进动画等功能