Angular 8と9で「ウィンドウ」とウィンドウの提供と注入の違いは何ですか?


10

これらのバージョンを使用する2つのAngularプロジェクトがあります。

  • 9.0.0-next.6
  • 8.1.0

バージョン9では、これを使用してwindowオブジェクトを提供および注入しました。

@NgModule({
  providers: [
    {
      provide: Window,
      useValue: window
    },
  ]
})

export class TestComponent implements OnInit {
  constructor(@Inject(Window) private window: Window)
}

それはうまくいきます。


このアプローチをバージョン8に適用すると、コンパイル中に警告とエラーがスローされました。

警告:TestComponentのすべてのパラメーターを解決できません…

私はこのように単一引用符を使用してそれを解決しました:

@NgModule({
  providers: [
    {
      provide: 'Window',
      useValue: window
    },
  ]
})

export class TestComponent implements OnInit {
  constructor(@Inject('Window') private window: Window)
}

両方のバージョンの違いは何ですか?
これを引き起こすAngular 8と9の違いは何ですか?


賞金があれば、私や他の人がAngularや異なるバージョンのフレームワークでプロバイダーdiがどのように機能するかをよりよく学び、理解できる答えが得られることを願っています。
ランプシェード

回答:


6

アプリがサーバー側レンダリングで動作するためには、ウィンドウスルートークンを使用するだけでなく、このトークンを参照せずにSSRフレンドリーな方法で作成することをお勧めしますwindow。AngularにはDOCUMENT、にアクセスするための組み込みのトークンがありますdocument。プロジェクトがwindowトークンを介して使用するために私が思いついたものは次のとおりです。

import {DOCUMENT} from '@angular/common';
import {inject, InjectionToken} from '@angular/core';

export const WINDOW = new InjectionToken<Window>(
    'An abstraction over global window object',
    {
        factory: () => {
            const {defaultView} = inject(DOCUMENT);

            if (!defaultView) {
                throw new Error('Window is not available');
            }

            return defaultView;
        },
    },
);

ご回答どうもありがとうございました。これは非常に役に立ち、将来的にはこのようなソリューションを使用する予定です。
ランプシェード

5

ValueProviderインターフェースを考慮する:

export declare interface ValueProvider extends ValueSansProvider {
    /**
     * An injection token. Typically an instance of `Type` or `InjectionToken`, but can be `any`.
     */
    provide: any;
    /**
     * When true, injector returns an array of instances. This is useful to allow multiple
     * providers spread across many files to provide configuration information to a common token.
     */
    multi?: boolean;
}

provideプロパティは型ですany。つまり、任意のオブジェクト(Windowコンストラクターを含む)がその中に入ることができます。オブジェクトは実際には関係ありません。コンストラクターにパラメーターを挿入するためにどのプロバイダーを使用する必要があるかを特定するには、参照のみが関係します。

ネイティブWindowコンストラクターをインジェクショントークンとして使用することをお勧めしません。ので、それはコンパイル時に失敗したWindowブラウザ環境で実行時に存在して活字体として、それがまた存在するdeclareが、角度8コンパイラが相関する静的コード解析を行うことができないWindowのプロバイダとにWindow、コンストラクタのパラメータでの割り当てがあるため、Window行われていますコードではなくブラウザによって。なぜAngular 9で機能するのかわからない...

依存関係プロバイダーを表す独自の注入トークンを作成する必要があります。この注入トークンは次のいずれかです。

  • 専用の文字列(で行ったような'Window'
  • 専用InjectionToken。例えばexport const window = new InjectionToken<Window>('window');

さらに、Angularコードはプラットフォームにとらわれない(ブラウザとNode.jsサーバーでも実行可能である必要がある)必要があるため、windowor undefined/ を返すファクトリを使用してから、コンポーネント内の/ ケースをnull処理することをお勧めします。undefinednull


1
細かいご回答ありがとうございます。それは大いに役立ちました。
ランプシェード

1
とても良い!ありがとう。Angularのドキュメント(v8とv9)を確認したところ、文字列を使用する例が1つも見つかりませんでした。:(彼らは本当にこれをドキュメントで説明するべきです!
Zaphoid
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.