【问题标题】:How to implement master/detail components without hierarchical routes?如何在没有分层路由的情况下实现主/细节组件?
【发布时间】:2021-08-05 01:15:23
【问题描述】:

我正在尝试一起实现以下内容。

带有路由/items(复数)的索引页面。此页面可滚动。

单击单个项目时,我想显示详细信息页面,但路径必须是 /item/:id(单数)。

有一个返回按钮详细页面。单击时,它应该返回到/items,但应该保持在它离开的相同滚动位置。

我想把它作为一个主要细节来实现。但我的路线不在层次结构中?

我应该如何处理?

我可以/items and /items/:id(都是复数形式)

/item and /item/:id(均为单数)

但我想要一个单数和一个复数

路由配置文件

app-routing.ts

{
    path: 'items',
    loadChildren: () => import('./pages/items/items.module').then(m => m.ItemsModule),
    data: { animation: 'Items'}
  },
  {
    path: 'item',
    loadChildren: () => import('./pages/Item/Item.module').then(m => m.ItemModule),
    data: { animation: 'Item', type: 'Item'}
  },

项目路由配置。

[{
  path: ':id',
  component: ItemComponent,
  resolve: {
    item: ItemResolverService
  },
  runGuardsAndResolvers: 'paramsOrQueryParamsChange'
}]

【问题讨论】:

  • 你在使用延迟加载路由吗?你能分享你当前的路线配置吗
  • 已在帖子中编辑

标签: angular routes


【解决方案1】:

您应该像这样创建一个顶级延迟加载路由:

{
  path: 'my-items',
  loadChildren: () => import('./pages/my-items/my-items.module').then(m => m.MyItemsModule)
}

然后使用 Angular CLI 创建一个新的路由模块,如下所示:

ng generate module pages/my-items/my-items --routing=true

这将创建一个包含 2 个模块文件的路由模块。其中一个模块文件包含 my-items 路由的子路由。

在这个模块文件中,你应该像这样定义你的子路由:

[
  {
    path: 'items',
    component: ItemsComponent
  },
  {
    path: 'item/:id',
    component: ItemComponent
  }
]

您显然需要创建这两个组件(ItemsComponent 和 ItemComponent),并且它们应该嵌套在使用它们的模块文件夹中。同样,您可以使用 Angular CLI 生成这些组件(如果您这样做并且它们按照说明嵌套,它应该自动在正确的模块中声明它们)。

ng generate component path/component-name

ng g c path/component-name

您可以在以下位置访问这些路线:

/my-items/items

/my-items/item/ITEM_ID

滚动:

在用户单击 BACK 时保持滚动位置:

在主视图中使用:

@ViewChild('scrollableEl ') scrollableEl: ElementRef;

然后在您的 HTML 中添加 #scrollableEl 到可滚动元素。

您现在有了可滚动元素的句柄。

然后做这样的事情:

ngAfterViewInit(): void {
  const scrollEl: HTMLElement = this.scrollableEl.nativeElement;
  // set last known scroll top value when master view loads
  const strScrollTop: string = sessionStorage.getItem('scrollTop');
  const scrollTop: number = strScrollTop ? parseInt(strScrollTop, 10) : 0;
  scrollEl.scrollTop = scrollTop;
  // keep track of the last known scroll position
  scrollEl.onscroll = () => {
    sessionStorage.setItem('scrollTop', scrollEl.scrollTop);
  };
}

您无需向详细视图添加任何代码。

这个解决方案基本上会跟踪 sessionStorage 中最后一个已知的滚动位置。当主组件加载时,它将列表滚动到最后一个已知的滚动位置。我的代码没有经过测试,所以这里或那里可能有一个错误或 2 个错误,但你应该明白了。

根据评论的示例 SETINTERVAL 聪明代码

如果您的滚动元素在页面加载时还没有准备好,这是一些示例代码,可以在元素准备好后立即抓取它。它总是尽快清除间隔。您将需要定制此代码以满足您的需求。

@ViewChild('summaries') summaries: ElementRef;

ngAfterViewInit(): void {
  this.doScroll();
}

@HostListener('window:resize')
onResize(): void {
  this.doScroll();
}

private doScroll(): void {
  this.whenElementReady('summaries').then((el: HTMLElement) => {
    if (el) {
      // change this to the scrollTop value that you need
      el.scrollTop = 0;
    }
  });
}

private whenElementReady(elementName: string): Promise<HTMLElement> {
  return new Promise((resolve) => {
  // will keep trying for 30 seconds
    const maxAttempts = 300;
    let attempts = 0;
    const interval = setInterval(() => {
      const el: HTMLElement = this[elementName]?.nativeElement;
      if (el) {
        clearInterval(interval);
        resolve(el);
      } else if (attempts > maxAttempts) {
        clearInterval(interval);
        resolve(null);
      }
      attempts++;
    }, 100);
  });
}

【讨论】:

  • 这不仅仅是常规的东西。当用户从孩子转到父母时,我还想保留滚动位置。这就是为什么我试图将它实现为类似主细节的行为,当子路由被销毁时,父路由保持原样。在上述情况下,从 /item/:id 返回项目时,页面会滚动到顶部,这对我来说不是很好的体验。
  • 我刚刚在我的答案中添加了滚动部分
  • master-detail 仅在您描述在同一视图上一起呈现主视图和细节的位置时起作用 - 例如掌握 LHS 并详细了解 RHS - 在这种情况下不需要我概述的解决方案
  • 我通过传递路线参数将我的路线标记为“前进”、“后退”。为前进保存了滚动位置,并为后退恢复了相同的滚动位置。它工作得很好,但是当用户返回时,路由动画和滚动会同时发生。仍在尽我最大的努力完成这项工作。
  • 如果您基本上是说当滚动突然向下跳时页面加载有点生涩,那么您是否考虑过使用动画(例如淡入页面)来隐藏抖动 - 如果您设置了按照我的建议进行路由配置,然后每次访问主视图时都应该调用 ngOnInit 和 ngAfterViewInit - 将滚动代码放在 ngAfterViewInit 中。如果你的滚动元素没有及时准备好,那么使用 setTimeout 或 setInterval - 你可以让它变得聪明 - 我在我的答案中粘贴了一些聪明的 setInterval 示例,以防它有帮助
猜你喜欢
  • 2016-04-05
  • 1970-01-01
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 2017-02-11
  • 2019-05-22
相关资源
最近更新 更多