用 RxJS、RxWX 編寫更優秀的(de)微信小程序代碼 - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關 >

用 RxJS、RxWX 編寫更優秀的(de)微信小程序代碼

發表時(shí)間:2021-4-12

發布人(rén):融晨科技

浏覽次數:55

好的(de)代碼通常符合一個(gè)特點:高内聚,低耦合。

通俗地(dì / de)說(shuō)就(jiù)是(shì)用更少地(dì / de)代碼完成更多地(dì / de)功能,比如web前端地(dì / de)MVVM框架就(jiù)是(shì)把對DOM的(de)操作和(hé / huò)事件監聽抽象出(chū)來(lái),通過數據綁定來(lái)更新數據和(hé / huò)視圖。

“組件化”的(de)思想也(yě)是(shì)如此,組件的(de)目的(de)不(bù)是(shì)簡單的(de)代碼分割,更重要(yào / yāo)的(de)是(shì)方便代碼的(de)複用。

這(zhè)些都是(shì)針對視圖層面的(de)優化措施,針對數據層,其實也(yě)有方法寫出(chū)更優秀的(de)代碼。

其中一個(gè)簡單有效的(de)方法就(jiù)是(shì) 盡量編寫純函數。

純函數

什麽是(shì)純函數?可以(yǐ)用一個(gè)表達式來(lái)描述

輸入參數x => 執行代碼 => 輸出(chū)結果y

這(zhè)看起來(lái)好像和(hé / huò)普通函數也(yě)沒啥區别,那麽它和(hé / huò)普通的(de)函數相比,“純”在(zài)哪裏?

  • 從輸入來(lái)看,參數是(shì)必傳的(de),而(ér)且不(bù)能被修改。比如 Math.random 這(zhè)類沒有參數的(de)函數就(jiù)不(bù)是(shì)純函數。

  • 從執行來(lái)看,不(bù)能引用外部變量或函數。

  • 從結果來(lái)看,執行必有結果,而(ér)且輸入相同的(de)參數,執行的(de)結果必須相同。

純函數是(shì)将邏輯分離到(dào)極緻:一段功能單一,邏輯封閉的(de)代碼。

思考:function(x) { return 1 } 是(shì)不(bù)是(shì)純函數?

如果你的(de)代碼中使用純函數,會帶來(lái)以(yǐ)下好處:

  • 易測試。寫過單元測試的(de)前端開發都知道(dào),前端的(de)單元測試是(shì)很難寫的(de),其中很大(dà)一個(gè)原因就(jiù)是(shì)“不(bù)純”的(de)函數太多,一個(gè)函數可能既要(yào / yāo)操作DOM,又要(yào / yāo)發送ajax請求,還可能引用了(le/liǎo)不(bù)知名的(de)全局變量…AngularJS在(zài)官方文檔中就(jiù)直接指出(chū)有些耦合性高的(de)代碼是(shì)難以(yǐ)測試的(de),所以(yǐ)這(zhè)也(yě)是(shì)近些年MVVM框架流行的(de)原因,框架承擔了(le/liǎo)DOM操作,開發者隻負責寫邏輯,從而(ér)讓代碼邏輯更清晰。

  • 可複用。 使用Node.js編寫服務端的(de)同學對一個(gè)詞肯定熟悉——“同構”,也(yě)就(jiù)是(shì)說(shuō),一份js代碼可以(yǐ)同時(shí)在(zài)服務端和(hé / huò)浏覽器端正常運行,而(ér)純函數是(shì)支持同構的(de)。

  • 無副作用。比如多個(gè)不(bù)純的(de)函數同時(shí)修改一個(gè)變量(或操作一個(gè)DOM元素),再加上(shàng)異步等情況,這(zhè)樣就(jiù)很容易引起沖突。而(ér)純函數既不(bù)修改入參也(yě)不(bù)修改外部變量,所以(yǐ)完全不(bù)用擔心。

RxJS

符合純函數特點的(de)第三方開源庫有非常著名的(de)underscore和(hé / huò)lodash,以(yǐ)及更加強大(dà)的(de)RxJS。

RxJS是(shì)微軟推出(chū)的(de)ReactiveX系列(RxJava,Rx.NET,RxScala,RxSwift等)中的(de)一員,目前Github上(shàng)star數已經超過17k。

它可以(yǐ)用來(lái)優雅地(dì / de)處理異步和(hé / huò)事件。主要(yào / yāo)通過它的(de)核心類型 Observable,以(yǐ)及強大(dà)的(de)操作符 (map、filter、reduce、every等,其中大(dà)部分都是(shì)純函數)來(lái)實現。

官方給它最直白的(de)定義是(shì)

可以(yǐ)把 RxJS 當做是(shì)用來(lái)處理事件的(de) Lodash 。

來(lái)一段官方的(de)代碼體驗一下:

// 使用普通的(de) JavaScript 控制按鈕一秒鍾内隻允許點擊一次
var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', () => {
  if (Date.now() - lastClick >= rate) {
    console.log(`Clicked ${++count} times`);
    lastClick = Date.now();
  }
});

