programing

서비스에 윈도우를 삽입하는 방법

iphone6s 2023. 3. 28. 21:20
반응형

서비스에 윈도우를 삽입하는 방법

localstorage하고 싶습니다.window1.x Angular 1.x와 같은 않기 를 내 시킵니다.$window.

그걸 어떻게 하는 거죠?

이 기능은 현재(2018-03, angular 5.2 with AoT, 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어플리케이션에서 이들을 사용하는 경우에도 동일한 방법으로 본 서비스에 대한 기타 글로벌한 정보를 제공합니다.


: with question . edit : Truchainz edit edit edit edit :2.1 edit2: 2 2.1.2 : Added notes AoT edit4 : 추가 any편집하다을 다른 때하도록 업데이트된 6:예: Window 을 합니다.

주입된 문서에서 창을 얻을 수 있습니다.

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

export class MyClass {

  private window: Window;

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

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

}

창에 사용자 지정 속성이 있는 경우 사용자 지정 인터페이스를 사용할 수 있습니다.

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

export interface CustomWindow extends Window {
  $: JQuery
  customProperty: boolean;
}

export class MyClass {

  private window: CustomWindow;

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

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

}

각도 2.0.0-rc.5 NgModule의 출시와 함께 도입되었다.이전 솔루션이 작동하지 않게 되었습니다.이 문제를 해결하기 위해 제가 한 일은 다음과 같습니다.

app.context.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) {}
}

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

편집:

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
}

.1하려면 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 I provide it like this이렇게 제공합니다.

{ provide: 'Window', useValue: window }

Here's another solution I came up recently after I got tired of getting 여기 또 다른 해결책이 있습니다. 제가 최근에 생각해낸 것은defaultView부에서DOCUMENT토큰과 Null을 확인하고 Null을 확인합니다.내장 토큰을 사용하여 null을 확인합니다.

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

주의: 저는 이 토큰을 다른 많은 글로벌오브젝트액세서들과 함께 https://github.com/ng-web-apis/common에서 이용할 수 있는 작은 라이브러리로 출시하였습니다.

기타 Angular용 네이티브 API 라이브러리는 https://github.com/ng-web-apis에서 확인하실 수 있습니다.

@Component 선언 전에 이 작업을 수행할 수도 있습니다.

declare var window: any;

컴파일러는 타입 any로 상정된 글로벌 변수로 선언하기 때문에 실제로 글로벌 창 변수에 액세스할 수 있도록 합니다.

어플리케이션 내 어디에서나 윈도우에 접속하는 것은 권장하지 않습니다.필요한 윈도우 속성에 액세스/변경하는 서비스(및 이러한 서비스를 컴포넌트에 삽입하는 것)를 작성하여 윈도우 오브젝트 전체를 변경하지 않고 윈도우에서 수행할 수 있는 작업의 범위를 좁혀야 합니다.

Angular RC4에서는 위의 답변 중 몇 가지를 조합한 다음 작업이 루트 앱에서 실행됩니다.ts는 프로바이더를 추가합니다.

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

그런 다음 서비스 등에서 컨스트럭터에 주입합니다.

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

'Window' 문자열에 OpaqueToken을 사용했습니다.

import {unimplemented} from '@angular/core/src/facade/exceptions';
import {OpaqueToken, Provider} from '@angular/core/index';

function _window(): any {
    return window;
}

export const WINDOW: OpaqueToken = new OpaqueToken('WindowToken');

export abstract class WindowRef {
    get nativeWindow(): any {
        return unimplemented();
    }
}

export class BrowserWindowRef extends WindowRef {
    constructor() {
        super();
    }
    get nativeWindow(): any {
        return _window();
    }
}


export const WINDOW_PROVIDERS = [
    new Provider(WindowRef, { useClass: BrowserWindowRef }),
    new Provider(WINDOW, { useFactory: _window, deps: [] }),
];

그리고 가져오기 용 가져오기 됩 니)를 가져오기 위해 사용되었다.WINDOW_PROVIDERS각 2.0-RC-4.0-RC-4로 부팅에 부팅됩니다.부트스트랩에 포함되어 있습니다.

그러나 Angular 2.0.0-rc.5 릴리스에서는 별도의 모듈을 작성해야 합니다.

