Угловая 4 $ window альтернатива [дубликат]

next в значительной степени просто вызывает __next__() в этом случае. Вызов __next__ на вашем объекте запустит генератор и вернет его (в этот момент в магии не делается).


В этом случае вы можете быть в состоянии избегайте вообще не определять __next__:

class MyString:
    def __init__(self,s):
        self.s=s

    def __iter__(self):
        for i in range(len(self.s)):
            yield(self.s[i])
        # Or...
        # for item in self.s:
        #     yield item

Если вы хотели использовать __iter__ и __next__ (чтобы определить итератор , а не просто сделать iterable ), вы, вероятно, захотите сделать что-то вроде этого:

class MyString:
    def __init__(self,s):
        self.s = s
        self._ix = None

    def __iter__(self):
        return self

    def __next__(self):
        if self._ix is None:
            self._ix = 0

        try:
            item = self.s[self._ix]
        except IndexError:
            # Possibly reset `self._ix`?
            raise StopIteration
        self._ix += 1
        return item

86
задан lokanx 9 December 2015 в 13:43
поделиться

19 ответов

Это работает для меня в настоящее время (2018-03, угловой 5.2 с AoT, проверено в angular-cli и пользовательской сборке webpack):

Сначала создайте инъекционную службу, которая предоставляет ссылку на окно :

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 и другие глобалы к этой службе аналогичным образом, если вы используете их в своем приложении.


edit: Обновлено с предложением Truchainz. edit2: Обновлено для углового 2.1.2 edit3: Добавлены примечания AoT edit4: Добавление обходного примечания типа any edit5: Обновленное решение для использования WindowRefService, которое исправляет ошибку, которую я получал при использовании предыдущего решения с другим редактором edit6: добавление примера custom Ввод текста

109
ответ дан elwyn 19 August 2018 в 04:50
поделиться
  • 1
    Наличие параметра @Inject в параметрах конструктора бросило кучу ошибок для меня, таких как ORIGINAL EXCEPTION: No provider for Window!. Однако удаление этого исправлено для меня. Для меня было достаточно всего лишь первых двух глобальных линий. – Truchainz 16 June 2016 в 23:29
  • 2
    Интересно ^^ Мне придется попробовать его еще в нескольких демонстрационных проектах - без @Inject я получал ошибки No provider for Window. Это довольно хорошо, не нужно руководство @Inject! – elwyn 17 June 2016 в 01:57
  • 3
    В 2.1.2 мне пришлось использовать @Inject(Window) для этого – James Kleeh 15 November 2016 в 17:55
  • 4
    [Д0] angular.io/docs/ts/latest/guide/… . О, мой плохой, не читал внимательно – Dummy 26 December 2016 в 23:19
  • 5
    @Brian да, он по-прежнему обращается к window, но при обслуживании между ними он позволяет заглушить собственный материал window в модульных тестах, и, как вы упомянули для SSR, может быть предоставлена ​​альтернативная услуга, которая предоставляет окно mock / noop для сервер. Причина, по которой я упоминаю AOT, - это несколько ранних решений для обертывания окна в AOT, когда Angular обновлен. – elwyn 10 January 2018 в 19:55

@maxisam спасибо за ngx-window-token . Я делал что-то подобное, но переключился на твое. Это моя служба для прослушивания событий изменения размера окна и уведомления абонентов.

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

Короткая и сладкая и работает как очарование.

0
ответ дан Andrew Alderson 19 August 2018 в 04:50
поделиться

Я использовал OpaqueToken для строки «Window»:

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 в bootstrap в Angular 2.0.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 { }

и только что определен в свойстве import моего основного 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 {}
8
ответ дан Chyngyz 19 August 2018 в 04:50
поделиться
  • 1
    есть ли причина, почему команда angular2 не реализовала ее? – Zamboney 15 August 2016 в 09:26
  • 2
    так как угловые окончательные фасады не работают ... (1,29): ошибка TS2307: Не удается найти модуль «@ угловой / ядро ​​/ src / фасад / исключения». – DS_web_developer 20 September 2016 в 10:27
  • 3
    также: (27,9): ошибка TS2304: не удается найти имя «поставщик». – DS_web_developer 20 September 2016 в 10:28
  • 4
    ОК, нереализованный легко, он больше не в исключениях, а в ошибках: «@ angular / core / src / facade / errors»; – DS_web_developer 20 September 2016 в 11:23
  • 5
    Это должен быть принятый ответ. Отлично работает. – cgTag 18 December 2016 в 19:43

Достаточно сделать

export class AppWindow extends Window {} 

и сделать

{ provide: 'AppWindow', useValue: window } 

, чтобы сделать AOT happy

