You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于进度数组使用Ionic Auth Guard的canLoad限制页面访问?

嘿,这个需求完全可以用单个Auth Guard搞定!我来给你一步步拆解实现思路和代码:

解决方案

1. 给路由绑定进度索引

首先,在你的路由配置里,给每个课程页面的路由添加自定义data属性,把页面对应的progress数组索引存进去。这样单个Guard就能通过路由数据知道当前要访问的页面对应哪个进度节点:

const routes: Routes = [
  {
    path: 'course',
    children: [
      {
        path: 'page1',
        loadChildren: () => import('./pages/page1/page1.module').then(m => m.Page1Module),
        canLoad: [CourseProgressGuard], // 后面会定义这个Guard
        data: { requiredProgressIndex: 0 } // 对应progress[0]
      },
      {
        path: 'page2',
        loadChildren: () => import('./pages/page2/page2.module').then(m => m.Page2Module),
        canLoad: [CourseProgressGuard],
        data: { requiredProgressIndex: 1 } // 对应progress[1]
      },
      {
        path: 'page3',
        loadChildren: () => import('./pages/page3/page3.module').then(m => m.Page3Module),
        canLoad: [CourseProgressGuard],
        data: { requiredProgressIndex: 2 } // 对应progress[2]
      },
      // 不管多少页面,都按这个模式添加就行
    ]
  }
];

2. 全局管理进度状态(推荐)

把progress数组放在一个全局服务里,用Observable维护,这样进度变化时Guard能实时响应,也方便各个页面更新进度:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class ProgressService {
  // 用BehaviorSubject保存进度,初始值按你的需求设置
  private progressSubject = new BehaviorSubject<boolean[]>([true, false, false]);
  progress$ = this.progressSubject.asObservable();

  // 更新进度的方法,比如页面1结束时调用
  updateProgress(newProgress: boolean[]) {
    this.progressSubject.next(newProgress);
  }
}

3. 编写单个Auth Guard的canLoad逻辑

这个Guard会读取路由的requiredProgressIndex,对比当前用户的活跃进度,决定是否允许加载页面,不允许的话直接导航回当前应该在的页面:

import { Injectable } from '@angular/core';
import { CanLoad, Route, Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ProgressService } from './progress.service';

@Injectable({ providedIn: 'root' })
export class CourseProgressGuard implements CanLoad {
  constructor(
    private progressService: ProgressService,
    private router: Router
  ) {}

  canLoad(route: Route): Observable<boolean | UrlTree> {
    return this.progressService.progress$.pipe(
      map(progress => {
        // 找到当前用户所在的进度节点(数组中唯一为true的索引)
        const currentActiveIndex = progress.findIndex(isActive => isActive);
        // 获取要访问页面对应的进度索引
        const targetIndex = route.data?.requiredProgressIndex;

        // 核心校验:只能访问当前活跃进度对应的页面
        if (targetIndex === currentActiveIndex) {
          return true; // 允许加载页面
        } else {
          // 尝试跳转时,导航回当前应该在的页面
          const currentPagePath = `course/page${currentActiveIndex + 1}`;
          return this.router.parseUrl(currentPagePath);
        }
      })
    );
  }
}

4. 在页面中更新进度

比如页面1结束时,调用服务的updateProgress方法切换进度:

// page1.component.ts
import { ProgressService } from '../progress.service';
import { Router } from '@angular/router';

constructor(
  private progressService: ProgressService,
  private router: Router
) {}

onPageComplete() {
  // 更新进度:页面1完成,切换到页面2的进度状态
  this.progressService.updateProgress([false, true, false]);
  // 自动导航到页面2(也可以让用户手动点击,按需求选择)
  this.router.navigate(['/course/page2']);
}
关键逻辑说明
  • 复用性:不管你有多少个课程页面,只需要在路由里添加canLoad: [CourseProgressGuard]和对应的requiredProgressIndex,Guard的逻辑完全不用修改。
  • 拦截所有跳转:不管用户是通过导航链接、地址栏输入还是其他方式跳转,canLoad都会拦截校验,确保只能访问当前进度对应的页面。
  • 响应式更新:用Observable维护进度,进度变化时Guard会自动重新校验,保证状态一致。

内容的提问来源于stack exchange,提问作者Pine van Wageningen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 10:17:44