Qual è la differenza tra fornire e iniettare 'Window' vs Window in Angular 8 e 9?


10

Ho due progetti angolari che usano queste versioni:

  • 9.0.0-next.6
  • 8.1.0

Nella versione 9 l'ho usato per fornire e iniettare l' windowoggetto:

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

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

Che funziona benissimo.


Adottare questo approccio alla versione 8 ha generato avvisi ed errori durante la compilazione:

Avvertenza: impossibile risolvere tutti i parametri per TestComponent ...

L'ho risolto usando virgolette singole, in questo modo:

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

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

Qual è la differenza tra entrambe le versioni?
Qual è la differenza in Angular 8 e 9 che causa questa cosa?


Spero con la generosità di poter ottenere una risposta dalla quale io e gli altri possiamo imparare e capire meglio come funzionano i provider e i di Angular e nelle diverse versioni del framework.
paralume

Risposte:


6

Affinché la tua app funzioni con Server Side Rendering, ti suggerisco non solo di utilizzare il token finestra attraverso, ma anche di creare questo token in modo SSR, senza fare alcun riferimento window. Angular ha un DOCUMENTtoken integrato per l'accesso document. Ecco cosa mi è venuto in mente per i miei progetti da utilizzare windowattraverso i token:

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;
        },
    },
);

Grazie mille per la tua risposta. È molto utile e userò una soluzione come questa in futuro.
paralume

5

Considerando l' ValueProviderinterfaccia:

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;
}

La provideproprietà è di tipo any. Ciò significa che qualsiasi oggetto (incluso il Windowcostruttore) può andare al suo interno. L'oggetto in realtà non importa, solo il riferimento è importante per identificare quale provider dovrebbe essere usato per iniettare un parametro in un costruttore.

Non dovrebbe essere considerato una buona pratica utilizzare il Windowcostruttore nativo come token di iniezione. Non riesce in fase di compilazione perché Windowesiste in fase di esecuzione in un ambiente browser, esiste anche come TypeScript declarema il compilatore Angular 8 non può eseguire analisi di codice statico per correlare i parametri Windownei provider e Windownei parametri di un costruttore, poiché l'assegnazione di Windowviene eseguita dal browser, non dal codice. Non so perché funzioni in Angular 9, sebbene ...

È necessario creare il proprio token di iniezione che rappresenta il provider di dipendenze. Questo token di iniezione dovrebbe essere:

  • Una stringa dedicata (come hai fatto con 'Window')
  • Un dedicato InjectionToken. Per esempioexport const window = new InjectionToken<Window>('window');

Inoltre, il codice angolare dovrebbe essere indipendente dalla piattaforma (dovrebbe essere eseguibile in un browser e anche su un server Node.js), quindi sarebbe meglio usare una factory che ritorna windowo undefined/ null, quindi gestire il caso undefined/ nullnei componenti.


1
Grazie mille per la risposta dettagliata. Mi ha aiutato molto.
Paralume

1
Molto bene! Grazie. Ho appena controllato i documenti angolari (v8 e v9) e non ho trovato un singolo esempio in cui usano le stringhe. :( Dovrebbero davvero spiegarlo nei documenti!
Zaphoid,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.