【发布时间】:2018-12-13 03:53:02
【问题描述】:
我正在尝试创建一个 Angular 服务,组件可以使用它来观察窗口调整大小事件。经过多次尝试,我终于发现这个解决方案效果最好https://stackoverflow.com/a/43833815。
但是,在 SSR 中运行时似乎会报错。
TypeError: this.eventManager.addGlobalEventListener is not a function
经过多次尝试,这就是我所在的位置:
服务
import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
import { EventManager } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class WindowService {
private resizeSubject: Subject<Window>;
constructor(
@Inject(PLATFORM_ID) private eventManager: EventManager) { // Event is not defined without @Inject(PLATFORM_ID)
this.resizeSubject = new Subject();
this.eventManager.addGlobalEventListener('window', 'resize', this.onResize.bind(this));
}
private onResize(event: UIEvent) {
this.resizeSubject.next(<Window>event.target);
}
/**
* Get an observerable for the window resize event
* @returns Return the window resize as an observable
*/
get onResize$(): Observable<Window> {
return this.resizeSubject.asObservable();
}
}
组件
import { Component, ElementRef, Input, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs/Subscription';
import { WindowService } from '../../services/window.service';
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html'
})
export class SidebarComponent implements OnInit, OnDestroy {
element: HTMLElement;
resizeSubscription: Subscription;
constructor(
private readonly el: ElementRef,
private windowService: WindowService) {
this.element = el.nativeElement;
}
ngOnInit(): void {
const self = this;
this.resizeSubscription = this.windowService.onResize$
.debounceTime(100)
.subscribe(function(windowObj) {
if (windowObj.innerWidth >= 1024) {
self.open();
} else {
self.close();
}
});
}
ngOnDestroy(): void {
if (this.resizeSubscription) {
this.resizeSubscription.unsubscribe();
}
}
...
}
绑定到窗口大小调整事件似乎是一种非常复杂的方法,但我还没有找到更好的方法来使用 Angular SRR。有推荐的方法吗?本质上,我需要在调整大小(以及加载)时检查窗口大小并相应地打开或关闭侧边栏。
【问题讨论】:
-
是否有什么东西阻止您在服务
window.onresize = ...中使用以下语法? -
@Ploppy 我不确定这会起作用,因为 Angular SSR 不知道“窗口”是什么?
-
我没有仔细阅读并错过了 SSR 部分,但是,我认为你做得很好,你甚至对 observable 进行了去抖动。我没有看到任何不好的情况,但请等待更多人确认。
-
你为什么不检查平台是否只添加事件处理程序,如果你是客户端?
-
@David 我尝试将
this.eventManager.addGlobalEventListener包装在 isPlatform 检查中,然后加载服务器端正常,但是当它将状态传输到客户端时它会出错。我假设是因为此时 WindowService 构造函数已经初始化,并且 angular 不会重新初始化 globalEventListener。
标签: angular server-side-rendering