我可以 运行 @Hostlistner 使用其他鼠标事件吗?
Can I run @Hostlistner with other mouse event?
为了避免设置无用的侦听器,我想仅在 mousedown 事件 为 [=26] 时才启动 mousemove 侦听器 =].类似的东西:
我的component.ts
里面
private startMouseMove(start: boolean){
if(start){
@HostListener('mousemove', ['$event'])
onMouseMove(event: MouseEvent){
console.log("start mousemove");
this.mousemove.emit(event);
}
}
}
@HostListener('mouseup', ['$event'])
onMouseup(event: MouseEvent){
console.log(event.type);
this.startMouseMove(false);
}
@HostListener('mousedown', ['$event'])
onMousedown(event: MouseEvent) {
console.log(event.type);
this.startMouseMove(true);
return false; // Call preventDefault() on the event
}
那当然不行。我想知道在 Angular 中是否可行,如果可行,该怎么做?
一种可能的解决方案是使用反应式方法:
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/takeUntil';
@Directive({
selector: '[my-drag]'
})
export class DragDirective {
subscription: Subscription;
constructor(private elRef: ElementRef, private zone: NgZone) {}
ngOnInit() {
this.zone.runOutsideAngular(() => this.initDragEvent());
}
initDragEvent() {
const el = this.elRef.nativeElement;
const mousedown = Observable.fromEvent(el, 'mousedown');
const mouseup = Observable.fromEvent(el, 'mouseup');
const mousemove = Observable.fromEvent(document, 'mousemove');
const mousedrag = mousedown.flatMap((md: any) => {
const startX = md.offsetX;
const startY = md.offsetY;
return mousemove.map((e: any) => {
e.preventDefault();
return {
left: e.clientX - startX,
top: e.clientY - startY
};
}).takeUntil(mouseup);
});
this.subscription = mousedrag.subscribe((pos) => {
console.log('mousemove is fired');
el.style.top = pos.top + 'px';
el.style.left = pos.left + 'px';
});
}
ngOnDestroy() {
if(this.subscription) {
this.subscription.unsubscribe();
}
}
}
我 运行 initDragEvent
超出了 angular 区域,因为我不希望发生冗余更改检测。
另一个解决方案是使用渲染器
export class DragDirective {
listener: Function;
@HostListener('mouseup', ['$event'])
onMouseup(event: MouseEvent) {
console.log(event.type);
this.startMouseMove(false);
}
@HostListener('mousedown', ['$event'])
onMousedown(event: MouseEvent) {
console.log(event.type);
this.startMouseMove(true);
return false;
}
constructor(private renderer: Renderer2) {}
private startMouseMove(start: boolean) {
this.ngOnDestroy();
if (start) {
this.listener = this.renderer.listen(document, 'mousemove', () => {
console.log("start mousemove", this.listener);
})
}
}
ngOnDestroy() {
if(this.listener) {
this.listener();
}
}
}
为了避免设置无用的侦听器,我想仅在 mousedown 事件 为 [=26] 时才启动 mousemove 侦听器 =].类似的东西:
我的component.ts
里面private startMouseMove(start: boolean){
if(start){
@HostListener('mousemove', ['$event'])
onMouseMove(event: MouseEvent){
console.log("start mousemove");
this.mousemove.emit(event);
}
}
}
@HostListener('mouseup', ['$event'])
onMouseup(event: MouseEvent){
console.log(event.type);
this.startMouseMove(false);
}
@HostListener('mousedown', ['$event'])
onMousedown(event: MouseEvent) {
console.log(event.type);
this.startMouseMove(true);
return false; // Call preventDefault() on the event
}
那当然不行。我想知道在 Angular 中是否可行,如果可行,该怎么做?
一种可能的解决方案是使用反应式方法:
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/takeUntil';
@Directive({
selector: '[my-drag]'
})
export class DragDirective {
subscription: Subscription;
constructor(private elRef: ElementRef, private zone: NgZone) {}
ngOnInit() {
this.zone.runOutsideAngular(() => this.initDragEvent());
}
initDragEvent() {
const el = this.elRef.nativeElement;
const mousedown = Observable.fromEvent(el, 'mousedown');
const mouseup = Observable.fromEvent(el, 'mouseup');
const mousemove = Observable.fromEvent(document, 'mousemove');
const mousedrag = mousedown.flatMap((md: any) => {
const startX = md.offsetX;
const startY = md.offsetY;
return mousemove.map((e: any) => {
e.preventDefault();
return {
left: e.clientX - startX,
top: e.clientY - startY
};
}).takeUntil(mouseup);
});
this.subscription = mousedrag.subscribe((pos) => {
console.log('mousemove is fired');
el.style.top = pos.top + 'px';
el.style.left = pos.left + 'px';
});
}
ngOnDestroy() {
if(this.subscription) {
this.subscription.unsubscribe();
}
}
}
我 运行 initDragEvent
超出了 angular 区域,因为我不希望发生冗余更改检测。
另一个解决方案是使用渲染器
export class DragDirective {
listener: Function;
@HostListener('mouseup', ['$event'])
onMouseup(event: MouseEvent) {
console.log(event.type);
this.startMouseMove(false);
}
@HostListener('mousedown', ['$event'])
onMousedown(event: MouseEvent) {
console.log(event.type);
this.startMouseMove(true);
return false;
}
constructor(private renderer: Renderer2) {}
private startMouseMove(start: boolean) {
this.ngOnDestroy();
if (start) {
this.listener = this.renderer.listen(document, 'mousemove', () => {
console.log("start mousemove", this.listener);
})
}
}
ngOnDestroy() {
if(this.listener) {
this.listener();
}
}
}