// 使用Rx.js實現
var button = document.querySelector('button');
Rx.Observable.fromEvent(button, 'click')
  .throttleTime(1000)
  .scan(count => count + 1, 0)
  .subscribe(count => console.log(`Clicked ${count} times`));

使用RxJS的(de)代碼消除了(le/liǎo)一些中間變量,使用操作符來(lái)分步執行邏輯,可讀性更強、耦合性更低,更方便測試和(hé / huò)修改。

關于(yú)RxJS更詳細介紹在(zài)以(yǐ)後的(de)文章中再叙,本文先談一談它的(de)應用。關于(yú)RxJS在(zài)web端和(hé / huò)node.js服務端的(de)應用都不(bù)乏文章,所以(yǐ)這(zhè)一次突破常規,來(lái)講一講在(zài)微信小程序(以(yǐ)下簡稱“小程序”)開發中的(de)使用。

小程序

直接在(zài)小程序中使用RxJS是(shì)會報錯的(de),所以(yǐ)我建立了(le/liǎo)一個(gè)開源項目來(lái)解決這(zhè)個(gè)問題:RxWX(項目地(dì / de)址:https://github.com/yalishizhude/RxJS )。

封裝了(le/liǎo)兩個(gè)js文件。

  • Rx.js。對Rx.js進行了(le/liǎo)一些修改使其能在(zài)小程序中運行。

  • RxWX.js。基于(yú)Rx.js對微信的(de)api進行了(le/liǎo)封裝,調用同名API不(bù)再使用回調,而(ér)是(shì)返回Observalbe對象。

安裝

提供兩種安裝途徑

Github

git clone https://github.com/yalishizhude/RxWX.git

可以(yǐ)直接下載項目,将根目錄的(de)Rx.js和(hé / huò)RxWX.js複制到(dào)小程序項目中,也(yě)可以(yǐ)訪問該網址複制粘貼這(zhè)兩個(gè)文件内容。

npm

npm i rxjs-wx

将node_modules/rxjs-wx目錄下的(de)Rx.js和(hé / huò)RxWX.js複制到(dào)小程序項目中。

使用

小程序的(de)API大(dà)多數都不(bù)是(shì)按照純函數的(de)思想設計的(de),把返回結果賦值給入參的(de)success、fail、complete屬性。

在(zài)邏輯簡單複雜的(de)情況下很容堕入“回調地(dì / de)獄”,而(ér)且同步和(hé / huò)異步的(de)接口調用方式也(yě)不(bù)一緻。而(ér)使用RxJS就(jiù)可以(yǐ)解決這(zhè)些問題,下面來(lái)看幾個(gè)例子(zǐ)。

處理回調

假設有這(zhè)樣一個(gè)需求,先通過 wx.getUserInfo 獲取用戶信息,然後傳給後端服務獲取該用戶其它信息,顯示在(zài)頁面上(shàng)。

// 普通代碼
let self = this
wx.getUserInfo({
  success: (res) => {
    wx.request({
      method: 'GET',
      url: 'xxx/user',
      data: res.userInfo,
      success(r) {
        self.setData({userInfo:r})
      },
      fail(e) {
        self.setData({userInfo:'not found'})
      }
    })
  },
  fail(e) {
    console.error(e)
  }
})

// 使用RxWX
import obs from './RxWX'

obs.getUserInfo()
  .catch(e => console.error(e))
  .switchMap(({ userInfo }) => obs.request({ method: 'GET', url: 'xxx/user', data: user }))
  .subscribe(userInfo => self.setData({ userInfo: r }), e => self.setData({ userInfo: 'not found' }))

處理事件

曾經在(zài)開發小程序的(de)時(shí)候使用navigator組件碰到(dào)一個(gè)比較嚴重的(de)問題:快速多次點擊的(de)時(shí)候會發生多次頁面跳轉,跳轉完成後需要(yào / yāo)多次點擊“返回”才能退回到(dào)原頁面。

爲(wéi / wèi)了(le/liǎo)解決這(zhè)個(gè)問題,一般可以(yǐ)手動綁定事件,然後進行一個(gè)防抖操作。

// 普通代碼
let tapping = false
...
tap(e) {
  if(!tapping) {
    wx.navigateTo({ url: '../demo/demo' })
    tapping = true
    setTimeout(() => tapping=false, 1000)
  }
}

// 使用RxWX
import obs from './RxWX'

tap(e) {
  obs.navigateTo({ url: '../demo/demo' })
  .debounce(1000)
  .subscribe()
}

其它

RxWX同時(shí)還支持wx對象的(de)其它非函數屬性,比如:

import obs from './RxWX'

console.log(obs.version) 
// {info:"", updateTime:"2017.7.10 19:35:05", version:"1.4.0"}

最後

RxJS和(hé / huò)RxWX是(shì)第三方庫,也(yě)是(shì)進入純函數世界的(de)大(dà)門,更是(shì)一種編寫更好代碼的(de)思維方式。


本文作者小程序聯盟社區博主 yalishizhude,搜索關注個(gè)人(rén)公衆号“web學習社”~

本文可被轉發或分享,但必須保留完整圖文信息和(hé / huò)出(chū)處,作者保留追究一切法律責任的(de)權利和(hé / huò)手段~ 

相關案例查看更多