13
ответ дан Günter Zöchbauer 19 August 2018 в 04:50
поделиться
  • 1
    Спасибо за решение, я пошел с WindowRef, но немного модифицировался. См. gist.github.com/lokanx/cc022ee0b8999cd3b7f5 – lokanx 10 December 2015 в 23:56
  • 2
    вызов WindowRef сделает его более последовательным, но может также быть запутанным для кода структуры, что тоже работает – gdi2290 30 December 2015 в 19:11
  • 3
    Ваш сервис устарел, пожалуйста, обновите – Ashutosh Jha 29 December 2016 в 07:06
  • 4
    Почему я получил ошибку ReferenceError: Window is not defined? – John_J 12 September 2017 в 04:11
  • 5
    Когда я пытаюсь внедрить его внутри конструктора, он предоставляет конструктор Illegal. – John Maclein 3 October 2017 в 09:18

Держите его простым, ребята!

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

<div>{{window.Object.entries({ foo: 1 }) | json}}</div>
0
ответ дан geoyws 19 August 2018 в 04:50
поделиться

С выпуском углового 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) {}
}

Вы также можете использовать a 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

22
ответ дан JNK 19 August 2018 в 04:50
поделиться
  • 1
    и где вы использовали AppModule – Zamboney 15 August 2016 в 09:29
  • 2
    Вы используете его для загрузки приложения или импорта его в другой модуль. Я редактировал мой пост – JNK 17 August 2016 в 13:59
  • 3
    Это одна из тех вещей, которые касаются Angular 2, которые я не понимаю. В какой момент вам нужно «просто знать», использовать декоратор @Inject в конструкторе? – dudewad 23 August 2016 в 22:59
  • 4
    В случае, если это полезно для кого-то еще, это не сработало для меня, пока я не добавил private в конструктор: @Inject('Window') private window: Window – StudioLE 22 February 2017 в 12:49
  • 5
    это решение выдает исключение с помощью команды ng serve --prod --aot – Atul Chaudhary 6 May 2017 в 10:54

В Angular RC4 следующие работы, которые представляют собой комбинацию некоторых из вышеперечисленных ответов, в корневом приложении app.ts добавят его:

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

Затем в вашем сервисе и т. д. вставьте его в конструктор

constructor(
      @Inject(Window) private _window: Window,
)
6
ответ дан Joel Davey 19 August 2018 в 04:50
поделиться
  • 1
    Это лучший ответ. Мне не нужно было вводить инъекции, я просто имею объявление constructor(private window: Window) – Stevo 26 October 2016 в 16:00

Чтобы заставить его работать с 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 }
10
ответ дан Klas Mellbourn 19 August 2018 в 04:50
поделиться
  • 1
    лучший ответ: вы можете ввести консоль таким образом, i.e. {обеспечить: «Консоль», useValue: window.console} – John Hardy 1 November 2016 в 04:44
  • 2
    Я использую ту же версию, но она жалуется на @NgModule, что окно не существует. – Mukus 9 December 2016 в 17:48
  • 3
    @Mukus Это звучит как проблема с окружающей средой. window должна быть неявно известной переменной в TypeScript. – Klas Mellbourn 9 December 2016 в 18:12
  • 4
    И это было так, когда я был на версии 2.2.1. Я должен понизить до 2.1.1, потому что Ionic RC3 не работает с этой версией. И в 2.1.1 он просто не понимает, в каком окне. – Mukus 9 December 2016 в 23:11
  • 5
    Тест @Mukus & amp; с ионным 2.1.3! – emc 24 August 2017 в 05:26

Вы можете использовать NgZone на угловом 4:

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

constructor(private zone: NgZone) {}

print() {
    this.zone.runOutsideAngular(() => window.print());
}
2
ответ дан Leonardo Pinto 19 August 2018 в 04:50
поделиться

Угловые 4 вводят InjectToken, а также создают токен для документа, называемого DOCUMENT . Я думаю, что это официальное решение, и оно работает в AoT.

Я использую ту же логику, чтобы создать небольшую библиотеку, названную ngx-window-token , чтобы не делать этого снова и снова ,

Я использовал его в другом проекте и строил в AoT без проблем.

Вот как я использовал его в другом пакете

Здесь plunker

В вашем модуле

imports: [ BrowserModule, WindowTokenModule ] В вашем компоненте

constructor(@Inject(WINDOW) _window) { }

