HTML原生不支持Observable,需通过CDN引入RxJS(如
引入后全局会挂载
rxjs
对象,所有操作符和创建函数都从它取,例如:
rxjs.Observable.create()
创建自定义流
rxjs.fromEvent(document, 'click')
将 DOM 事件转为流
rxjs.interval(1000)
创建每秒发射一次的数字流
注意:RxJS 7+ 默认导出是模块化结构,CDN UMD 版才提供全局
rxjs
命名空间;若用 ESM 方式(
type="module"
),需改用
import { fromEvent } from 'https://cdn.skypack.dev/rxjs@7'
。
立即学习
“
前端免费学习笔记(深入)
”;
如何把点击、输入等 DOM 事件转成 Observable 流
fromEvent
是最常用的桥接函数,但它对目标元素有要求:必须在调用时已存在于 DOM 中,否则监听失败(不会报错,但永远收不到值)。
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
✅ 正确做法:确保元素已挂载,或在
DOMContentLoaded
后执行
❌ 常见错误:在
中脚本立即调用
fromEvent(document.getElementById('btn'), 'click')
,此时
#btn
还未解析
⚠️ 注意事件对象类型:
fromEvent(inputEl, 'input')
发出的是原生
InputEvent
,要取值得写
ev.target.value
,不是直接发字符串
示例:监听按钮点击并打印次数
const btn = document.getElementById('my-btn');
const clicks$ = rxjs.fromEvent(btn, 'click');
clicks$.pipe(
rxjs.operators.scan(acc => acc + 1, 0)
).subscribe(count => console.log('已点击', count, '次'));
为什么不能直接 new Observable() 监听 input 输入?
可以
new rxjs.Observable()
,但手动实现防抖、取值、取消订阅等逻辑非常容易出错。比如:
没调用
observer.complete()
或没清理
addEventListener
,会导致内存泄漏
连续快速输入时,若没加
debounceTime
,会触发大量无意义计算
input
事件在中文输入法下行为异常(按下拼音键就触发),应优先用
fromEvent(el, 'input')
+
map
+
filter
过滤空值
更稳妥的做法是组合现成操作符:
const input$ = rxjs.fromEvent(inputEl, 'input').pipe(
rxjs.operators.map(ev => ev.target.value),
rxjs.operators.filter(val => val.trim().length > 0),
rxjs.operators.debounceTime(300)
);
Observable 订阅后不自动销毁?小心内存泄漏
DOM 元素被移除、页面跳转、组件卸载时,如果 Observable 还在持续发射(如
interval
、
fromEvent
绑定在 document 上),而你没主动
unsubscribe()
,就会导致闭包引用无法释放。
显式保存订阅:
const sub = source$.subscribe(...); sub.unsubscribe();
推荐用
takeUntil
配合“销毁信号”流,例如:
fromEvent(btn, 'click').pipe(takeUntil(fromEvent(window, 'beforeunload')))
框架中(如 Angular)可依赖
async
管道自动管理;纯 HTML 场景只能自己记、自己清
特别提醒:
fromEvent
返回的 Observable 在订阅者取消时,
不会自动移除事件监听器
——这是 RxJS 的设计,必须靠操作符(如
take(1)
、
first()
)或手动
unsubscribe
触发清理。