成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊MobX 上手指南

開發 前端
之前用 Redux 比較多,一直聽說 Mobx 能讓你體驗到在 React 里面寫 Vue 的感覺,今天打算嘗試下 Mobx 是不是真的有寫 Vue 的感覺。

[[378343]]

之前用 Redux 比較多,一直聽說 Mobx 能讓你體驗到在 React 里面寫 Vue 的感覺,今天打算嘗試下 Mobx 是不是真的有寫 Vue 的感覺。

題外話

在介紹 MobX 的用法之前,先說點題外話,我們可以看一下 MobX 的中文簡介。在 MobX 的中文網站上寫著:

“MobX 是一個經過戰火洗禮的庫,它通過透明的函數響應式編程使得狀態管理變得簡單和可擴展。

數據流

“戰火洗禮的庫” 怎么看都感覺很奇怪,讀起來很拗口??,而且網上很多介紹 MobX 的文章都是這么寫的,在 github 翻閱其 README 發現寫的是:

“MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP).

可以看到作者原本要表達的意思是 MobX 是經過了許多的測試,擁有比較強的健壯性。下面是通過谷歌翻譯的結果,看起來也比中文網的表達要準確一些。

谷歌翻譯

雖然,我的英文水平也很菜,還是會盡量看官方的文檔,這樣可以避免一些不必要的誤解。

如何使用?

言歸正傳,MobX 現在的最新版是 6.0,這個版本的 API 相比于之前有了極大的簡化,可以說更加好用了。之前的版本是裝飾器風格的語法糖,但是裝飾器在現在的 ES 規范中并不成熟,而且引入裝飾器語法也在增加打包后的代碼體積。綜合考慮后,MobX 6.0 取消了裝飾器語法的 API。

響應式對象

