addeventlistener事件参数_响应式编程实战——新版RxJS实现真正双击事件流

13c76aefba121cf381935b9ecd958449.png

响应式编程是一种思想,是一种模式,就像 if else 和 for while 一样,是所有编程语言的基本单元。为什么会这样类比?因为现在基本所有的编程语言都有了自己的 Rx 实现,比如 RxJava, Rx.Net, RxJS, RxGo, RxDart等等,至少我们常用的语言都有自己的 Rx。再举个例子,比如斐波那契数列的实现和编程语言无关对么?不同点就是各语言的 if 语句、for 循环语句等等的写法有不同。Rx 也一样,比如我使用 RxJS 实现了按钮的双击操作,我可以把代码拷贝到 Java 中,修改一下操作符的名称,使用方式就好了。

响应式编程同样也是实现组合式编程和积木式编程的最佳实践。使用的越多,你才能体会响应式编程的强大和美妙之处。理论是根基,实战才有价值,下面我们就来看看如何用 RxJS 实现按钮的双击效果。

虽然 DOM 中已经有了双击事件类型,作为练习,让我们假设只有单击事件可以使用。

如果不使用 RxJS 我们将会怎么做?

  1. counter 变量计数
  2. addEventListener 注册单击事件
  3. setTimeout 来判断时间间隔。

让我们看看 RxJS 如何实现。我们知道 Rx 是事件流,单击事件流可以想象成从一根管子,单击事件可以想象成一个珠子,一发生单击事件,这个珠子就从管子的一头流入,从另一头流出。像下面这样:

e----

-e---

--e--

---e-

----e

下面看看怎么用 RxJS 实现这根管子:

ffe537ec99a5b97092b097b6050e6cb1.png

如何使用单击事件流实现双击事件流呢?管子好说,关键是里面的珠子。这里要用到 4 个 RxJS 操作符。先简要说下操作符。我觉得操作符可以类比为中间件,拦截函数等等,后台同学好理解,前台同学不理解的话可以去看看 koa 框架。操作符接收一根管子,监控管子里的珠子并做完操作,然后重新生成一根管子,里面存放操作完的珠子。

throttleTime:throttle 的中文翻译是节流阀的意思。它的参数是一段时间。它的作用在时间参数范围内的珠子可以过,时间一到阀门就关上了,谁也过不去了。当第一个珠子经过它时,它就开始计时。

buffer:它的参数是一个事件流或者说管子。它的作用是收集这根管子流出的珠子,放进一个袋子里,这个袋子就是数组。

map:对经过它的珠子做处理。

filter:对经过它的珠子做过滤,满足要求的珠子才能过去。

下面是实现:

import React, { useRef, useEffect } from "react";import { fromEvent } from "rxjs";import { buffer, filter, map, throttleTime } from "rxjs/operators";/*   throttleTime 操作符的第二个参数,其实默认值也是 async,那为什么还要传入呢?因为假如你有三个参数,传入了第一个和第三个,第二个就必须传了,js 无法忽略中间的参数不填。*/import { async } from "rxjs/internal/scheduler/async"; export default function App() {  const btnRef = useRef(null);  /*   这个是 throttleTime 操作符的第三个参数,默认值 leading 为 true,trailing 为 false  */  const throttleConfig = {    leading: false,    trailing: true  }  useEffect(() => {    const btnClick$ = fromEvent(btnRef.current, "click");    const throttled$ = btnClick$.pipe(throttleTime(250, async ,throttleConfig))    const btnDblClick$ = btnClick$.pipe(      buffer(throttled$),      map(arr => arr.length),      filter(len => len === 2),    );    const subscription = btnDblClick$.subscribe(() => {      console.log("双击啦");    });    return () => {      subscription.unsubscribe();    };  });  return (    
我是一个按钮
);}

解释说明:

  1. 快速地在按钮上点击两次,将产生两个珠子,也就是 btnClick$ 事件流里面有两个 click 事件。
  2. 我们把这根管子交给了 buffer 操作符,然而 buffer 对这根管子不感兴趣,它需要另外一根管子;这另外一根管子也是基于单击事件流生成的,只不过加了个阀门,里面有个定时器,当你第一次 click 的时候,定时器开始计时,计时期间的 click 事件都可以进到管子里;当定时器停止时,click 事件将无法进到管子里。定时器归零,直到你又一次 click 再开始计时。
  3. 我们把上一步的管子交给了 buffer,buffer 把这根管子里的珠子放进袋子,也就是数组中。比如交给 buffer 之前的管子里有两个珠子,交给 buffer 之后,buffer 把这俩数字放进了袋子,放进了一根新管子。
  4. 这一步 map 操作符拿到了管子,它算出袋子里的珠子数量,放到另一根新管子里,新管子里放的就是珠子的数量。
  5. filter 操作符拿到前面传过来的管子,它对里面的数字有意见,不等于 2 的都扔了,把等于 2 的放进了另一根管子,传递下去。
  6. 这一步没有操作符了,因此 filter 返回的管子给了 btnDblClick$ 变量保存。

综上,只要 btnDlbClick$ 流出的事件,就是双击事件,明白了吗?不明白请关注微信公众号“读一读我”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值