[angular] 서비스에 창을 삽입하는 방법은 무엇입니까?

TypeScript에서 localstorage. windowAngular 1.x와 같은 전역 변수를 참조하고 싶지 않기 때문에 브라우저 개체에 대한 참조를 내 서비스 에 삽입하고 싶습니다 $window.

어떻게하나요?



답변

이것은 현재 나를 위해 일하고 있습니다 (2018-03, AoT가있는 angular 5.2, angular-cli 및 사용자 정의 웹 팩 빌드에서 테스트 됨).

먼저 창에 대한 참조를 제공하는 주입 가능한 서비스를 만듭니다.

import { Injectable } from '@angular/core';

// This interface is optional, showing how you can add strong typings for custom globals.
// Just use "Window" as the type if you don't have custom global stuff
export interface ICustomWindow extends Window {
    __custom_global_stuff: string;
}

function getWindow (): any {
    return window;
}

@Injectable()
export class WindowRefService {
    get nativeWindow (): ICustomWindow {
        return getWindow();
    }
}

이제 해당 서비스를 루트 AppModule에 등록하여 모든 곳에 삽입 할 수 있습니다.

import { WindowRefService } from './window-ref.service';

@NgModule({
  providers: [
    WindowRefService
  ],
  ...
})
export class AppModule {}

그런 다음 나중에 주입해야 할 부분 window:

import { Component} from '@angular/core';
import { WindowRefService, ICustomWindow } from './window-ref.service';

@Component({ ... })
export default class MyCoolComponent {
    private _window: ICustomWindow;

    constructor (
        windowRef: WindowRefService
    ) {
        this._window = windowRef.nativeWindow;
    }

    public doThing (): void {
        let foo = this._window.XMLHttpRequest;
        let bar = this._window.__custom_global_stuff;
    }
...

nativeDocument응용 프로그램에서 사용하는 경우 유사한 방식으로이 서비스에 및 기타 전역 을 추가 할 수도 있습니다 .


편집 : Truchainz 제안으로 업데이트되었습니다. edit2 : angular 2.1.2에 대해 업데이트 됨 edit3 : AoT 노트 추가 edit4 : any유형 해결 방법 note edit5 : 다른 빌드로 이전 솔루션을 사용할 때 발생하던 오류를 수정하는 WindowRefService를 사용하도록 업데이트 된 솔루션 edit6 : 예제 사용자 지정 창 타이핑 추가


답변

angular 2.0.0-rc.5의 출시와 함께 NgModule이 도입되었습니다. 이전 솔루션이 작동을 멈췄습니다. 이것은 내가 그것을 고치기 위해 한 일입니다.

app.module.ts :

@NgModule({
  providers: [
    { provide: 'Window',  useValue: window }
  ],
  declarations: [...],
  imports: [...]
})
export class AppModule {}

일부 구성 요소에서 :

import { Component, Inject } from '@angular/core';

@Component({...})
export class MyComponent {
    constructor (@Inject('Window') window: Window) {}
}

OpaqueToken을 사용할 수도 있습니다.문자열 ‘Window’대신

편집하다:

AppModule은 다음과 같이 main.ts에서 애플리케이션을 부트 스트랩하는 데 사용됩니다.

import { platformBrowserDynamic  } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule)

NgModule에 대한 자세한 내용은 Angular 2 설명서를 참조하십시오 . https://angular.io/docs/ts/latest/guide/ngmodule.html


답변

제공자를 설정 한 후에 주입 할 수 있습니다.

import {provide} from 'angular2/core';
bootstrap(..., [provide(Window, {useValue: window})]);

constructor(private window: Window) {
    // this.window
}


답변

삽입 된 문서에서 창을 가져올 수 있습니다.

import { Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

export class MyClass {

  constructor(@Inject(DOCUMENT) private document: Document) {
     this.window = this.document.defaultView;
  }

  check() {
    console.log(this.document);
    console.log(this.window);
  }

}


답변

Angular 2.1.1에서 작동하려면 @Inject문자열을 사용하여 창을 만들어야했습니다.

  constructor( @Inject('Window') private window: Window) { }

다음과 같이 조롱

beforeEach(() => {
  let windowMock: Window = <any>{ };
  TestBed.configureTestingModule({
    providers: [
      ApiUriService,
      { provide: 'Window', useFactory: (() => { return windowMock; }) }
    ]
  });

보통 @NgModule이렇게 제공합니다

{ provide: 'Window', useValue: window }


답변

Angular RC4에서는 위의 답변 중 일부가 결합 된 다음 작업이 루트 app.ts에서 공급자를 추가합니다.

@Component({
    templateUrl: 'build/app.html',
    providers: [
        anotherProvider,
        { provide: Window, useValue: window }
    ]
})

그런 다음 서비스 등에서 생성자에 삽입하십시오.

constructor(
      @Inject(Window) private _window: Window,
)


답변

@Component 선언 전에도 그렇게 할 수 있습니다.

declare var window: any;

컴파일러는 실제로 전역 창 변수에 액세스 할 수 있도록합니다. 이는 any 유형의 가정 된 전역 변수로 선언하기 때문입니다.

응용 프로그램의 모든 곳에서 창에 액세스하는 것은 권장하지 않습니다. 필요한 창 속성에 액세스 / 수정하는 서비스를 만들고 구성 요소에 해당 서비스를 삽입하여 창으로 할 수있는 작업을 수정하지 않고 범위를 지정해야합니다. 전체 창 개체.