【问题标题】:How to import directives without repeatedly writing to some components如何在不重复写入某些组件的情况下导入指令
【发布时间】:2016-05-03 08:19:13
【问题描述】:

我正在使用 Angular2 和 TypeScript 创建 Web 应用程序。当我创建一些 CustomElements(它的意思是组件和指令,验证器)时,我发现我为每个组件编写了 directives: [...] 代码,以便像下面的代码一样导入 CustomElements。

// my_comopnent_1.comopnent.ts
@Component({
  selector: 'my-component-1',
  directives: [
    ROUTER_DIRECTIVES,
    MyDirective1,
    MyDirective2,
    MyValidator1,
    MyValidator2,
    ...
  ],
})

// my_comopnent_2.comopnent.ts
@Component({
  selector: 'my-component-2',
  directives: [
    ROUTER_DIRECTIVES,
    MyDirective1,
    MyDirective2,
    MyValidator1,
    MyValidator2,
    ...
  ],
})

// my_comopnent_3.comopnent.ts
@Component({
  selector: 'my-component-3',
  directives: [
    ROUTER_DIRECTIVES,
    MyDirective1,
    MyDirective2,
    MyValidator1,
    MyValidator2,
    ...
  ],
})

是否存在无需重复写入directives: [...] 即可导入一些CustomComopnents 的方式,例如事件冒泡或原型链? 我的理想是,当我将代码编写到父组件时,它的子组件包括父组件导入的自定义元素。

// parent.component.ts
@Component({
  selector: 'parent',
  directives: [MyDirective1, ...],
})

// child.component.ts
@Component({
  selector: 'child',
  template: `
    // It's possible to use MyDirective because of importing by ParentComponent.
    <div my-directive></div>
  `,
})

【问题讨论】:

    标签: typescript angular


    【解决方案1】:

    您可以通过这种方式将它们定义为平台指令:

    export const GENERAL_DIRECTIVES: any[] = [
      ROUTER_DIRECTIVES,
      MyDirective1,
      MyDirective2,
      MyValidator1,
      MyValidator2,
      (...)
    ];
    
    bootstrap(App, [
      provide(PLATFORM_DIRECTIVES, {useValue: [GENERAL_DIRECTIVES], multi: true})
    ]);
    

    这样你就不需要每次都导入了。

    查看这个问题了解更多详情:

    这种方法的主要缺点是它们对应用程序中的所有组件都是全局的。另一种方法包括创建一个自定义装饰器,该装饰器扩展组件元数据(directives 属性)以添加这些组件/指令。通过这种方式,您可以精细地控制要自动指定这些指令的位置。

    这种机制可以依赖于继承,即抽象根组件。

    这是一个示例:

    export function CustomComponent(annotation: any) {
      return function (target: Function) {
        var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
        var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
    
        var parentAnnotation = parentAnnotations[0];
        Object.keys(parentAnnotation).forEach(key => {
          if (isPresent(parentAnnotation[key])) {
            if (key === 'directives') {
              // merge directives attributes
              let parentDirectives = parentAnnotation[key] || [];
              let currentDirectives = annotation[key] || [];
              currentDirectives.concat(parentDirectives);
            } else {
              annotation[key] = parentAnnotation[key];
            }
          }
        });
        var metadata = new ComponentMetadata(annotation);
    
        Reflect.defineMetadata('annotations', [ metadata ], target);
      }
    }
    

    并使用它:

    @Component({
      directives: [
        ROUTER_DIRECTIVES,
        MyDirective1,
        MyDirective2,
        MyValidator1,
        MyValidator2,
        (...)
      ]
    })
    export class AbstractComponent {
    }
    
    @CustomComponent({
      selector: 'sub',
      template: `
        (...)
      `
    })
    export class SubComponent extends AbstractComponent {
    }
    
    @Component({
      selector: 'app',
      template: `
        <sub></sub>
      `,
      directives [ SubComponent ]
    })
    export class App {
    }
    

    查看这个问题了解更多详情:

    【讨论】:

      【解决方案2】:

      您可以全局提供指令和管道,如

      bootstrap(AppComponent, [
          provide(PLATFORM_DIRECTIVES, 
              {useValue: [
                  ROUTER_DIRECTIVES, 
                  MyDirective1, 
                  MyDirective2, 
                  MyValidator1, 
                  MyValidator2
               ], multi: true}),
      
          provide(PLATFORM_PIPES, 
               {useValue: [RainbowizePipe], multi:true})
      
      ]);
      

      您传递的指令和管道数组由 Angulars DI 自动展平,这允许传递任意嵌套数组。 例如将一个模块的指令打包成一个数组,然后最后将一个包含所有模块数组的数组传递给provide()

      【讨论】:

      • 谢谢。我不知道创建全局组件会与 DI 有关。
      • Angular 在内部也使用 DI :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      相关资源
      最近更新 更多