【问题标题】:div that remains in the DOM for all routes保留在 DOM 中的所有路由的 div
【发布时间】:2021-07-15 10:40:36
【问题描述】:

我正在开发一个使用 Vimeo 对象的 Angular 应用程序。我正在使用路由,并且在其中一个组件/页面中,我显示视频的那个,我有以下 div:

<div id="VimeoVideoDiv" class="message-fullarea" data-vimeo-controls="false" data-vimeo-autoplay="false"></div>

因此,当显示视频页面时,vimeo 在这里渲染得很好,它会注入一个 iframe,一旦您按下播放,它就会开始缓冲,然后播放视频。在某些时候,我想暂停视频并移动到另一个页面以捕获一些数据。提交数据后,我想将用户重定向到视频页面并继续从它离开的地方播放视频。问题是视频从头开始播放。您可能认为我可以将时间设置为暂停的 x 秒,但这样做会导致再次缓冲,这是我想避免的。

这是因为当路由到捕获数据页面时,视频页面被破坏(从 DOM 中删除)。我想的一种方法是将 vimeo 播放器 div 保留在 app.component.ts 中,在路由器出口之前,并以某种方式将其注入视频页面/组件。

这可能吗?还有其他选择吗?

【问题讨论】:

    标签: angular vimeo


    【解决方案1】:

    是的,可以将其添加到app.component.ts 以确保它不会被破坏。

    另一个想法是将组件包装在另一个组件中并在内部使用&lt;router-outlet&gt;&lt;/router-outlet&gt;

    在模块中应该是这样的:

    const routes:Routes = [
    {path:'', component:VimeoContainerComponent, children: [
        {path: 'somepath', component:SomeComponent },
        {path: '....', .... } ,
        ....
        ]}
    ]
    

    VimeoContainerComponent 应该如下所示:

    <div id="VimeoVideoDiv" class="message-fullarea" data-vimeo-controls="false" data-vimeo-autoplay="false"></div>
    <router-outlet></router-outlet>
    

    现在将显示它的所有子元素,并且 div 将保持不变。

    另外,你没有把你的app.component弄脏!

    欲了解更多信息, https://angular.io/guide/router#nesting-routes

    【讨论】:

    • 这就是我目前正在尝试的,但问题是现在视频呈现在路由中指定的所有页面/组件之上。例如,在 VimeoComponent 中,我有一个标题,然后是视频,然后是底部的 2 个按钮,如果我将 div 设置在 router-outlet 上方,那么它将呈现在标题上方。有没有办法在特定的地方展示它?
    • 您可以使用 'position: absolute/ position: fixed' 和 z-index 或将其导出到组件并通过在特定位置调用它来明确决定它在每个组件中的位置跨度>
    • 我明白你的意思。我的第一次尝试是将视频和表单放在同一个组件中,并使用 [style.display]="showVideo? 'block' : 'none'" 隐藏视频,但我有一些路线动画和隐藏/显示和对于块 & none 很难将元素向左/向右移动。你的方法也有同样的问题。
    • 请在提问时更加具体,以便我们提供更好的帮助!
    【解决方案2】:

    您可以尝试为您的应用实现RouteReuseStrategy。这将允许您分离您的视频路线,而不是销毁它、存储它并在以后重复使用它。重用的路由会渲染得非常快——基本上就像路由缓存一样。

    这不是 Angular 中一个有据可查的功能(或者是一个方便的功能,恕我直言),你必须四处看看如何使用它,但这里有一些东西可以帮助你入门:

    export class CustomRouteReuseStrategy implements RouteReuseStrategy {
      private storedRoutes = new Map<any, DetachedRouteHandle>();
    
      shouldDetach(route: ActivatedRouteSnapshot): boolean {
        return this.isVideoRoute(route);
      }
    
      store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
        this.storedRoutes.set(route.routeConfig, handle);
      }
    
      shouldAttach(route: ActivatedRouteSnapshot): boolean {
        return this.storedRoutes.has(route.routeConfig);
      }
    
      retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
        return this.storedRoutes.get(route.routeConfig);
      }
    
      shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        return future.routeConfig === curr.routeConfig;
      }
    
      private isVideoRoute(route: ActivatedRouteSnapshot): boolean {
        // Determine somehow that this is the route containing the video.
      }
    }
    

    这是一个非常原始且有缺陷的实现,您可能需要做很多事情才能使其真正正常工作,例如:

    • 如果存储的路线在某些时候没有被重复使用,则手动销毁它;
    • 使用不同的机制来存储路线;
    • 实现一些方法,例如ngOnReactivate,路由即将恢复时调用;

    【讨论】:

    • 我试过那个,我可以看到重用视频路由时没有调用 ngOnDestroy 但 DOM 不见了。除非有办法保持 DOM 存在(当然是隐藏的),否则它不起作用
    • @Bonomi 我明白了。使用辅助路由器插座和简单的display: none 怎么样?在主路由更改时切换?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 2015-09-22
    • 2020-02-26
    • 2022-11-27
    • 2016-07-05
    • 2018-02-02
    相关资源
    最近更新 更多