首页 文章

路由器命名为激活一次的出口

提问于
浏览
8

无论在主插座中导航的路线是什么,是否可以将路由器命名为出口一次激活然后永不销毁?

目的是让组件在页面上保持不变(例如, sidebar ),但在初始加载时获得路由的好处 - 例如防护(解析器)和延迟加载 .

要求是命名出口不应以任何负面方式影响UX,例如通过向SPA URL引入垃圾后缀,例如, (outletName:routeName) ,他们也不应该在初始激活后将它们与路由器分离,这是合适的 .

skipLocationChange 选项不能用于此目的 . 在this example /login(popup:compose) 中,当按顺序导航 ContactLogin 路径时,将显示URL .

3 回答

  • 2

    路由器需要有关命名出口的信息,因此很有可能实现自己的 UrlSerializer 会有所帮助 .

    想法很简单,反序列化过程应该知道具有静态命名出口的路由并产生包含命名出口的 UrlTree ,即 /login url应该产生相同的 UrlTree ,因为默认序列化器将为url /login(popup:compose) 产生 . 在序列化期间,静态命名的出口参数不应包含在结果URL中 .

  • 1

    看来我们不能使用针对指定出口的辅助路由,而不会将辅助路由附加到URL . 正如您的问题中所建议的,一种可能的解决方案是在激活后将组件从路由器插座上拆下 . 我在this stackblitz中显示了实现该解决方案的尝试:

    <router-outlet name="popup" #popupRouterOutlet (activate)="processActivate($event)"></router-outlet>
    <ng-container #popupContainer></ng-container>
    
    export class AppComponent {
    
      @ViewChild("popupRouterOutlet", { read: ViewContainerRef }) private popupRouterOutlet: ViewContainerRef;
      @ViewChild("popupContainer", { read: ViewContainerRef }) private popupContainer: ViewContainerRef;
    
      constructor(public router: Router) {
      }
    
      processActivate(e) {
          let viewRef = this.popupRouterOutlet.detach(0);
          this.popupContainer.insert(viewRef);
          this.router.navigate([".", { outlets: { popup: null } }]);
      }
    }
    

    activate 事件处理程序中,组件与路由器插座分离,它插入 ng-container ,并清除路由器插座 . 然后组件可以保留在DOM中,而不再使用辅助路由 .

    组件的静态内容已成功传输,但不幸的是,绑定不是 . 这个问题已经报道过了 . 已在Angular Github上在issue 20824中发出请求,以允许将组件从一个容器移动到另一个容器 . 在实现该功能请求之前,似乎不可能进行这种转移 .

  • 3

    skipLocationChange 导航选项仅适用于其提供的路由器,然后命名插座出现在URL中,如 /login(foo:bar) .

    正如@kemsky所建议的那样,可以通过覆盖 UrlSerializer 来获得永久的 foo 路由器插座:

    import {
      UrlSerializer, DefaultUrlSerializer, UrlSegmentGroup, UrlTree
    } from '@angular/router';
    
    export class FooUrlSerializer extends DefaultUrlSerializer {
      serialize(tree) {
        const { foo, ...noFooChildren } = tree.root.children;
        const root = new UrlSegmentGroup(tree.root.segments, noFooChildren);
        const noFooTree = Object.assign(new UrlTree(), tree, { root });
    
        return super.serialize(noFooTree);
      }
    }
    
    ...
    providers: [{ provide: UrlSerializer, useClass: FooUrlSerializer }, ...]
    ...
    

相关问题