ホームページ  >  記事  >  ウェブフロントエンド  >  Angular 開発の問題レコード: コンポーネントは @Input 入力属性を取得できません

Angular 開発の問題レコード: コンポーネントは @Input 入力属性を取得できません

青灯夜游
青灯夜游転載
2022-12-09 20:17:142703ブラウズ

最近仕事で機能を実装していたときに、小さな問題が発生しました: Angularコンポーネントは @Input 入力属性を取得できません。これらの問題については比較的よく知っていますが、次のことを見つける必要があります。これはプロセスなので、この問題を要約して記録します。

Angular 開発の問題レコード: コンポーネントは @Input 入力属性を取得できません

[関連チュートリアルの推奨事項: "angular チュートリアル"]

コンポーネント#を指定する必要があります# #入力属性を設定します@Input、コーディングするだけです。難しいことではありません。

元のコードは次のとおりです:

@Component({
	selector: 'my-menu',
	templateUrl: './main-menu.widget.html'
})
export class MyMenuWidget {
  data: any[];
  
  ...

    constructor(...) {
       this._changesSubscription = this._service.changes.pipe(
            map((data: any[]) => {
                    ...
                    return data;
            })
        ).subscribe((data: any[]) => {
            this.data = data;
        });
    }

  ...
}

入力属性を追加します:

@Component({
	selector: 'my-menu',
	templateUrl: './main-menu.widget.html'
})
export class MyMenuWidget {
  @Input() isMainMenu: boolean = false;

  data: any[];
  
  ...

    constructor(...) {
        this._changesSubscription = this._service.changes.pipe(
                map((data: any[]) => {
                        ...
                        return data;
                })
        ).subscribe((data: any[]) => {
            if (this.isMainMenu) {
               this.data = data.filter((d: any) => d.ID === 233);
            }
            else {
              this.data = data;
            }
        });
    }

  ...
}

使用してください:

<my-menu [isMainMenu]="mainMenu"></my-menu>

その後、

MyMenuWidget の入力属性 isMainMenu が値を取得できないことがわかりました。スペルに何か問題がありますか?調べてみると特に問題はなかったのですが、値が取得できませんでした。

よく見てください、ああああ? ? ?

Observable へのサブスクリプションは、実際にはコンストラクターに書き込まれます。 ! !この方法で記述すると、一部のシナリオでは正常に動作し、コードの機能には影響しませんが、この書き方は非常に不規則であり、上記の例のコードと同様の問題が発生します。したがって、通常の開発ではこのように書くことはお勧めできません。

コードをアップロードします。

@Component({
	selector: &#39;my-menu&#39;,
	templateUrl: &#39;./main-menu.widget.html&#39;
})
export class MyMenuWidget {
  @Input() isMainMenu: boolean = false;

  data: any[];
  
  ...
  
  constructor(...) {
     ...
  }
  
    ngOnInit() {
        this._changesSubscription = this._service.changes.pipe(
            map((data: any[]) => {
                ...
                return data;
            })
        ).subscribe((data: any[]) => {
            if (this.isMainMenu) {
                    this.data = data.filter((d: any) => d.ID === 233);
            }
            else {
                this.data = data;
            }
        });
    }

  ...
}

そこで問題は、なぜ同じコードを

ngOnInit に配置しても正常に動作するのかということです。コンストラクターではなく、ngOnInit に入れるべきだと言う人もいるでしょう。では、なぜそうではないのかを解明する必要があります。

問題は、Angular コンストラクターと ngOnInit 関数の違いは何でしょうか?

違い 1

言語の違い:

まず、言語の観点から両者の違いを見てみましょう。

ngOnInit はコンポーネント クラスのメソッドにすぎません。特定の名前が付いていることを除けば、その構造はクラスの他のメソッドと変わりません。

export class MyMenuWidget implements OnInit { 
   ngOnInit() {}
}

実装してもしなくても、このままでも全然問題なく書けます。このインターフェイスを実装するために明示的なマークアップは必要ありません。

export class MyMenuWidget {
   ngOnInit() {}
}

これは ES6 の書き方です。ES5 で上記のコードを書くにはどうすればよいですか?

コンストラクタはそれとは全く異なり、クラスのインスタンス作成時に呼び出されます。

export class MyMenuWidget {
   constructor(){}
  
   ngOnInit() {}
}

違い 2

コンポーネント初期化プロセスの違い:

コンポーネントの初期化の観点から見ると、この 2 つの違いは依然として非常に大きいです。 Angular の起動プロセスには 2 つの主な段階があります:


1. コンポーネント ツリーの構築; 2. 変更検出の実行;

Angular がコンポーネント ツリーを構築するときは、コンポーネント インスタンスを作成する必要があります。まず、コンストラクター new が呼び出されてインスタンスが作成され、これによりコンポーネント クラスのコンストラクターが呼び出されます。 ngOnInit を含むすべてのライフサイクル フックは、変更検出フェーズの一部として呼び出されます。

Angular が変更検出を開始すると、コンポーネント ツリーが構築され、ツリー内のすべてのコンポーネントのコンストラクターが呼び出されます。さらに、各コンポーネントのテンプレート ノードがこの時点で DOM に追加されます。ここでは、コンポーネントの初期化に必要なすべてのデータ (DI プロバイダー、DOM など) にアクセスできます。 @Input 通信メカニズムは変更検出フェーズの一部として処理されるため、コンストラクターでは @Input を使用できません。

export class MyMenuWidget {
   constructor(private _elementRef: ElementRef){
     ...
   }
  
   ngOnInit() {}
}

違い 3

機能上の違い:

Angular

コンストラクター の場合、主に初期化と依存関係の注入に使用されます。通常のアプローチは、コンストラクターにできるだけ少ないロジックを入れることですが、場合によっては、多くのロジックを入れても、機能に影響を与えないことがあります。

ngOnInit の場合、Angular はコンポーネントの DOM を作成し、コンストラクターを使用して必要な依存関係をすべて注入し、初期化の完了後に ngOnInit を呼び出します。これは、コンポーネントの初期化ロジックを実行するのに適した場所です。 。

簡単に言えば、

、constructorコンストラクター自体は Angular とは何の関係もありません。ngOnInitこれらのフック関数は Angular で定義されています。

概要

@Input がコンストラクターで値を取得できない理由は明らかでしょうか。将来的には、どのロジックをコンストラクターに配置する必要があり、どのロジックを ngOnInit に配置する必要があるかが明確になるでしょう。

プログラミング関連の知識について詳しくは、

プログラミング教育をご覧ください。 !

以上がAngular 開発の問題レコード: コンポーネントは @Input 入力属性を取得できませんの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。