【问题标题】:Structuring Angular 2 application with interdependent components使用相互依赖的组件构建 Angular 2 应用程序
【发布时间】:2017-05-15 13:11:01
【问题描述】:

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

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

Top level template structure:

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

菜单应该是一个独立于任何其他组件或功能区域的组件,并且不应该知道额外的导航组件,但它应该包装这个组件。

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

    这种模式的总体思路是在主视图组件(上面的 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 的子节点,而只是转发到路由器。路由器实现只是为每个嵌入式视图出口提供一组 BehaviorObservables。

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

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

    使用这种模式,您可以构建注入多个视图的路由器,只需触摸一个文件,并将逻辑全部保存在一个地方。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-11
      • 2018-02-09
      • 1970-01-01
      • 2014-10-11
      • 1970-01-01
      • 2010-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多