Architecture 使用相互依赖的组件构建Angular 2应用程序

Architecture 使用相互依赖的组件构建Angular 2应用程序,architecture,angular2-routing,angular2-components,router-outlet,Architecture,Angular2 Routing,Angular2 Components,Router Outlet,我正在为Angular 2应用程序寻找一个好的结构,它有一些类似于相互依赖的组件 以下是问题的基本思路: 应该有侧导航菜单组件和一个包含路由器出口的内容区。对于某些路线,侧边组件应包含一个用于导航的附加组件(例如,用于快速访问的项目列表,其中主内容区域为“详细视图”) 顶级模板结构: 菜单应该是一个独立于任何其他组件或功能区域的组件,不应该知道附加导航组件,但它应该包装此组件 实现的一种方法是只定义as顶级组件,在路由定义的每个屏幕中,在HTML模板中提供侧菜单。在我看来,这是一个糟糕的设计,

我正在为Angular 2应用程序寻找一个好的结构,它有一些类似于相互依赖的组件

以下是问题的基本思路: 应该有侧导航菜单组件和一个包含路由器出口的内容区。对于某些路线,侧边组件应包含一个用于导航的附加组件(例如,用于快速访问的项目列表,其中主内容区域为“详细视图”)

顶级模板结构:
菜单应该是一个独立于任何其他组件或功能区域的组件,不应该知道附加导航组件,但它应该包装此组件

实现的一种方法是只定义as顶级组件,在路由定义的每个屏幕中,在HTML模板中提供侧菜单。在我看来,这是一个糟糕的设计,因为部分HTML代码是重复的

另一种选择是在菜单组件中的活动路线上创建一个开关,并在其中包含正确的导航片段,但这会将路线(屏幕)的逻辑扩展到几个组件中,这对我来说似乎是一个更糟糕的设计

为导航片段使用命名的路由器出口也不是正确的方法,因为组件不是彼此独立显示的,而是始终一起显示的。手动修改路线(清除导航碎片部分)将破坏设计


我还没有在angular文档中找到这样一个用例的好设计。我在这里遗漏了什么吗?

我终于自己找到了一个可行的解决方案

如果您遇到某些组件应该将其模板内容的一部分注入另一个组件的问题,您可能希望使用自定义路由器服务的结构指令

此模式的总体思想是在主视图组件(上面的featureA组件)的模板中使用特定的结构指令

使用此模式,您可以构建路由器,只需触摸一个文件,即可将其插入多个视图中,并将所有逻辑保持在一个位置

Top level template structure:

<sidenav>
  <featureA-nav-fragment></featureA-nav-fragment>
</sidenav>
<router-outlet>
  <!-- featureA component -->
</router-outlet>
<div *embeddedIntoNav>some navigation related content</div>   
<div>
  Feature A view
<div>
@Directive({
  selector: '[embeddedIntoNav]'
})
export class EmbeddedIntoNavDirective {

  constructor(
    private customRouter: CustomRouter,
    private templateRef: TemplateRef<any>
  ) { }

  ngOnInit() {
    this.customRouter.navContent$.next(this.templateRef);
  }

  ngOnDestroy() {
    this.customRouter.navContent$.next(null);
  }
}
@Directive({
  selector: 'nav-container'
})
export class NavContainerDirective implements OnInit {

  constructor(
    private viewContainer: ViewContainerRef,
    private customRouter: CustomRouter
  ) {
  }

  ngOnInit() {
    this.customRouter.navContent$.subscribe((template) => {
      this.viewContainer.clear();
      if (template) {
        this.viewContainer.createEmbeddedView(template);
      }
    });
  }
}