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

Angular 一次激活的路由器命名出口,angular,angular2-routing,angular4-router,Angular,Angular2 Routing,Angular4 Router,是否有可能让路由器命名的出口被激活一次,然后再也不会被破坏,无论在主出口中导航的是什么路线 这样做的目的是让组件保持在页面上(例如,侧栏),但在初始加载时获得路由的好处,例如保护(解析器)和延迟加载 要求是指定的出口不应以任何负面方式影响用户体验,例如通过在SPA URL中引入垃圾后缀,例如(outletName:routeName),它们也不应意外停用。若有办法在初始激活后将它们从路由器上分离,那个么这将是合适的 skipLocationChange选项不能用于此目的。在/login(弹出窗口

是否有可能让路由器命名的出口被激活一次,然后再也不会被破坏,无论在主出口中导航的是什么路线

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

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


skipLocationChange
选项不能用于此目的。在
/login(弹出窗口:compose)
Contact和
login
路线按顺序导航时,会出现
URL。

看来,如果不将次要路线附加到URL,我们就无法使用以指定门店为目标的次要路线。正如您在问题中所建议的,一种可能的解决方案是在激活组件后将其从路由器出口分离。我实施该解决方案的尝试如所示:

激活
事件处理程序中,组件从路由器出口分离,插入
ng容器
,路由器出口被清除。然后,组件可以留在DOM中,而不再使用辅助路由


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

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


想法很简单,反序列化过程应该知道有静态命名出口的路由,并生成包含命名出口的
UrlTree
,即对于
/login
url应该生成与默认序列化程序为url
/login(弹出:compose)
生成的
UrlTree
相同的
。在序列化过程中,静态命名出口参数不应包含在结果url中。

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 }, ...]
...
我们在项目中遇到了相同的(关键的)用户体验需求,并提出了一个半干净但迄今为止功能齐全的解决方案

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

不要忘记在模块中提供:

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

字符串处理显然不是百分之百的干净,但它为我们完成了任务——也许它对您有所帮助。请注意,您的URL现在不能完全重建您的路由器状态(显然)。

您可以创建二级URLoutlets@pixelbits是的,就是这个想法。但它们究竟应该如何定义呢?我相信这个问题足够具体,不会被认为“过于宽泛”,而且可能的高质量答案数量有限。我没有提供任何代码,因为在本例中它是通用的。在中可以看到,当导航主出口时,次
弹出窗口
出口仍然存在,但它会污染URL(弹出窗口:撰写)
。导航时,请指定skipLocationChange:true@pixelbits但这只适用于二级插座上的单一导航。看见单击“联系人”
链接时,url不会更改,但单击“登录”时会出现
(弹出窗口:撰写)
。在这里,我尝试了一下,希望组件在激活后可以移动到另一个容器中(请参阅)。一开始它看起来似乎可以工作,但事实并非如此:绑定在这个过程中丢失了。一旦中请求的功能就位,这可能是您的解决方案。这是一个极好的主意,谢谢。我不确定是否有比我更好的方法来重建url树,但它对我很有用。
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 }, ...]
...
@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,
    },
  ],