1

我们有一个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(primary <router-outlet>)中,我们需要在屏幕上显示用户列表:

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

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

应用模型

这里我们的路线:

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对象...在解析器中获取用户数据的唯一方法是将其传递为queryParams. 当我们有 3 个属性时会很好,但是,如果我们有 10 多个属性,URL 就会变得丑陋和混乱。而且,解析器的角色似乎是解析异步数据而不是传递静态数据。

感谢您提供见解!

4

1 回答 1

1

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

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

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

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

  • 如果您使用实时异步数据,则会丢失实时更新,因为如果文档仅获取一次(通常通过 take(1) 获取)并且流被关闭
  • 如果您使用的是像 Ionic 这样缓存页面的东西,您可能会遇到过时数据的问题
于 2019-11-26T21:36:58.640 回答