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