作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我将 Angular 2.0.0-rc.4 与 RxJS 5.0.0-beta.6 一起使用。
我正在尝试从事件中创建可观察流的不同方法,但我对这些选项感到不知所措并想征求意见。我很欣赏没有一刀切的解决方案,并且类(class)中有马。可能还有其他我不知道或没有考虑过的技术。
Angular 2 component interaction cookbook提供了父组件与子组件事件交互的几种方法。但是,只有parent and children communicate via a service的例子使用 observables 并且在大多数情况下似乎有点矫枉过正。
场景是模板的元素发出大量事件,我想定期知道最新的值是什么。
我用 Observable
的 sampleTime
以 1000ms 为周期监控鼠标位置的方法 <p>
HTML 元素。
1) 此技术使用 ElementRef
注入(inject)组件的构造函数以访问 nativeElement
属性并通过标签名称查询子元素。
@Component({
selector: 'watch-child-events',
template: `
<p>Move over me!</p>
<div *ngFor="let message of messages">{{message}}</div>
`
})
export class WatchChildEventsComponent implements OnInit {
messages:string[] = [];
constructor(private el:ElementRef) {}
ngOnInit() {
let p = this.el.nativeElement.getElementsByTagName('p')[0];
Observable
.fromEvent(p, 'mousemove')
.sampleTime(1000)
.subscribe((e:MouseEvent) => {
this.messages.push(`${e.type} (${e.x}, ${e.y})`);
});
}
}
fromEvent
Observable
的工厂方法使用起来相当诱人,这是第一个想到的技术。
EventEmitter
,这是一个
Observable
.
@Component({
selector: 'watch-child-events',
template: `
<p (mousemove)="handle($event)">Move over me!</p>
<div *ngFor="let message of messages">{{message}}</div>
`
})
export class WatchChildEventsComponent implements OnInit {
messages:string[] = [];
emitter:EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
ngOnInit() {
this.emitter
.sampleTime(1000)
.subscribe((e:MouseEvent) => {
this.messages.push(`${e.type} (${e.x}, ${e.y})`);
});
}
handle(e:MouseEvent) {
this.emitter.emit(e);
}
}
Subject
.
@Component({
selector: 'watch-child-events',
template: `
<p (mousemove)="handle($event)">Move over me!</p>
<div *ngFor="let message of messages">{{message}}</div>
`
})
export class WatchChildEventsComponent implements OnInit {
messages:string[] = [];
subject = new Subject<MouseEvent>();
ngOnInit() {
this.subject
.sampleTime(1000)
.subscribe((e:MouseEvent) => {
this.messages.push(`${e.type} (${e.x}, ${e.y})`);
});
}
handle(e:MouseEvent) {
this.subject.next(e);
}
}
ReplaySubject
在我订阅时接收已发布值的完整历史记录,或者只是最近的一个(如果存在),使用
subject = new ReplaySubject<MouseEvent>(1);
反而。
@ViewChild
装饰器。
@Component({
selector: 'watch-child-events',
template: `
<p #p">Move over me!</p>
<div *ngFor="let message of messages">{{message}}</div>
`
})
export class WatchChildEventsComponent implements AfterViewInit {
messages:string[] = [];
@ViewChild('p') p:ElementRef;
ngAfterViewInit() {
Observable
.fromEvent(this.p.nativeElement, 'mousemove')
.sampleTime(1000)
.subscribe((e:MouseEvent) => {
this.messages.push(`${e.type} (${e.x}, ${e.y})`);
});
}
}
nativeElement
触及 DOM , 使用字符串来引用事件名称和模板引用,并使用
AfterViewInit
生命周期钩子(Hook)。
Subject
的自定义组件并定期发出事件。
@Component({
selector: 'child-event-producer',
template: `
<p (mousemove)="handle($event)">
<ng-content></ng-content>
</p>
`
})
export class ChildEventProducerComponent {
@Output() event = new EventEmitter<MouseEvent>();
subject = new Subject<MouseEvent>();
constructor() {
this.subject
.sampleTime(1000)
.subscribe((e:MouseEvent) => {
this.event.emit(e);
});
}
handle(e:MouseEvent) {
this.subject.next(e);
}
}
@Component({
selector: 'watch-child-events',
template: `
<child-event-producer (event)="handle($event)">
Move over me!
</child-event-producer>
<div *ngFor="let message of messages">{{message}}</div>
`,
directives: [ChildEventProducerComponent]
})
export class WatchChildEventsComponent {
messages:string[] = [];
handle(e:MouseEvent) {
this.messages.push(`${e.type} (${e.x}, ${e.y})`);
}
}
@Component({
selector: 'child-event-producer',
template: `
<p (mousemove)="handle($event)">
<ng-content></ng-content>
</p>
`
})
export class ChildEventProducerComponent {
@Output() event = new EventEmitter<MouseEvent>();
handle(e:MouseEvent) {
this.event.emit(e);
}
}
@ViewChild
连接到父级中装饰器要么像这样:
@Component({
selector: 'watch-child-events',
template: `
<child-event-producer>
Move over me!
</child-event-producer>
<div *ngFor="let message of messages">{{message}}</div>
`,
directives: [ChildEventProducerComponent]
})
export class WatchChildEventsComponent implements AfterViewInit {
messages:string[] = [];
@ViewChild(ChildEventProducerComponent) child:ChildEventProducerComponent;
ngAfterViewInit() {
Observable
.from(this.child.event)
.sampleTime(1000)
.subscribe((e:MouseEvent) => {
this.messages.push(`${e.type} (${e.x}, ${e.y})`);
});
}
}
@Component({
selector: 'watch-child-events',
template: `
<child-event-producer (event)="handle($event)">
Move over me!
</child-event-producer>
<div *ngFor="let message of messages">{{message}}</div>
`,
directives: [ChildEventProducerComponent]
})
export class WatchChildEventsComponent implements OnInit {
messages:string[] = [];
subject = new Subject<MouseEvent>();
ngOnInit() {
this.subject
.sampleTime(1000)
.subscribe((e:MouseEvent) => {
this.messages.push(`${e.type} (${e.x}, ${e.y})`);
});
}
handle(e:MouseEvent) {
this.subject.next(e);
}
}
Subject
,这与早期的技术相同。
@Injectable()
export class LocationService {
private source = new ReplaySubject<{x:number;y:number;}>(1);
stream:Observable<{x:number;y:number;}> = this.source
.asObservable()
.sampleTime(1000);
moveTo(location:{x:number;y:number;}) {
this.source.next(location);
}
}
LocationService
注入(inject)构造函数并调用
moveTo
在事件处理程序中。
@Component({
selector: 'child-event-producer',
template: `
<p (mousemove)="handle($event)">
<ng-content></ng-content>
</p>
`
})
export class ChildEventProducerComponent {
constructor(private svc:LocationService) {}
handle(e:MouseEvent) {
this.svc.moveTo({x: e.x, y: e.y});
}
}
@Component({
selector: 'watch-child-events',
template: `
<child-event-producer>
Move over me!
</child-event-producer>
<div *ngFor="let message of messages">{{message}}</div>
`,
directives: [ChildEventProducerComponent],
providers: [LocationService]
})
export class WatchChildEventsComponent implements OnInit, OnDestroy {
messages:string[] = [];
subscription:Subscription;
constructor(private svc:LocationService) {}
ngOnInit() {
this.subscription = this.svc.stream
.subscribe((e:{x:number;y:number;}) => {
this.messages.push(`(${e.x}, ${e.y})`);
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
最佳答案
在方法 6 中,您可以使用 event binding (scroll down to "Custom Events with EventEmitter") 而不是 @ViewChild
和 ngAfterViewInit
,这简化了很多:
@Component({
selector: 'watch-child-events',
template: `
<child-event-producer (event)="onEvent($event)">
Move over me!
</child-event-producer>
<div *ngFor="let message of messages">{{message}}</div>
`,
directives: [ChildEventProducerComponent]
})
export class WatchChildEventsComponent {
messages:string[] = [];
onEvent(e) { this.messages.push(`${e.type} (${e.x}, ${e.y})`); }
}
关于typescript - 如何从 Angular2 组件模板子元素事件创建 RxJS 可观察流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38722621/
我是一名优秀的程序员,十分优秀!