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

时间:2018-02-16 23:17:24

标签: angular angular2-routing angular4-router

是否有可能让路由器命名的插座被激活一次,然后永远不会被破坏,无论在主插座中导航的路线是什么?

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

要求是指定的出口不应以任何负面方式影响用户体验,例如通过向SPA URL引入垃圾后缀,例如, (outletName:routeName),他们也不应该被意外停用。如果在初始激活后有一种方法可以将它们与路由器分离,那么这是合适的。

skipLocationChange选项不能用于此目的。在/login(popup:compose) Contact网址中,当Login//print V int hight=2; int rowLen = (hight-1)*2; for (i=0; i<hight; i++) { for (int zz=0;zz<=i;zz++) { System.out.print(" "); } for (int zy=i-1;zy<=0;zy++) { System.out.print("* "); } //print space for (int s=0;s<=3+i;s++) { System.out.print(" "); } //print * 路由按顺序导航时,会显示。

4 个答案:

答案 0 :(得分:3)

路由器需要有关指定商店的信息,因此很有可能实施您自己的UrlSerializer会有所帮助。

理念很简单,反序列化过程应该知道具有静态命名出口的路由并生成包含命名出口的UrlTree,即/login url应该生成与默认序列化器相同的UrlTree将生成网址/login(popup:compose)。在序列化期间,静态命名的出口参数不应包含在生成的URL中。

答案 1 :(得分:2)

看来我们不能使用针对指定商店的辅助路由,而不会将辅助路由附加到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中,而不再使用辅助路由。

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

答案 2 :(得分:1)

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

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

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 }, ...]
...

答案 3 :(得分:1)

我们在项目中遇到了相同(关键)的UX需求,并提出了一个半干净但到目前​​为止功能完整的解决方案。

实施自定义LocationStrategy,我们只需扩展默认的PathLocationStrategy类并预处理URL(将显示给用户/浏览器):

@Injectable()
export class OnlyPrimaryLocationStrategy extends PathLocationStrategy implements LocationStrategy {
  static readonly AUX_ROUTE_SEPERATOR = '//';

  replaceState(state: any, title: string, url: string, queryParams: string): void {
    super.replaceState(state, title, this.preprocessUrl(url), queryParams);
  }

  pushState(state: any, title: string, url: string, queryParams: string): void {
    super.pushState(state, title, this.preprocessUrl(url), queryParams);
  }

  preprocessUrl(url: string): string {
    if (url.includes(OnlyPrimaryLocationStrategy.AUX_ROUTE_SEPERATOR)) {
      if (url.split(OnlyPrimaryLocationStrategy.AUX_ROUTE_SEPERATOR).length > 2) {
        throw new Error(
          'Usage for more than one auxiliary route on the same level detected - please recheck imlementation'
        );
      }
      return url.split(OnlyPrimaryLocationStrategy.AUX_ROUTE_SEPERATOR)[0].replace('(', '');
    } else {
      return url;
    }
  }
}

不要忘记在您的模块中提供它:

providers: [
    {
     // ...
      provide: LocationStrategy,
      useClass: OnlyPrimaryLocationStrategy,
    },
  ],

字符串处理显然不是100%干净的,但是它可以为我们完成工作-也许可以帮助您。请注意,您的URL现在不完全能够(显然)重建路由器状态。