MobX 通過 makeObservable 方法來構造響應式對象,傳入的對象屬性會通過 Proxy 代理,與 Vue 類似,在 6.0 版本之前使用的是 Object.defineProperty API,當然 6.0 也提供了降級方案。

  1. import { configure, makeObservable, observable, action, computed } from 'mobx' 
  2.  
  3. // 使用該配置,可以將 Proxy 降級為 Object.defineProperty 
  4. configure({ useProxies: "never" }); 
  5.  
  6. // 構造響應對象 
  7. const store = makeObservable( 
  8.   // 需要代理的響應對象 
  9.   { 
  10.     count: 0, 
  11.     get double() { 
  12.       return this.count * 2 
  13.     }, 
  14.     increment() { 
  15.       this.count += 1 
  16.     }, 
  17.     decrement() { 
  18.       this.count -= 1 
  19.     } 
  20.   }, 
  21.   // 對各個屬性進行包裝,用于標記該屬性的作用 
  22.   { 
  23.     count: observable, // 需要跟蹤的響應屬性 
  24.     double: computed,  // 計算屬性 
  25.     increment: action, // action 調用后,會修改響應對象 
  26.     decrement: action, // action 調用后,會修改響應對象 
  27.   } 

我們在看看之前版本的 MobX,使用裝飾器的寫法:

  1. class Store { 
  2.   @observable count = 0 
  3.   constructor() { 
  4.     makeObservable(this) 
  5.   } 
  6.   @action increment() { 
  7.     this.count++; 
  8.   } 
  9.   @action decrement() { 
  10.     this.count--; 
  11.   } 
  12.   @computed get double() { 
  13.     return this.count * 2 
  14.   } 
  15.  
  16. const store = new Store() 

這么看起來,好像寫法并沒有得到什么簡化,好像比寫裝飾器還要復雜點。下面我們看看 6.0 版本一個更強大的 API:makeAutoObservable。

makeAutoObservable 是一個更強大的 makeObservable,可以自動為屬性加上對象的包裝函數,上手成本直線下降。

  1. import { makeAutoObservable } from 'mobx' 
  2.  
  3. const store = makeAutoObservable({ 
  4.   count: 0, 
  5.   get double() { 
  6.     return this.count * 2 
  7.   }, 
  8.   increment() { 
  9.     this.count += 1 
  10.   }, 
  11.   decrement() { 
  12.     this.count -= 1 
  13.   } 
  14. }) 

計算屬性

MobX 的屬性與 Vue 的 computed 一樣,在 makeAutoObservable 中就是一個 getter,getter 依賴的值一旦發生變化,getter 本身的返回值也會跟隨變化。

  1. import { makeAutoObservable } from 'mobx' 
  2.  
  3. const store = makeAutoObservable({ 
  4.   count: 0, 
  5.   get double() { 
  6.     return this.count * 2 
  7.   } 
  8. }) 

當 store.count 為 1 時,調用 store.double 會返回 2。

修改行為

當我們需要修改 store 上的響應屬性時,我們可以通過直接重新賦值的方式修改,但是這樣會得到 MobX 的警告??。

  1. const store = makeAutoObservable({ 
  2.   count: 0 
  3. }); 
  4.  
  5. document.getElementById("increment").onclick = function () { 
  6.   store.count += 1 

warn

MobX 會提示,在修改響應式對象的屬性時,需要通過 action 的方式修改。雖然直接修改也能生效,但是這樣會讓 MobX 狀態的管理比較混亂,而且將狀態修改放到 action 中,能夠讓 MobX 在內部的事務流程中進行修改,以免拿到的某個屬性還處于中間態,最后計算的結果不夠準確。

makeAutoObservable 中的所有方法都會被處理成 action。

  1. import { makeAutoObservable } from 'mobx' 
  2.  
  3. const store = makeAutoObservable({ 
  4.   count: 0, 
  5.   get double() { 
  6.     return this.count * 2 
  7.   }, 
  8.   increment() { // action 
  9.     this.count += 1 
  10.   }, 
  11.   decrement() { // action 
  12.     this.count -= 1 
  13.   } 
  14. }) 

不同于 Vuex,將狀態的修改劃分為 mutation 和 action,同步修改放到 mutation 中,異步的操作放到 action 中。在 MobX 中,不管是同步還是異步操作,都可以放到 action 中,只是異步操作在修改屬性時,需要將賦值操作放到 runInAction 中。

  1. import { runInAction, makeAutoObservable } from 'mobx' 
  2.  
  3. const store = makeAutoObservable({ 
  4.   count: 0, 
  5.   async initCount() { 
  6.     // 模擬獲取遠程的數據 
  7.     const count = await new Promise((resolve) => { 
  8.       setTimeout(() => { 
  9.         resolve(10) 
  10.       }, 500) 
  11.     }) 
  12.     // 獲取數據后,將賦值操作放到 runInAction 中 
  13.     runInAction(() => { 
  14.       this.count = count 
  15.     }) 
  16.   } 
  17. }) 
  18.  
  19. store.initCount() 

如果不調用 runInAction ,則可以直接調用本身已經存在的 action。

  1. import { runInAction, makeAutoObservable } from 'mobx' 
  2.  
  3. const store = makeAutoObservable({ 
  4.   count: 0, 
  5.   setCount(count) { 
  6.     this.count = count 
  7.   }, 
  8.   async initCount() { 
  9.     // 模擬獲取遠程的數據 
  10.     const count = await new Promise((resolve) => { 
  11.       setTimeout(() => { 
  12.         resolve(10) 
  13.       }, 500) 
  14.     }) 
  15.     // 獲取數據后,調用已有的 action 
  16.     this.setCount(count
  17.   } 
  18. }) 
  19.  
  20. store.initCount() 

監聽對象變更

無論是在 React 還是在小程序中想要引入 MobX,都需要在對象變更的時候,通知調用原生的 setState/setData 方法,將狀態同步到視圖上。

通過 autorun 方法可以實現這個能力,我們可以把 autorun 理解為 React Hooks 中的 useEffect。每當 store 的響應屬性發生修改時,傳入 autorun 的方法(effect)就會被調用一次。

  1. import { autorun, makeAutoObservable } from 'mobx' 
  2.  
  3. const store = makeAutoObservable({ 
  4.   count: 0, 
  5.   setCount(count) { 
  6.     this.count = count 
  7.   }, 
  8.   increment() { 
  9.     this.count++ 
  10.   }, 
  11.   decrement() { 
  12.     this.count-- 
  13.   } 
  14. }) 
  15.  
  16. document.getElementById("increment").onclick = function () { 
  17.   store.count++ 
  18.  
  19. const $count = document.getElementById("count"
  20. $count.innerText = `${store.count}` 
  21. autorun(() => { 
  22.   $count.innerText = `${store.count}` 
  23. }) 

每當 button#increment 按鈕被點擊的時候,span#count 內的值就會自動進行同步。??查看完整代碼。

效果演示

除了 autorun ,MobX 還提供了更精細化的監聽方法:reaction、 when。

  1. const store = makeAutoObservable({ 
  2.   count: 0, 
  3.   setCount(count) { 
  4.     this.count = count 
  5.   }, 
  6.   increment() { 
  7.     this.count++ 
  8.   }, 
  9.   decrement() { 
  10.     this.count-- 
  11.   } 
  12. }) 
  13.  
  14. // store 發生修改立即調用 effect 
  15. autorun(() => { 
  16.   $count.innerText = `${store.count}` 
  17. }); 
  18.  
  19. // 第一個方法的返回值修改后才會調用后面的 effect 
  20. reaction( 
  21.   // 表示 store.count 修改后才會調用 
  22.   () => store.count
  23.   // 第一個參數為當前值,第二個參數為修改前的值 
  24.   // 有點類似與 Vue 中的 watch 
  25.   (value, prevValue) => { 
  26.     console.log('diff', value - prevValue) 
  27.   } 
  28. ); 
  29.  
  30. // 第一個方法的返回值為真,立即調用后面的 effect 
  31. when(() => store.count > 10, () => { 
  32.   console.log(store.count
  33. }) 
  34. // when 方法還能返回一個 promise 
  35. (async function() { 
  36.   await when(() => store.count > 10) 
  37.   console.log('store.count > 10'
  38. })() 

總結

MobX 的介紹到這里就結束了,本文只是大致的列舉了一下 MobX 的 API,希望大家能有所收獲。后續打算再深入研究下 MobX 的實現,等我研究好了,再寫篇文章來分享。

 

責任編輯:武曉燕 來源: 更了不起的前端
相關推薦

2025-05-28 15:46:13

2014-06-24 09:41:56

Android Stu教程

2024-01-29 00:36:50

Backstage設施工具

2016-06-20 10:20:22

Docker云計算

2014-01-22 10:00:10

Android SDKAndroid開發

2021-11-26 09:40:37

EclipseIDEA開發

2013-12-04 13:27:56

Android SDK項目

2013-12-26 15:40:33

Android SDK項目

2013-12-04 14:44:41

Android SDK用戶交互

2014-06-06 14:25:03

iOS 8SwiftWWDC2014

2013-12-26 15:14:38

Android SDK運行調試

2012-08-01 17:39:17

2021-01-19 06:16:05

前端Babel 技術熱點

2013-12-26 14:52:52

Android SDK物理設備

2013-12-04 14:29:18

Android SDK應用程序

2013-12-26 15:47:59

Android SDK應用程序

2013-11-27 10:12:11

2013-12-26 15:26:48

Android SDKActivity生命周期

2021-02-24 08:32:45

Web Compone前端Web 應用

2013-12-04 15:11:03

Android SDK應用程序
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲国产精品suv | 亚洲精品一区在线 | 成人亚洲精品 | 日韩欧美中文 | 视频一区在线观看 | 亚洲在线视频 | 玖玖综合网 | 久久国产婷婷国产香蕉 | 国产欧美精品在线观看 | 一区二区三区国产精品 | 欧美精品在线一区 | 一区二区视频在线观看 | 毛片一级片 | 亚洲精品国产一区 | 一级高清视频 | 国产欧美精品一区二区 | 亚洲 中文 欧美 日韩 在线观看 | 在线成人免费视频 | 91视频在线观看免费 | 欧美在线播放一区 | 欧美日韩一区二区三区四区 | 日本不卡免费新一二三区 | av黄色在线观看 | 色欧美综合 | av资源网站 | 国产精品大片在线观看 | 99久久精品免费看国产四区 | 亚洲看片网站 | 午夜视频在线观看一区二区 | 国产福利视频 | 日韩精品一区二区三区四区视频 | 91精品国产综合久久精品 | 网络毛片 | 日韩一区二区在线观看 | 免费av手机在线观看 | 久久久资源 | 一区二区av | 91视视频在线观看入口直接观看 | 精品一区二区三区在线播放 | 无码日韩精品一区二区免费 | 欧美激情一区二区三区 |