4
ответ дан maxisam 19 August 2018 в 04:50
поделиться
  • 1
    это должно быть просто встроено в Угловое – C.M. 8 June 2017 в 17:00
  • 2
    Они не могут. Они пытаются заставить Angular не привязываться к определенной платформе. – maxisam 8 June 2017 в 20:11
  • 3
    Спасибо Maxisan за это! Я использовал модуль npm, и он отлично работал в проекте Ionic, пока я не попытался скомпилировать сборку. (ионная загрузка --prod). Прямой импорт ngx-window-token / src / index.ts решил это. Извините, не знаю, почему ... – ryanrain 13 August 2017 в 19:33
  • 4
    @ryanrain вы можете сообщить об этом на github? Я посмотрю, когда у меня будет время. Было бы замечательно, если бы вы также приложили сообщение об ошибке – maxisam 14 August 2017 в 06:52

Это самый короткий / самый чистый ответ, который я нашел, работая с 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);
  }
}
1
ответ дан nwarp 19 August 2018 в 04:50
поделиться

Вы можете просто ввести его после того, как вы установили провайдера:

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

constructor(private window: Window) {
    // this.window
}
15
ответ дан Paul Dutka 19 August 2018 в 04:50
поделиться
  • 1
    но когда я изменяю window.var, содержимое страницы не изменяется – Ravinder Payal 12 May 2016 в 05:17
  • 2
    Это не работает в Safari, поскольку Window не является инъекционным. Я должен был создать свой собственный тип Injectable, который содержал свойства Window, которые мне нужны. Возможно, лучший подход заключался в создании службы, как описано в других ответах – daveb 27 May 2016 в 10:07
  • 3
    Этот подход вызывает ошибку в Safari – Kamil Kiełczewski 4 August 2016 в 19:56
  • 4
    Этот подход не работает, потому что useValue фактически создает копию значения, которое вы ему предоставляете. См. github.com/angular/angular/issues/10788#issuecomment-300614425 . Этот подход будет работать, если вы измените его на использование useFactory и вернете значение из обратного вызова. – Levi Lindsey 14 November 2017 в 01:33

Перед объявлением @Component вы также можете это сделать,

declare var window: any;

Компилятор фактически позволит вам затем перейти к глобальной переменной окна, поскольку вы объявляете ее как предполагаемую глобальную переменную с типом any .

Я бы не предлагал обращаться к окну повсюду в вашем приложении, хотя вам следует создавать службы, которые получают доступ / модифицируют необходимые атрибуты окна (и внедряют эти службы в ваши компоненты) в объем, который вы можете делать с помощью окна, не позволяя им изменять весь объект окна.

7
ответ дан S.Galarneau 19 August 2018 в 04:50
поделиться

Получение объекта окна через DI (Injection Dependency) не является хорошей идеей, когда глобальные переменные доступны во всем приложении.

Но если вы не хотите использовать объект окна, вы также можете использовать self, которое также указывает на объект окна.

-1
ответ дан Shivang Gupta 19 August 2018 в 04:50
поделиться
  • 1
    Это нехороший совет. Dependency Injection упрощает тестирование классов (компонентов, директив, служб, труб и т. Д.) (Например, даже без браузера) и более простое использование на разных платформах, таких как рендеринг на стороне сервера или веб-рабочих. Это может сработать для некоторых, и простота может иметь некоторую привлекательность, но обескураживать использование DI - это ИМХО плохой ответ. – Günter Zöchbauer 31 January 2018 в 11:43
  • 2
    Я согласен, но без браузера, как оконный объект доступен? – Shivang Gupta 31 January 2018 в 11:57
  • 3
    Вы можете передать макет объекта вместо реального. Это причина, по которой DI делает тестирование таким простым. – Günter Zöchbauer 31 January 2018 в 11:58

Я знаю, что вопрос заключается в том, как вставить объект окна в компонент, но вы делаете это только для того, чтобы добраться до localStorage. Если вы просто хотите localStorage, почему бы не использовать сервис, который предоставляет именно это, например h5webstorage . Затем компонент будет описывать его реальные зависимости, которые делают ваш код более удобочитаемым.

3
ответ дан SirDarquan 19 August 2018 в 04:50
поделиться
  • 1
    Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. – cpburnz 28 April 2016 в 18:52

На сегодняшний день (апрель 2016 года) код в предыдущем решении не работает, я думаю, что можно сразу вводить окно в 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;
    }
}
6
ответ дан Will de la Vega 19 August 2018 в 04:50
поделиться

Существует возможность прямого доступа к объекту окна через документ

document.defaultView == window
2
ответ дан Василь Петров 19 August 2018 в 04:50
поделиться
  • 1
    Отличная идея. Это действительно помогает мне. – Maosheng Wang 3 June 2018 в 09:43
0
ответ дан Alex Nikulin 30 October 2018 в 16:46
поделиться
13
ответ дан Günter Zöchbauer 30 October 2018 в 16:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: