Saya memiliki dua proyek Angular menggunakan versi ini:
- 9.0.0-next.6
- 8.1.0
Dalam versi 9 saya menggunakan ini untuk menyediakan dan menyuntikkan window
objek:
@NgModule({
providers: [
{
provide: Window,
useValue: window
},
]
})
export class TestComponent implements OnInit {
constructor(@Inject(Window) private window: Window)
}
Itu bekerja dengan baik.
Mengambil pendekatan ini untuk versi 8 melemparkan peringatan dan kesalahan selama kompilasi:
Peringatan: Tidak dapat menyelesaikan semua parameter untuk TestComponent ...
Saya menyelesaikannya dengan menggunakan tanda kutip tunggal, seperti ini:
@NgModule({
providers: [
{
provide: 'Window',
useValue: window
},
]
})
export class TestComponent implements OnInit {
constructor(@Inject('Window') private window: Window)
}
Apa perbedaan antara kedua versi?
Apa perbedaan dalam Angular 8 dan 9 yang menyebabkan hal ini?
Jawaban:
Agar aplikasi Anda berfungsi dengan Server Side Rendering, saya sarankan Anda tidak hanya menggunakan jendela melalui token, tetapi juga membuat token ini dengan cara yang ramah SSR, tanpa referensi
window
sama sekali. Angular memilikiDOCUMENT
token bawaan untuk mengaksesdocument
. Inilah yang saya buat untuk proyek saya untuk digunakanwindow
melalui token:sumber
Mempertimbangkan
ValueProvider
antarmuka:The
provide
properti adalah tipeany
. Itu berarti benda apa pun (termasukWindow
konstruktor) dapat masuk ke dalamnya. Objek sebenarnya tidak masalah, hanya referensi masalah untuk mengidentifikasi penyedia mana yang harus digunakan untuk menyuntikkan parameter dalam konstruktor.Seharusnya tidak dianggap sebagai praktik yang baik untuk menggunakan
Window
konstruktor asli sebagai token injeksi. Gagal pada waktu kompilasi karenaWindow
ada pada saat dijalankan dalam lingkungan browser, ia juga ada sebagai TypeScriptdeclare
tetapi kompiler Angular 8 tidak dapat melakukan analisis kode statis untuk mengkorelasikanWindow
dalam penyedia danWindow
dalam parameter konstruktor, karena penugasan dariWindow
dilakukan oleh browser, bukan oleh kode. Tidak yakin mengapa ini bekerja di Angular 9, ...Anda harus membuat token injeksi Anda sendiri yang mewakili penyedia ketergantungan. Token injeksi ini harus berupa:
'Window'
)InjectionToken
. Sebagai contohexport const window = new InjectionToken<Window>('window');
Selain itu, kode Angular harus platform agnostik (harus dapat dieksekusi di browser dan pada server Node.js juga) sehingga akan lebih baik menggunakan pabrik yang mengembalikan
window
atauundefined
/null
, kemudian menanganiundefined
/null
case dalam komponen.sumber