Dan*_*bdn 199 javascript angular
我想基于窗口重新调整大小事件(加载和动态)执行一些任务.
目前我有我的DOM如下:
<div id="Harbour">
<div id="Port" (window:resize)="onResize($event)" >
<router-outlet></router-outlet>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
事件正确触发
export class AppComponent {
onResize(event) {
console.log(event);
}
}
Run Code Online (Sandbox Code Playgroud)
如何从此事件对象中检索宽度和高度?
谢谢.
Gün*_*uer 458
<div (window:resize)="onResize($event)"
Run Code Online (Sandbox Code Playgroud)
onResize(event) {
event.target.innerWidth;
}
Run Code Online (Sandbox Code Playgroud)
要么
@HostListener('window:resize', ['$event'])
onResize(event) {
event.target.innerWidth;
}
Run Code Online (Sandbox Code Playgroud)
支持的全球目标是window,document和body.
在Angular中实现https://github.com/angular/angular/issues/13248之前,性能更好地订阅DOM事件并使用RXJS来减少事件量,如其他一些答案中所示.
Joh*_*ohn 59
@Günter的回答是正确的.我只是想提出另一种方法.
您还可以在@Component()-decorator中添加主机绑定.您可以将事件和所需的函数调用放在host-metadata-property中,如下所示:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
host: {
'(window:resize)': 'onResize($event)'
}
})
export class AppComponent{
onResize(event){
event.target.innerWidth; // window width
}
}
Run Code Online (Sandbox Code Playgroud)
cga*_*ian 40
执行此操作的正确方法是使用EventManager类绑定事件.这允许您的代码在替代平台中工作,例如使用Angular Universal进行服务器端渲染.
import { EventManager } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Injectable } from '@angular/core';
@Injectable()
export class ResizeService {
get onResize$(): Observable<Window> {
return this.resizeSubject.asObservable();
}
private resizeSubject: Subject<Window>;
constructor(private eventManager: EventManager) {
this.resizeSubject = new Subject();
this.eventManager.addGlobalEventListener('window', 'resize', this.onResize.bind(this));
}
private onResize(event: UIEvent) {
this.resizeSubject.next(<Window>event.target);
}
}
Run Code Online (Sandbox Code Playgroud)
在组件中使用就像将此服务作为提供程序添加到app.module然后在组件的构造函数中导入它一样简单.
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-component',
template: ``,
styles: [``]
})
export class MyComponent implements OnInit {
private resizeSubscription: Subscription;
constructor(private resizeService: ResizeService) { }
ngOnInit() {
this.resizeSubscription = this.resizeService.onResize$
.subscribe(size => console.log(size));
}
ngOnDestroy() {
if (this.resizeSubscription) {
this.resizeSubscription.unsubscribe();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Gri*_*mer 30
这是一个更好的方法.根据Birowsky的回答.
第1步:angular service使用RxJS Observables创建一个.
import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
@Injectable()
export class WindowService {
height$: Observable<number>;
//create more Observables as and when needed for various properties
hello: string = "Hello";
constructor() {
let windowSize$ = new BehaviorSubject(getWindowSize());
this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();
Observable.fromEvent(window, 'resize')
.map(getWindowSize)
.subscribe(windowSize$);
}
}
function getWindowSize() {
return {
height: window.innerHeight
//you can sense other parameters here
};
};
Run Code Online (Sandbox Code Playgroud)
步骤2:注入上述内容service并订阅Observables服务中创建的任何您希望接收窗口调整大小事件的位置.
import { Component } from '@angular/core';
//import service
import { WindowService } from '../Services/window.service';
@Component({
selector: 'pm-app',
templateUrl: './componentTemplates/app.component.html',
providers: [WindowService]
})
export class AppComponent {
constructor(private windowService: WindowService) {
//subscribe to the window resize event
windowService.height$.subscribe((value:any) => {
//Do whatever you want with the value.
//You can also subscribe to other observables of the service
});
}
}
Run Code Online (Sandbox Code Playgroud)
对反应式编程的充分理解将始终有助于克服困难问题.希望这有助于某人.
Chr*_*ley 30
我知道这是很久以前的问题,但现在有更好的方法可以做到这一点!我不确定是否有人会看到这个答案.显然你的进口:
import { fromEvent, Observable, Subscription } from "rxjs";
Run Code Online (Sandbox Code Playgroud)
然后在你的组件中:
resizeObservable$: Observable<Event>
resizeSubscription$: Subscription
ngOnInit() {
this.resizeObservable$ = fromEvent(window, 'resize')
this.resizeSubscription$ = this.resizeObservable$.subscribe( evt => {
console.log('event: ', evt)
})
}
Run Code Online (Sandbox Code Playgroud)
然后一定要取消订阅摧毁!
ngOnDestroy() {
this.resizeSubscription$.unsubscribe()
}
Run Code Online (Sandbox Code Playgroud)
Tot*_*ati 15
angular CDK 中有一个ViewportRuler服务。它在区域外运行,支持orientationchange和resize。它也适用于服务器端渲染。
@Component({
selector: 'my-app',
template: `
<p>Viewport size: {{ width }} x {{ height }}</p>
`
})
export class AppComponent implements OnDestroy {
width: number;
height: number;
private readonly viewportChange = this.viewportRuler
.change(200)
.subscribe(() => this.ngZone.run(() => this.setSize()));
constructor(
private readonly viewportRuler: ViewportRuler,
private readonly ngZone: NgZone
) {
// Change happens well, on change. The first load is not a change, so we init the values here. (You can use `startWith` operator too.)
this.setSize();
}
// Never forget to unsubscribe!
ngOnDestroy() {
this.viewportChange.unsubscribe();
}
private setSize() {
const { width, height } = this.viewportRuler.getViewportSize();
this.width = width;
this.height = height;
}
}
Run Code Online (Sandbox Code Playgroud)
Sta*_*avm 10
我还没有看到任何人谈论MediaMatcher的angular/cdk.
您可以定义MediaQuery并将侦听器附加到它 - 然后在模板(或ts)上的任何位置,如果匹配匹配,您可以调用内容. LiveExample
App.Component.ts
import {Component, ChangeDetectorRef} from '@angular/core';
import {MediaMatcher} from '@angular/cdk/layout';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
mobileQuery: MediaQueryList;
constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher) {
this.mobileQuery = media.matchMedia('(max-width: 600px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
}
private _mobileQueryListener: () => void;
ngOnDestroy() {
this.mobileQuery.removeListener(this._mobileQueryListener);
}
}
Run Code Online (Sandbox Code Playgroud)
App.Component.Html
<div [class]="mobileQuery.matches ? 'text-red' : 'text-blue'"> I turn red on mobile mode
</div>
Run Code Online (Sandbox Code Playgroud)
App.Component.css
.text-red {
color: red;
}
.text-blue {
color: blue;
}
Run Code Online (Sandbox Code Playgroud)
来源:https://material.angular.io/components/sidenav/overview
假设<600px意味着移动给你,你可以使用这个observable并订阅它:
首先,我们需要当前的窗口大小.所以我们创建一个只发出一个值的observable:当前窗口大小.
initial$ = Observable.of(window.innerWidth > 599 ? false : true);
Run Code Online (Sandbox Code Playgroud)
然后我们需要创建另一个observable,以便我们知道窗口大小何时被更改.为此,我们可以使用"fromEvent"运算符.要了解有关rxjs`s运营商的更多信息,请访问:rxjs
resize$ = Observable.fromEvent(window, 'resize').map((event: any) => {
return event.target.innerWidth > 599 ? false : true;
});
Run Code Online (Sandbox Code Playgroud)
合并这两个流以接收我们的可观察量:
mobile$ = Observable.merge(this.resize$, this.initial$).distinctUntilChanged();
Run Code Online (Sandbox Code Playgroud)
现在您可以像这样订阅它:
mobile$.subscribe((event) => { console.log(event); });
Run Code Online (Sandbox Code Playgroud)
记得取消订阅:)
如果您只想在调整大小完成后发生一个事件,最好将 RxJS 与debounceTime结合使用: debounceTime:丢弃在输出之间花费的时间少于指定时间的发出值。
在运行代码之前,他在发出的 2 个事件之间等待了 > 0.5 秒。简单来说,它会等待大小调整完成后再执行下一个代码。
// RxJS v6+
import { fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';
...
const resize$ = fromEvent(window, 'resize');
resize$
.pipe(
map((i: any) => i),
debounceTime(500) // He waits > 0.5s between 2 events emitted before running the next.
)
.subscribe((event) => {
console.log('resize is finished');
});
Run Code Online (Sandbox Code Playgroud)
我检查了大部分答案。然后决定查看有关Layout的 Angular 文档。
Angular 有自己的观察者来检测不同的大小,并且很容易实现到组件或服务中。
一个简单的例子是:
import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';
@Component({...})
class MyComponent {
constructor(breakpointObserver: BreakpointObserver) {
breakpointObserver.observe([
Breakpoints.HandsetLandscape,
Breakpoints.HandsetPortrait
]).subscribe(result => {
if (result.matches) {
this.activateHandsetLayout();
}
});
}
}Run Code Online (Sandbox Code Playgroud)
希望能帮助到你