import { NgModule } from '@angular/core';
import { WINDOW_PROVIDERS } from './window';

@NgModule({
    providers: [WINDOW_PROVIDERS]
})
export class WindowModule { }

되어 있습니다.app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { WindowModule } from './other/window.module';

import { AppComponent } from './app.component';

@NgModule({
    imports: [ BrowserModule, WindowModule ],
    declarations: [ ... ],
    providers: [ ... ],
    bootstrap: [ AppComponent ]
})
export class AppModule {}

Angular 4 주입 도입토큰, 그리고 DOCUMENT라는 문서용 토큰도 만들어요. 이게 정식 솔루션이고 AoT에서 작동하는 것 같아요.

같은 논리를 사용하여 ngx-window-token이라는 작은 라이브러리를 생성하여 이 작업을 반복하지 않도록 합니다.

다른 프로젝트에서 사용하고 있으며, 문제없이 AoT를 내장하고 있습니다.

다른 패키지에서 사용한 방법은 다음과 같습니다.

여기 플런커가 있습니다.

모듈 내

imports: [ BrowserModule, WindowTokenModule ]

constructor(@Inject(WINDOW) _window) { }

해도 충분하다

export class AppWindow extends Window {} 

하고 있다

{ provide: 'AppWindow', useValue: window } 

AOT를 기쁘게 하다

오늘(2016년 4월)부터는 이전 솔루션에서 코드가 작동하지 않아 App.ts에 직접 창을 삽입한 후 앱에서 글로벌 접속을 위한 서비스에 필요한 값을 모을 수 있다고 생각합니다만, 만약 독자적으로 서비스를 만들어 삽입하는 것을 선호한다면, 이것이 보다 간단한 방법입니다.

https://gist.github.com/WilldelaVega777/9afcbd6cc661f4107c2b74dd6090cebf

//--------------------------------------------------------------------------------------------------
// Imports Section:
//--------------------------------------------------------------------------------------------------
import {Injectable} from 'angular2/core'
import {window} from 'angular2/src/facade/browser';

//--------------------------------------------------------------------------------------------------
// Service Class:
//--------------------------------------------------------------------------------------------------
@Injectable()
export class WindowService
{
    //----------------------------------------------------------------------------------------------
    // Constructor Method Section:
    //----------------------------------------------------------------------------------------------
    constructor(){}

    //----------------------------------------------------------------------------------------------
    // Public Properties Section:
    //----------------------------------------------------------------------------------------------
    get nativeWindow() : Window
    {
        return window;
    }
}

문서를 통해 창의 개체에 직접 액세스할 수 있습니다.

document.defaultView == window

윈도 오브젝트를 컴포넌트에 삽입하는 방법이 문제라는 것은 알고 있습니다만, localStorage에 접속하기 위해서만 이 작업을 하고 있는 것 같습니다.정말로 localStorage만 원한다면 h5webstorage와 같이 그것만 제공하는 서비스를 사용해 보십시오.그런 다음 컴포넌트가 실제 종속성을 설명하여 코드를 더 잘 읽을 수 있도록 합니다.

이것은 Angular 4 AOT와 함께 작업한 결과 중 가장 짧고 깨끗한 답변입니다.

출처 : https://github.com/angular/angular/issues/12631#issuecomment-274260009

@Injectable()
export class WindowWrapper extends Window {}

export function getWindow() { return window; }

@NgModule({
  ...
  providers: [
    {provide: WindowWrapper, useFactory: getWindow}
  ]
  ...
})
export class AppModule {
  constructor(w: WindowWrapper) {
    console.log(w);
  }
}

Angular 4에서는 NgZone을 사용할 수 있습니다.

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

constructor(private zone: NgZone) {}

print() {
    this.zone.runOutsideAngular(() => window.print());
}

또, 이 마크를 붙이는 것도 좋은 방법입니다.DOCUMENT옵션입니다.Angular 문서별:

응용프로그램 컨텍스트와 렌더링 컨텍스트가 같지 않은 경우(예: 응용프로그램을 웹 워커로 실행하는 경우) 문서를 응용프로그램 컨텍스트에서 사용하지 못할 수 있습니다.

다음 예시는 다음 예시를 제시하겠습니다.DOCUMENT브라우저가 SVG를 지원하는지 여부를 확인합니다.

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

