서비스에 윈도우를 삽입하는 방법
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
'programing' 카테고리의 다른 글
| 어디서든 Angular UI 모드를 닫는 방법 (0) | 2023.03.28 |
|---|---|
| jq를 사용하여 json의 여러 필드를 순차적으로 구문 분석 및 표시 (0) | 2023.03.28 |
| 파일에서 ESLint react/prop-type 규칙을 비활성화하려면 어떻게 해야 합니까? (0) | 2023.03.28 |
| AngularJS: 렌더링 후 콜백(렌더 후 DOM으로 작업) (0) | 2023.03.28 |
| C++ 클래스의 JSON으로의 변환 (0) | 2023.03.28 |