2

仕事の制約のためにES6 / ES7を使い続けながら、ロープを学び、切り替えを試みているため、Angular 2内でカスタムコンポーネントに取り組んでいます。次のように定義されたコンポーネントがあるとします。

// Import Inject, Component and View constructor (for metadata)
import {Inject, Injectable} from 'angular2/core';
import {Component, View} from 'angular2/core';
// Import NgClass directive
import {NgClass} from 'angular2/common';

import { InjectMetadata } from 'angular2/core';

// # Accordion Component

@Component({
  selector: 'accordion, [accordion]',

  // Modify the `host` element with a css class designator
  host: {
    'class': 'panel-group'
  }
})

// Define the view of our `Component` using one or more
// `View` annotations
@View({

  // Link to our external template file
  templateUrl: './components/accordion/accordion.html'
})

// Create and export `Component` class
export class Accordion {

  constructor() {

    this.groups = [];
  }

  // Function to register groups
  addGroup(group) {
    this.groups.push(group);
  }

  closeOthers(openGroup) {
    this.groups.forEach((group) => {
      if(group !== openGroup) {
        group.isOpen = false;
      }
    });
  }

  removeGroup(group) {
    let index = this.groups.indexOf(group);

    if(index !== -1) {
      this.groups.splice(index, 1);
    }
  }
}

これを呼び出された別のコンポーネントに渡す必要がありますが、このスタック オーバーフロー スレッドAccordionGroupの回答に従って、コンストラクターで行うように注入しようとすると、次のようになります。

// # AccordionGroup Component

// Annotate AccordionGroup class with `Component`
@Component({
  selector: 'accordion-group, [accordion-group]',
  inputs: ['heading', 'isOpen'],

  // Let Angular know about `Accordion`
  providers: [Accordion]
})

// Define the view of our `Component` using one or more
// `View` annotations
@View({

  // Link to our external template file
  templateUrl: './components/accordion/accordion-group.html',

  // Specify which directives our `Component` will utilize with
  // the `directive` property of the `View` annotation
  directives: [NgClass]
})

// Create and export `Component` class
export class AccordionGroup {

  constructor(accordion) {

    this.isOpen = false;

    this.accordion = accordion;

    this.accordion.addGroup(this);
  }

  // Angular 2 DI desugar'd
  // Reference: https://stackoverflow.com/questions/33026015/how-to-inject-angular2-http-service-into-es6-7-class
  static get parameters() {
    return [[Accordion]];
  }

  toggleOpen(event) {
    event.preventDefault();
    this.isOpen = !this.isOpen;
    this.accordion.closeOthers(this);
  }

  onDestroy() {
    this.accordion.removeGroup(this);
  }
}

使用して

static get parameters() {
  return [[Accordion]];
}

最初のコメントに記載されている修正を行った後、コンポーネントをレンダリングします。

次のいずれかを使用すると、コンポーネントがレンダリングされます。

AccordionGroup.parameters = [[Accordion]];

また

AccordionGroup.parameters = [new Inject(Accordion)];

あるいは

// Use reflect metadata as an attempt to inject appropriate
// dependency
@Reflect.metadata('parameters', [[new InjectMetadata(Accordion)]])

しかし、ES7 でパラメーター デコレーターを使用できるようになるまで、これらのうちどれを使用するのが適切な方法なのかという疑問が残ります。

余談ですが、コードの多くは、TypeScript を使用した Angular 2 のすべてを示すこの特定のチュートリアルからのものでした。Angular 2 へのディレクティブの移行

4

2 に答える 2

1

@Inject()コンストラクタ パラメータにデコレータを追加する必要があります。これは ES7 仕様ではサポートされていないため (現在の仕様では、クラス、プロパティ、およびメソッドのデコレーターのみが許可されています)、トランスパイラー用の何らかのプラグインが必要です。

Babel を使用してトランスパイルする場合は、babel-plugin-angular2-annotationsプラグインを使用してこれを許可し、コードを正しくトランスパイルできます。

import {Inject} from 'angular2/core';

export class AccordionGroup {
  constructor(@Inject(Accordion) accordion) {
    // ...
  }
}
于 2016-01-29T17:21:55.057 に答える
0

エリックがコメントで言ったことに加えて、コンストラクター@Inject内のデコレーターを見逃した可能性がありますAccordionGroup

import {Inject} from 'angular2/core';

export class AccordionGroup {
  constructor(@Inject(Accordion) accordion) {
    (...)
  }
}

お役に立てば幸いです、ティエリー

于 2016-01-29T16:35:02.493 に答える