【问题标题】:Is it a good practice to use a route resolver to pass static data to a route component in Angular 8?使用路由解析器将静态数据传递给 Angular 8 中的路由组件是一种好习惯吗?
【发布时间】:2026-01-24 11:50:01
【问题描述】:

我们有一个User 组件接收用户对象作为@input

export class UserComponent implements OnInit {
  @Input() user: User;

  constructor() {}
}

这里对应的模板:

<div class="user-box">
  <img class="avatar" [src]="user.avatar" alt="user_picture">
  <div class="infos">
    <div class="username">{{ user.username }}</div>
    <div>{{ user.email }}</div>
    <div class="gender">{{ user.gender }}</div>
  </div>
</div>

在路由组件UsersList(主要&lt;router-outlet&gt;)中,我们需要在屏幕上显示用户列表:

<user
  *ngFor="let user of users
  [user]="user"
  (click)="selectUser(user)">
</user>

然后,当我们单击从列表中选择用户时,我们使用相同的User 组件显示选定的用户数据,但这次作为路由组件(命名为&lt;router-outlet name="selected"&gt;):

这里是我们的路线:

const ROUTES: Routes = [
  {
    path: '',
    component: UsersList
  },
  {
    path: ':username',
    component: UserComponent,
    outlet: 'selected'
  }
];

所以,这里是selectUser() 函数:

selectUser(user: User) {
  return this.router.navigate([ { outlets: { selected: [ user.username ] } } ], { state: { user } });
}

在我们的User组件内部,我们需要实现OnInit接口:

if (this.route.outlet === 'selected') {
  this.route.paramMap.pipe(map(() => window.history.state)).subscribe(state => {
    if (!state.user) {
      return this.router.navigate([ { outlets: { selected: null } } ]);
    }
    this.user = state.user;
  });
}

所有这些都非常好!我想知道的是,这样做是否是一个好习惯?

仅供参考,我也尝试使用路由解析器,但我无法访问 NavigationExtras state 对象...在解析器中获取用户数据的唯一方法是将其传递为 @ 987654340@。当我们有 3 个属性时会很好,但是,如果我们有 10+ 个属性,那么 URL 就会变得丑陋和混乱。而且,解析器的角色似乎是解析异步数据而不是传递静态数据。

感谢您提供见解!

【问题讨论】:

    标签: angular angular-routing angular-router angular-resolver


    【解决方案1】:

    良好的做法,或者说“Angular 方式”,是使用文档中所写的路由解析器:https://angular.io/guide/router#fetch-data-before-navigating

    我尽可能使用解析器,因此我可以编写干净的页面组件,以便在实例化时从路由器获取所需的数据(我也可以将解析器重新用于其他路由,但这种情况很少发生)。

    这也使路由彼此独立:我可以在进入用户列表页面之前看到用户页面,我认为我不能用你当前的代码做到这一点。另外,如果用户不存在,我可以直接从解析器重定向到 404 页面。

    顺便说一下,解析器可能有一些缺点需要牢记:

    • 如果您使用实时异步数据,则会丢失实时更新,因为如果仅获取一次文档(通常通过 take(1))并且流将关闭
    • 如果您使用 Ionic 之类的缓存页面的工具,您可能会遇到数据过时的问题

    【讨论】:

    • 这里的主要区别是我没有“用户页面”。我在页面右侧使用辅助路线向用户展示。因此,您永远不会在“用户列表页面”之前看到“用户页面”。您可以随时单击其中一个用户看到两者。
    • 啊,好的,明白了!所以在这种情况下,我会这样做:使用列表页面的解析器来获取所有用户,并使用简单的主/详细模式 (angular.io/tutorial/toh-pt3) 来显示用户。如果您希望能够从 url 中选择一个用户,我会将用户 ID 添加为 param 或 queryParam 并让列表页面选择正确的用户并将其传递给用户组件。这样用户组件就不需要使用路由,变得可重用了。
    • 我已经这样做了,但没有将用户名添加为 queryParam。我一定会试一试,然后回复你。谢谢。