web-dev-qa-db-ja.com

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

私は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の違いは何ですか?

10
lampshade

アプリがサーバー側レンダリングで機能するためには、ウィンドウスルートークンを使用するだけでなく、windowをまったく参照せずに、SSRフレンドリーな方法でこのトークンを作成することをお勧めします。 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;
        },
    },
);
6
waterplea

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はブラウザー環境で実行時に存在し、TypeScript declareとしても存在するため、コンパイル時に失敗しますが、Angular 8コンパイラーは静的に実行できませんプロバイダーのWindowとコンストラクターのパラメーターのWindowを関連付けるコード分析。Windowの割り当ては、コードではなくブラウザーによって行われるためです。 Angular 9で動作する理由...

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

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

さらに、Angularコードはプラットフォームに依存しない(ブラウザとNode.jsサーバーでも実行可能である必要があります)必要があるため、windowまたはundefined/nullし、コンポーネントのundefined/nullケースを処理します。

5
Guerric P