如何在AngularJS中使用fromEvent方法创建可观察数据流
在这篇文章中,我们将学习Observable如何支持angular应用程序中发布者和订阅者之间的数据共享。与承诺等技术相比,Observable被称为是一种更好的事件处理、异步编程和处理多值的技术。
- 可观察的:代表一个可以随时间到达的数据流或数据源。但如果没有订阅者,可观察者就没有意义。
-
订阅者:简单地说,它是一段保持对Observable及其数据的关注的代码。它获取数据并使其对组件可用。
先决知识:
1.Angular v6.2.9或以上和RxJs v6.4.0或以上
2.Node v10.15.3或以上和NPM v6.4.1或以上
(Note: RxJs is automatically installed with Angular, similarly NPM is automatically installed with Node)
你一定已经了解了Angular中Observable和Subscribe的基本概念。
项目结构:它将看起来像这样
创建Observable最常见和最简单的方法:创建Observable最常见和最简单的方法是使用RxJs库提供的方法。它是一个第三方库,当你创建一个新的angular项目时,它会自动安装。其中一个方法是fromEvent。我们将在后面讨论其他的方法,如Interval和Timer。
FromEvent: FromEvent是RxJs提供的一种方法,用于创建Observable。最重要的是,我们可以直接从DOM事件中创建Observable。通过DOM事件,它意味着点击事件、按键事件、滚动事件等,也就是一个简单的鼠标点击,我们可以创建一个数据流,即一个Observable。FromEvent将帮助我们实现这一点。
语法:
fromEvent(target,eventName)
.subscribe((res)=>{console.log(res)})
让我们来谈谈这两个参数。
target :它可以是任何DOM EventTarget,如按钮、单选按钮、滑块等。无论我们使用什么DOM事件目标,它都应该有方法来注册/取消注册事件处理程序。我们上面讨论的元素是内建的机制。我们不需要为此写代码。
eventName:它是我们想要监听的事件类型。
例子 。点击,mousedown,mouseup,点击,dblclick,mousemove,mouseover,mousewheel,mouseout,touchstart,touchmove,touchchend,touchcancel,keydown,keypress,keyup等。
方法:我们将在用户界面上创建一个简单的按钮 “添加图书”,每点击一次这个按钮,我们将创建一个数据流。为了保持简单,我们的数据流将只包含一个硬编码的字符串,即 “书”。随着每一次点击,我们将不断地生成Book 1、Book 2、Book 3,以此类推。为了在用户界面上显示这个数据流,我们将创建一个空的数据流
<
ul>,并不断地将每一本书作为一个列表项加入,也就是<li> <ul>
在运行时加入。
准备工作:要从DOM元素触发的任何事件中创建一个可观察的事件,首先,我们需要获得一个对该DOM元素的引用。这可以用ViewChild和ElementRef来完成。所以,这个代码可以写成:。
- HTML:
<button #addBtn>Add</button>
@ViewChild(‘addBtn’, {static: true}) addBtn: ElementRef;
这里this.addBtn.nativeElement返回本地DOM元素。这将是我们的目标(准确地说,是EventTarget),它是fromEvent方法的第一个参数。第二个参数是 “点击”,因为我们使用的是一个按钮点击。因此,代码变成了。
fromEvent(this.addBtn.nativeElement, 'click')
.subscribe((res)=>{console.log(res)}
一个小问题出现了!我们应该把这行代码放在哪里?
那么,最好的地方是ngAfterViewInit。这是因为ViewChild不会初始化addBtn元素,除非ngOnInit完成。因此,我们将把这段代码放在ngAfterViewInit中,因为从优先级上讲,ngOnInit是组件加载时第一个要执行的方法。
ngAfterViewInit() {
fromEvent(this.addBtn.nativeElement, 'click')
.subscribe((res) => {
console.log(res);
})
}
如果我们点击这个按钮,我们会在控制台得到这个结果。
所有这些都是我们点击按钮时产生的数据流。
让我们开始把它转换为工作代码。
- 第1步:创建一个新的Angular项目
ng new observable-app
- 第2步:创建一个名为FromEventComponent的组件
ng g c from-event
4个新文件应该被创建,app.module.ts应该被更新。
所有需要的文件和修改
- 第3步:创建一个服务PrintService
ng g s print-service
我们可以不使用服务,但要使我们的代码更加动态和有意义。让我们使用一个服务。这正在进行中。现在让我们做一些必要的修改来使它发挥作用。
<!-- To display the data/stream on
UI we will keep on adding each stream
as a list item in ul below -->
<ul id="elementContainer"></ul>
<!-- Button which will create a stream -->
<button #addBtn>Add Book</button>
printStream(containerName, stream) {
let element = document.createElement('li');
element.innerText = stream;
document.getElementById(containerName).appendChild(element);
}
因为我们已经创建了一个名为printStream的方法。它将接受两个参数。第一个参数是DOM元素,其中数据将被追加,第二个参数是我想追加的数据或流。现在我们可以把这个服务注入组件并使用这个方法。
ngAfterViewInit() {
let count = 1;
fromEvent(this.addBtn.nativeElement, "click")
.subscribe((res) => {
this._printService.printStream(
"elementContainer", "Book " + count++);
})
}
我们已经采取了一个计数变量来区分流。它将不断增加自动递增的整数 “Book”。在这里,在 “this._printService.printStream(‘elementContainer’, ‘Book’ + count++) “这一行,我们正在告诉要追加的地方和要追加的内容。
Final 代码:
<!-- To display the data/stream
on UI we will keep on adding
each stream as a list item in
ul below -->
<ul id="elementContainer"></ul>
<!--Button which will create a stream-->
<button #addBtn>Add Book</button>
import { Component, ElementRef, OnInit, ViewChild } from "@angular/core";
import { fromEvent } from "rxjs";
import { PrintServiceService } from "../print-service.service";
@Component({
selector: "app-from-event",
templateUrl: "./from-event.component.html",
styleUrls: ["./from-event.component.css"],
})
export class FromEventComponent implements OnInit {
@ViewChild("addBtn", { static: true }) addBtn: ElementRef;
constructor(private _printService: PrintServiceService) {}
ngOnInit() {}
ngAfterViewInit() {
let count = 1;
fromEvent(this.addBtn.nativeElement, "click").subscribe((res) => {
this._printService.printStream("elementContainer", "Book " + count++);
});
}
}
import { Injectable } from "@angular/core";
@Injectable({
providedIn: "root",
})
export class PrintServiceService {
constructor() {}
printStream(containerName, stream) {
// Creating li element in run time
let element = document.createElement("li");
element.innerText = stream;
// Appending li to ul
document.getElementById(containerName).appendChild(element);
}
}
...
<app-from-event></app-from-event>
输出:你可以看到每一次鼠标点击都有流被处理。在接下来的文章中,我们将学习间隔和定时器。这只不过是创建Observable的另一种方式,增加了一些设施。希望这有帮助。