Sự khác biệt giữa cung cấp và tiêm 'Cửa sổ' so với Cửa sổ trong Góc 8 và 9 là gì?


10

Tôi có hai dự án Angular sử dụng các phiên bản này:

  • 9.0.0-tiếp theo.6
  • 8.1.0

Trong phiên bản 9, tôi đã sử dụng điều này để cung cấp và tiêm windowobhject:

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

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

Mà hoạt động tốt.


Thực hiện phương pháp này cho phiên bản 8 đã ném các cảnh báo và lỗi trong quá trình biên dịch:

Cảnh báo: Không thể giải quyết tất cả các tham số cho TestComponent

Tôi đã giải quyết nó bằng cách sử dụng dấu ngoặc đơn, như thế này:

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

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

Sự khác biệt giữa cả hai phiên bản là gì?
Sự khác biệt trong Angular 8 và 9 gây ra điều này là gì?


Tôi hy vọng với tiền thưởng tôi có thể nhận được câu trả lời từ đó tôi và người khác có thể tìm hiểu và hiểu rõ hơn về cách các nhà cung cấpdi trong Angular và trong các phiên bản khác nhau của khung làm việc.
chụp đèn

Câu trả lời:


6

Để ứng dụng của bạn hoạt động với Kết xuất phía máy chủ, tôi khuyên bạn không chỉ sử dụng cửa sổ thông qua mã thông báo mà còn tạo mã thông báo này theo cách thân thiện với SSR mà không cần tham khảo window. Angular có DOCUMENTmã thông báo tích hợp để truy cập document. Đây là những gì tôi đã đưa ra cho các dự án của mình để sử dụng windowthông qua mã thông báo:

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

Cảm ơn bạn rất nhiều vì câu trả lời của bạn. Nó rất hữu ích và tôi sẽ sử dụng một giải pháp như thế này trong tương lai.
chụp đèn

5

Xem xét ValueProvidergiao diện:

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

Các providetài sản là loại any. Điều đó có nghĩa là bất kỳ đối tượng nào (bao gồm hàm Windowtạo) có thể đi vào bên trong nó. Đối tượng thực sự không quan trọng, chỉ có các tham chiếu quan trọng để xác định nhà cung cấp nào sẽ được sử dụng để tiêm một tham số trong hàm tạo.

Không nên coi đó là một cách thực hành tốt để sử dụng hàm tạo gốc Windowlàm mã thông báo tiêm. Nó không thành công khi biên dịch vì Windowtồn tại vào thời gian chạy trong môi trường trình duyệt, nó cũng tồn tại dưới dạng TypeScript declarenhưng trình biên dịch Angular 8 không thể phân tích mã tĩnh để tương quan giữa Windowcác nhà cung cấp và Windowtrong các tham số của hàm tạo, vì việc gán Windowđược hoàn thành bởi trình duyệt, không phải bởi mã. Không chắc tại sao nó hoạt động trong Angular 9, mặc dù ...

Bạn nên tạo mã thông báo tiêm của riêng bạn đại diện cho nhà cung cấp phụ thuộc. Mã thông báo tiêm này phải là:

  • Một chuỗi chuyên dụng (như bạn đã làm với 'Window')
  • Một sự tận tâm InjectionToken. Ví dụexport const window = new InjectionToken<Window>('window');

Ngoài ra, mã Angular phải là nền tảng bất khả tri (nên được thực thi trong trình duyệt và trên máy chủ Node.js), vì vậy sẽ tốt hơn khi sử dụng một nhà máy trả về windowhoặc undefined/ null, sau đó xử lý undefined/ nullcase trong các thành phần.


1
Cảm ơn bạn rất nhiều vì câu trả lời chi tiết của bạn. Nó đã giúp rất nhiều.
chụp đèn

1
Rất tốt! Cảm ơn. Tôi vừa kiểm tra các tài liệu Angular (v8 và v9) và tôi đã không tìm thấy một ví dụ duy nhất nơi chúng sử dụng chuỗi. :( Họ thực sự nên giải thích điều này trong các tài liệu!
Zaphoid
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.