...

constructor(@Optional() @Inject(DOCUMENT) document: Document) {
   this.supportsSvg = !!(
   document &&
   document.createElementNS &&
   document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect
);

모듈에 공급자를 선언합니다.

  providers: [
    { provide: Window, useValue: window }
  ]

컴포넌트 또는 서비스에 다음을 주입합니다.

constructor(private window: Window)

속성에 액세스할 수 있습니다.

console.log(this.window.document);

또는 새 값을 만듭니다.

(<any>this.window).MyNewValue = 'John Doe' ;

@maxisam ngx-contractions 감사합니다.나도 비슷한 걸 하다가 네 걸로 바꿨어.윈도 크기 변경 이벤트를 듣고 가입자에게 통지하는 서비스입니다.

import { Inject, Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import { WINDOW } from 'ngx-window-token';


export interface WindowSize {
    readonly width: number;
    readonly height: number;
}

@Injectable()
export class WindowSizeService {

    constructor( @Inject(WINDOW) private _window: any ) {
        Observable.fromEvent(_window, 'resize')
        .auditTime(100)
        .map(event => <WindowSize>{width: event['currentTarget'].innerWidth, height: event['currentTarget'].innerHeight})
        .subscribe((windowSize) => {
            this.windowSizeChanged$.next(windowSize);
        });
    }

    readonly windowSizeChanged$ = new BehaviorSubject<WindowSize>(<WindowSize>{width: this._window.innerWidth, height: this._window.innerHeight});
}

짧고 달콤하며 매력적으로 작용합니다.

"창"에 속하는 속성이 정말로 필요하기 때문에 창을 삽입해야 하는 경우 다음과 같이 서비스를 생성하십시오.

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

@Injectable({
  providedIn: 'root',
})
export class WindowService {
  public getInstance(): Window {
    return window;
  }
}

여기 조롱하기 쉬운 예가 있습니다.WindowService테스트용:

export class AnotherService {
  constructor(private windowService: WindowService) {}

  public hasPreviousPage(): boolean {
    return this.windowService.getInstance().history.length > 2;
  }
}

그러나 창을 사용하여 글로벌하게 정의된 변수를 얻는다면 먼저 글로벌을 사용하는 것이 좋습니다.대신 이거.다음으로 글로벌 입력은 타이프 스크립트모듈의 문제입니다.요컨대 다음과 같은 작업을 수행합니다.

이 주변 컨텍스트를 어딘가에 선언합니다.

declare global {
  function hello():string;
}

그러면 ts는 다음 코드에 대해 불평하지 않습니다.

globalThis.hello(); // best way
window.hello(); // okay but window could be undefined in tests, workers or headless nodejs

이 경우에도 실장을 추가해야 합니다.hello()세계 어디론가.

물론 다음과 같은 더러운 속임수를 사용할 수도 있습니다(단, 권장하지 않습니다).

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

interface ExtraParams {
hello:() => string;
}

@Injectable({
  providedIn: 'root',
})
export class WindowService {
  public getInstance(): Window & ExtraParams {
    return window as unknown as Window & ExtraParams;
  }
}

응용 프로그램 전체에서 글로벌 변수에 액세스할 수 있는 경우 DI(Dependency Injection)를 통해 창 개체를 가져오는 것은 좋은 생각이 아닙니다.

그러나 윈도우 오브젝트를 사용하지 않으려면self키워드를 지정합니다.

여러분, 심플하게 하세요!

export class HeroesComponent implements OnInit {
  heroes: Hero[];
  window = window;
}

<div>{{window.Object.entries({ foo: 1 }) | json}}</div>

여기 윈도우 오브젝트에 접속하는 것은 매우 간단합니다.기본적인 컴포넌트로 동작 테스트를 했습니다.

import { Component, OnInit,Inject } from '@angular/core';
import {DOCUMENT} from '@angular/platform-browser';

@Component({
  selector: 'app-verticalbanners',
  templateUrl: './verticalbanners.component.html',
  styleUrls: ['./verticalbanners.component.css']
})
export class VerticalbannersComponent implements OnInit {

  constructor(){ }

  ngOnInit() {
    console.log(window.innerHeight );
  }

}

언급URL : https://stackoverflow.com/questions/34177221/how-to-inject-window-into-a-service

반응형