響應式編程實戰(zhàn)——新版RxJS實現(xiàn)真正雙擊事件流

響應式編程是一種思想迁霎,是一種模式肉盹,就像 if else 和 for while 一樣烹看,是所有編程語言的基本單元国拇。為什么會這樣類比?因為現(xiàn)在基本所有的編程語言都有了自己的 Rx 實現(xiàn)惯殊,比如 RxJava, Rx.Net, RxJS, RxGo, RxDart等等酱吝,至少我們常用的語言都有自己的 Rx。再舉個例子土思,比如斐波那契數(shù)列的實現(xiàn)和編程語言無關對么变逃?不同點就是各語言的 if 語句雹食、for 循環(huán)語句等等的寫法有不同恢着。Rx 也一樣染乌,比如我使用 RxJS 實現(xiàn)了按鈕的雙擊操作慎陵,我可以把代碼拷貝到 Java 中陋葡,修改一下操作符的名稱谭企,使用方式就好了祠墅。

響應式編程同樣也是實現(xiàn)組合式編程和積木式編程的最佳實踐冻璃。使用的越多响谓,你才能體會響應式編程的強大和美妙之處。理論是根基省艳,實戰(zhàn)才有價值娘纷,下面我們就來看看如何用 RxJS 實現(xiàn)按鈕的雙擊效果。

雖然 DOM 中已經(jīng)有了雙擊事件類型跋炕,作為練習赖晶,讓我們假設只有單擊事件可以使用。

如果不使用 RxJS 我們將會怎么做辐烂?

  1. counter 變量計數(shù)
  2. addEventListener 注冊單擊事件
  3. setTimeout 來判斷時間間隔遏插。

讓我們看看 RxJS 如何實現(xiàn)。我們知道 Rx 是事件流纠修,單擊事件流可以想象成從一根管子胳嘲,單擊事件可以想象成一個珠子,一發(fā)生單擊事件扣草,這個珠子就從管子的一頭流入了牛,從另一頭流出颜屠。像下面這樣:

e----

-e---

--e--

---e-

----e

下面看看怎么用 RxJS 實現(xiàn)這根管子:

如何使用單擊事件流實現(xiàn)雙擊事件流呢?管子好說鹰祸,關鍵是里面的珠子甫窟。這里要用到 4 個 RxJS 操作符。先簡要說下操作符蛙婴。我覺得操作符可以類比為中間件蕴坪,攔截函數(shù)等等,后臺同學好理解敬锐,前臺同學不理解的話可以去看看 koa 框架背传。操作符接收一根管子,監(jiān)控管子里的珠子并做完操作台夺,然后重新生成一根管子径玖,里面存放操作完的珠子。

throttleTime:throttle 的中文翻譯是節(jié)流閥的意思颤介。它的參數(shù)是一段時間梳星。它的作用在時間參數(shù)范圍內(nèi)的珠子可以過,時間一到閥門就關上了滚朵,誰也過不去了冤灾。當?shù)谝粋€珠子經(jīng)過它時,它就開始計時辕近。

buffer:它的參數(shù)是一個事件流或者說管子韵吨。它的作用是收集這根管子流出的珠子,放進一個袋子里移宅,這個袋子就是數(shù)組归粉。

map:對經(jīng)過它的珠子做處理。

filter:對經(jīng)過它的珠子做過濾漏峰,滿足要求的珠子才能過去糠悼。

下面是實現(xiàn):

import React, { useRef, useEffect } from "react";

import { fromEvent } from "rxjs";
import { buffer, filter, map, throttleTime } from "rxjs/operators";

// throttleTime 操作符的第二個參數(shù),其實默認值也是 async浅乔,那為什么還要傳入呢倔喂?因為假如你有三個參數(shù),傳入了第一個和第三個靖苇,第二個就必須傳了席噩,js 無法忽略中間的參數(shù)不填。
import { async } from "rxjs/internal/scheduler/async"; 

export default function App() {
  const btnRef = useRef(null);

  // 這個是 throttleTime 操作符的第三個參數(shù)顾复,默認值 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 (
    <div className="App">
      <button ref={btnRef}>我是一個按鈕</button>
    </div>
  );
}

解釋說明:

  1. 快速地在按鈕上點擊兩次芯砸,將產(chǎn)生兩個珠子萧芙,也就是 btnClick$ 事件流里面有兩個 click 事件给梅。
  2. 我們把這根管子交給了 buffer 操作符,然而 buffer 對這根管子不感興趣双揪,它需要另外一個管子动羽;這另外一根管子也是基于單擊事件流生成的,只不過加了個閥門渔期,里面有個定時器运吓,當你第一次 click 的時候,定時器開始計時疯趟,計時期間的 click 事件都可以進到管子里拘哨;當定時器停止時,click 事件將無法進到管子里信峻。定時器歸零倦青,直到你又一次 click 再開始計時。
  3. 我們把上一步的管子交給了 buffer盹舞,buffer 把這根管子里的珠子放進袋子产镐,也就是數(shù)組中。比如交給 buffer 之前的管子里有兩個珠子踢步,交給 buffer 之后癣亚,buffer 把這倆數(shù)字放進了袋子,放進了一根新管子获印。
  4. 這一步 map 操作符拿到了管子述雾,它算出袋子里的珠子數(shù)量,放到另一根新管子里蓬豁,新管子里放的就是珠子的數(shù)量绰咽。
  5. filter 操作符拿到前面?zhèn)鬟^來的管子,它對里面的數(shù)字有意見地粪,不等于 2 的都扔了,把等于 2 的放進了另一根管子琐谤,傳遞下去蟆技。
  6. 這一步?jīng)]有操作符了,因此 filter 返回的管子給了 btnDblClick$ 變量保存斗忌。

綜上质礼,只要 btnDlbClick$ 流出的事件,就是雙擊事件织阳,明白了嗎眶蕉?不明白請關注微信公眾號“讀一讀我”哦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末唧躲,一起剝皮案震驚了整個濱河市造挽,隨后出現(xiàn)的幾起案子碱璃,更是在濱河造成了極大的恐慌,老刑警劉巖饭入,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嵌器,死亡現(xiàn)場離奇詭異,居然都是意外死亡谐丢,警方通過查閱死者的電腦和手機爽航,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乾忱,“玉大人讥珍,你說我怎么就攤上這事≌粒” “怎么了串述?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寞肖。 經(jīng)常有香客問我纲酗,道長,這世上最難降的妖魔是什么新蟆? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任觅赊,我火速辦了婚禮,結(jié)果婚禮上琼稻,老公的妹妹穿的比我還像新娘吮螺。我一直安慰自己,他們只是感情好帕翻,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布鸠补。 她就那樣靜靜地躺著,像睡著了一般嘀掸。 火紅的嫁衣襯著肌膚如雪紫岩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天睬塌,我揣著相機與錄音泉蝌,去河邊找鬼。 笑死揩晴,一個胖子當著我的面吹牛勋陪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播硫兰,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼诅愚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了劫映?” 一聲冷哼從身側(cè)響起违孝,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤刹前,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后等浊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腮郊,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年筹燕,在試婚紗的時候發(fā)現(xiàn)自己被綠了轧飞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡撒踪,死狀恐怖过咬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情制妄,我是刑警寧澤掸绞,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站耕捞,受9級特大地震影響衔掸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俺抽,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一敞映、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧磷斧,春花似錦振愿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至侣颂,卻和暖如春档桃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背横蜒。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工胳蛮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丛晌。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像斗幼,于是被迫代替她去往敵國和親澎蛛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350