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

时间:2017-05-09 21:30:24

标签: architecture angular2-routing angular2-components router-outlet

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

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

Top level template structure:

<sidenav>
  <featureA-nav-fragment></featureA-nav-fragment>
</sidenav>
<router-outlet>
  <!-- featureA component -->
</router-outlet>

菜单应该是与任何其他组件或功能区域无关的组件,并且不应该知道其他导航组件,但它应该包装此组件。

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

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

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

我还没有在角度文档中找到这样一个用例的好设计。我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:0)

我终于找到了自己的解决方案。

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

这种模式的一般思想是在主视图组件的模板中使用特定的结构指令(上面的featureA组件)。

<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);
  }
}

使用此结构指令进行调查的部分不会附加到功能A的子项中,而只会附加到路由器上。路由器实现是每个嵌入式视图插座的一组BehaviorObservable。

另一个指令用于定义嵌入视图的出口:

@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);
      }
    });
  }
}

使用此模式,您可以构建路由器,只需触摸单个文件即可注入多个视图,并将逻辑保存在一个位置。