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
Это работает для меня в настоящее время (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 Ввод текста
@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});
}
Короткая и сладкая и работает как очарование.
Я использовал 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 {}
Достаточно сделать
export class AppWindow extends Window {}
и сделать
{ provide: 'AppWindow', useValue: window }
, чтобы сделать AOT happy
Держите его простым, ребята!
export class HeroesComponent implements OnInit {
heroes: Hero[];
window = window;
}
<div>{{window.Object.entries({ foo: 1 }) | json}}</div>
С выпуском углового 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
@Inject('Window') private window: Window
– StudioLE
22 February 2017 в 12:49
В Angular RC4 следующие работы, которые представляют собой комбинацию некоторых из вышеперечисленных ответов, в корневом приложении app.ts добавят его:
@Component({
templateUrl: 'build/app.html',
providers: [
anotherProvider,
{ provide: Window, useValue: window }
]
})
Затем в вашем сервисе и т. д. вставьте его в конструктор
constructor(
@Inject(Window) private _window: Window,
)
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 }
window
должна быть неявно известной переменной в TypeScript.
– Klas Mellbourn
9 December 2016 в 18:12
Вы можете использовать NgZone на угловом 4:
import { NgZone } from '@angular/core';
constructor(private zone: NgZone) {}
print() {
this.zone.runOutsideAngular(() => window.print());
}
Угловые 4 вводят InjectToken, а также создают токен для документа, называемого DOCUMENT . Я думаю, что это официальное решение, и оно работает в AoT.
Я использую ту же логику, чтобы создать небольшую библиотеку, названную ngx-window-token , чтобы не делать этого снова и снова ,
Я использовал его в другом проекте и строил в AoT без проблем.
Вот как я использовал его в другом пакете
Здесь plunker
В вашем модуле
imports: [ BrowserModule, WindowTokenModule ]
В вашем компоненте
constructor(@Inject(WINDOW) _window) { }
Это самый короткий / самый чистый ответ, который я нашел, работая с 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);
}
}
Вы можете просто ввести его после того, как вы установили провайдера:
import {provide} from 'angular2/core';
bootstrap(..., [provide(Window, {useValue: window})]);
constructor(private window: Window) {
// this.window
}
window.var
, содержимое страницы не изменяется
– Ravinder Payal
12 May 2016 в 05:17
Перед объявлением @Component вы также можете это сделать,
declare var window: any;
Компилятор фактически позволит вам затем перейти к глобальной переменной окна, поскольку вы объявляете ее как предполагаемую глобальную переменную с типом any .
Я бы не предлагал обращаться к окну повсюду в вашем приложении, хотя вам следует создавать службы, которые получают доступ / модифицируют необходимые атрибуты окна (и внедряют эти службы в ваши компоненты) в объем, который вы можете делать с помощью окна, не позволяя им изменять весь объект окна.
Получение объекта окна через DI (Injection Dependency) не является хорошей идеей, когда глобальные переменные доступны во всем приложении.
Но если вы не хотите использовать объект окна, вы также можете использовать self
, которое также указывает на объект окна.
Я знаю, что вопрос заключается в том, как вставить объект окна в компонент, но вы делаете это только для того, чтобы добраться до localStorage. Если вы просто хотите localStorage, почему бы не использовать сервис, который предоставляет именно это, например h5webstorage . Затем компонент будет описывать его реальные зависимости, которые делают ваш код более удобочитаемым.
На сегодняшний день (апрель 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;
}
}
Существует возможность прямого доступа к объекту окна через документ
document.defaultView == window
ORIGINAL EXCEPTION: No provider for Window!
. Однако удаление этого исправлено для меня. Для меня было достаточно всего лишь первых двух глобальных линий. – Truchainz 16 June 2016 в 23:29@Inject
я получал ошибкиNo provider for Window
. Это довольно хорошо, не нужно руководство@Inject
! – elwyn 17 June 2016 в 01:57@Inject(Window)
для этого – James Kleeh 15 November 2016 в 17:55window
, но при обслуживании между ними он позволяет заглушить собственный материалwindow
в модульных тестах, и, как вы упомянули для SSR, может быть предоставлена альтернативная услуга, которая предоставляет окно mock / noop для сервер. Причина, по которой я упоминаю AOT, - это несколько ранних решений для обертывания окна в AOT, когда Angular обновлен. – elwyn 10 January 2018 в 19:55