MobX 上手指南,寫 Vue 的感覺?

之前用 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 也提供了降級方案。

import?{?configure,?makeObservable,?observable,?action,?computed?}?from?'mobx'//?使用該配置,可以將?Proxy?降級為?Object.defineProperty
configure({?useProxies:?"never"?});//?構造響應對象
const?store?=?makeObservable(//?需要代理的響應對象{count:?0,get?double()?{return?this.count?*?2},increment()?{this.count?+=?1},decrement()?{this.count?-=?1}},//?對各個屬性進行包裝,用于標記該屬性的作用{count:?observable,?//?需要跟蹤的響應屬性double:?computed,??//?計算屬性increment:?action,?//?action?調用后,會修改響應對象decrement:?action,?//?action?調用后,會修改響應對象}
)

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

class?Store?{@observable?count?=?0constructor()?{makeObservable(this)}@action?increment()?{this.count++;}@action?decrement()?{this.count--;}@computed?get?double()?{return?this.count?*?2}
}const?store?=?new?Store()

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

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

import?{?makeAutoObservable?}?from?'mobx'const?store?=?makeAutoObservable({count:?0,get?double()?{return?this.count?*?2},increment()?{this.count?+=?1},decrement()?{this.count?-=?1}
})

計算屬性

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

import?{?makeAutoObservable?}?from?'mobx'const?store?=?makeAutoObservable({count:?0,get?double()?{return?this.count?*?2}
})

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

修改行為

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

const?store?=?makeAutoObservable({count:?0
});document.getElementById("increment").onclick?=?function?()?{store.count?+=?1
}
warn

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

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

import?{?makeAutoObservable?}?from?'mobx'const?store?=?makeAutoObservable({count:?0,get?double()?{return?this.count?*?2},increment()?{?//?actionthis.count?+=?1},decrement()?{?//?actionthis.count?-=?1}
})

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

import?{?runInAction,?makeAutoObservable?}?from?'mobx'const?store?=?makeAutoObservable({count:?0,async?initCount()?{//?模擬獲取遠程的數據const?count?=?await?new?Promise((resolve)?=>?{setTimeout(()?=>?{resolve(10)},?500)})//?獲取數據后,將賦值操作放到?runInAction?中runInAction(()?=>?{this.count?=?count})}
})store.initCount()

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

import?{?runInAction,?makeAutoObservable?}?from?'mobx'const?store?=?makeAutoObservable({count:?0,setCount(count)?{this.count?=?count},async?initCount()?{//?模擬獲取遠程的數據const?count?=?await?new?Promise((resolve)?=>?{setTimeout(()?=>?{resolve(10)},?500)})//?獲取數據后,調用已有的?actionthis.setCount(count)}
})store.initCount()

監聽對象變更

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

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

import?{?autorun,?makeAutoObservable?}?from?'mobx'const?store?=?makeAutoObservable({count:?0,setCount(count)?{this.count?=?count},increment()?{this.count++},decrement()?{this.count--}
})document.getElementById("increment").onclick?=?function?()?{store.count++
}const?$count?=?document.getElementById("count")
$count.innerText?=?`${store.count}`
autorun(()?=>?{$count.innerText?=?`${store.count}`
})

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

效果演示

除了 autorun ,MobX 還提供了更精細化的監聽方法:reactionwhen

const?store?=?makeAutoObservable({count:?0,setCount(count)?{this.count?=?count},increment()?{this.count++},decrement()?{this.count--}
})//?store?發生修改立即調用?effect
autorun(()?=>?{$count.innerText?=?`${store.count}`
});//?第一個方法的返回值修改后才會調用后面的?effect
reaction(//?表示?store.count?修改后才會調用()?=>?store.count,//?第一個參數為當前值,第二個參數為修改前的值//?有點類似與?Vue?中的?watch(value,?prevValue)?=>?{console.log('diff',?value?-?prevValue)}
);//?第一個方法的返回值為真,立即調用后面的?effect
when(()?=>?store.count?>?10,?()?=>?{console.log(store.count)
})
//?when?方法還能返回一個?promise
(async?function()?{await?when(()?=>?store.count?>?10)console.log('store.count?>?10')
})()

總結

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


最近組建了一個江西人的前端交流群,如果你也是江西人可以加我微信ruochuan12 拉你進群。


常駐推薦閱讀

若川知乎高贊:有哪些必看的 JS庫?
我在阿里招前端,我該怎么幫你?(現在還可以加模擬面試群)
如何拿下阿里巴巴 P6 的前端 Offer
如何準備阿里P6/P7前端面試--項目經歷準備篇
大廠面試官常問的亮點,該如何做出?
如何從初級到專家(P4-P7)打破成長瓶頸和有效突破
若川知乎問答:2年前端經驗,做的項目沒什么技術含量,怎么辦?

常駐末尾

你好,我是若川,江西人~(點擊藍字了解我)歷時一年只寫了一個學習源碼整體架構系列?有哪些必看的JS庫:jQuery、underscore、lodash、sentry、vuex、axios、koa、redux

  1. 關注若川視野,回復"pdf" 領取優質前端書籍pdf,回復"1",可加群長期交流學習

  2. 我的博客地址:https://lxchuan12.gitee.io?歡迎收藏

  3. 覺得文章不錯,可以?分享、點贊、在看?呀^_^另外歡迎留言交流~

小提醒:若川視野公眾號面試、源碼等文章合集在菜單欄中間【源碼精選】按鈕,歡迎點擊閱讀,也可以星標我的公眾號,便于查找

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276150.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276150.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276150.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ansible中yaml語法應用

4、yaml語法應用 ansible的playbook編寫是yaml語言編寫,掌握yaml語法是編寫playbook的必要條件,格式要求和Python相似,具體教程參考如下yaml語言教程 附上一個yaml文件轉js格式文件鏈接在線免費yaml內容轉json格式 4.1、 ansible中的yaml語法…

中興a2018拆機圖片_中興天機拆機步驟詳解【圖文】

中興天機上市時有兩款,黑色和白色。黑色的缺點是外觀過于傳統,并不是很適合年輕人使用,但是其推出白色款卻很好的解決了這個問題。中興天機的整體性質與性價比完美的拼過了 小米 3等同時上線的手機產品。中興天機價格在1799左右,小…

網絡視頻貼片廣告全面推行第三方監測

視頻網站優酷與國際調研機構尼爾森聯合對外宣布:針對優酷視頻貼片廣告全面推行第三方監測。這是視頻行業首次倡導廣告投放數據透明化的一大舉措。  近年來,網絡視頻已經成為廣告主營銷的一大選擇。隨著廣告主投放額度不斷加大,廣告主對視頻…

css3動畫事件—webkitAnimationEnd

轉載鏈接:http://www.jb51.net/css/72443.html 用css3的animation完成一個動畫,當只有這個動畫完成時才執行令一個事件,比如讓動畫保持在終止的狀態或其他一些事件。我們該怎么辦呢。 第一種方法: 用計時器,設定一個…

(送書和紅包)快人一步,掌握前端函數式編程

大家好,我是若川。上周末送出了3本新書和若干紅包,抽獎名單已公布。本周又爭取到了4本《前端函數式編程》書籍包郵送給大家,抽獎規則見文末,與以往不同的是除了關鍵詞、留言、在看抽獎外,還有最早關注獎,歡…

js split參數為無效字符_js使用split函數按照多個字符對字符串進行分割的方法

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":5,"count":5}]},"card":[{"des":"阿里云函數計算(Function Compute)是一個事件…

Windows下訪問VirtualBox的mysql服務

由于好長時間沒有在windows下使用mysql,現在出現好多選項,而且使用sqlyog連接總是出現1045錯誤,所以在虛擬機Ubuntu下安裝mysql進行訪問,但是想用win下面vscode進行開發,就有了Windows下訪問VirtualBox的mysql服務的想…

JavaScript操作表格進行拖拽排序

<js-dodo-table- Drag and Drop JQuery plugin>以上插件可對table進行排序&#xff0c;拖動&#xff01; 例如有下面一個樣子的id為table的表格&#xff1a; <table id"table"cellspacing"0"cellpadding"2"><tr id"1"…

UBUNTU 用戶及用戶組管理 修改用戶和主機名

轉載鏈接&#xff1a;http://blog.sina.com.cn/s/blog_66439a3e0101dm1g.html 一、用戶及用戶組管理 創建組&#xff1a; $sudo addgroup ccache 創建用戶&#xff1a; $sudo useradd ccache -g ccache -M 創新wfz用戶并創建HOME目錄&#xff0c;指定用戶組為ccache $sudo u…

ping -a 獲取不到主機名_網絡測試命令——PING

命令功能&#xff1a;Linux系統和windows系統的ping命令是常用的網絡命令&#xff0c;它通常用來測試與目標主機的連通性&#xff0c;這樣我們就可以根據它ping輸出的信息來確定目標主機是否可訪問(但這不是絕對的)。有些服務器為了防止通過ping探測到&#xff0c;通過防火墻設…

寫在2021: 值得關注/學習的前端框架和工具庫

前言最近在知乎看到了這么個問題&#xff1a;學完Vue還有必要學習React和Node嗎&#xff1f;[1]&#xff0c; 有很奇妙的感覺&#xff0c;因為我在最開始入門前端時&#xff0c;也是以Vue入的門&#xff0c;在“學完”Vue之后&#xff0c; 我也有了這個疑問&#xff0c;但當時的…

萬物互聯之~RPC專欄

3.RPC引入 上篇回顧&#xff1a;萬物互聯之~深入篇 Code&#xff1a;https://github.com/lotapp/BaseCode/tree/master/python/6.net/6.rpc/ 其他專欄最新篇&#xff1a;協程加強之~兼容答疑篇 | 聊聊數據庫~SQL環境篇 3.1.概念 RPC(Remote Procedure Call)&#xff1a;分布式系…

python判斷字符大小寫轉換_Python 字符串大小寫轉換的簡單實例

①所有字母都轉換為大寫# -*- coding:utf-8 -*-if __name__ "__main__":a hello, world!print(a.upper())輸出&#xff1a;HELLO, WORLD!②所有字母都轉換為小寫# -*- coding:utf-8 -*-if __name__ "__main__":a HELLO, WORLD!print(a.lower())輸出&am…

正則表達式如何匹配正反斜杠

轉載鏈接&#xff1a;http://wiki.ubuntu.org.cn/Python%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97#.E5.8F.8D.E6.96.9C.E6.9D.A0.E7.9A.84.E9.BA.BB.E7.83.A6 反斜杠的麻煩 在早期規定中&#xff0c;正則表達式用反斜杠字符 ("…

前端進階必備Node.js,你得了解一下

作為前端開發&#xff0c;工作中肯定離不開 JavaScript &#xff0c;而 Node.js 是基于 JavaScript 語言和 V8 引擎的 Web 服務器項目&#xff0c;讓你可以直接使用 JavaScript 來搭架服務器。而且在 Node 環境下&#xff0c;通過模塊化的 JavaScript 代碼&#xff0c;加上函數…

Google推出“Google實驗室” Ad Innovations

4月1日消息&#xff0c;據國外媒體報道&#xff0c;Google近日推出了Ad Innovations功能&#xff0c;類似于“Google實驗室”&#xff0c;但專門用于展示最新的廣告技術、方案等&#xff0c;并征求廣告主的反饋。 目前Ad Innovations已有數款新功能&#xff0c;Google將按照反饋…

JS中utf8和GBK的字符編碼轉換

1、PHP中的 json_encode 函數只限編碼UTF-8的數據&#xff0c;當轉換GBK或者GB2312等編碼的數據時&#xff0c;會將漢字轉為NULL。 2、JavaScript 中json 的使用&#xff1a; ① 將對象轉為json字符串&#xff1a;JSON.stringify(obj)② 將json轉為對象&#xff1a;dataObj ev…

tcptracerte參數_TCP/IP詳解學習筆記(4)-ICMP協議,ping和Traceroute【轉】

1.IMCP協議介紹前面講到了&#xff0c;IP協議并不是一個可靠的協議&#xff0c;它不保證數據被送達&#xff0c;那么&#xff0c;自然的&#xff0c;保證數據送達的工作應該由其他的模塊來完成。其中一個重要的模塊就是ICMP(網絡控制報文)協議。當傳送IP數據包發生錯誤&#xf…

[實踐系列]Promises/A+規范

前言 [實踐系列] 主要是讓我們通過實踐去加深對一些原理的理解。 實踐系列-前端路由 實踐系列-Babel原理 有興趣的同學可以關注 實踐系列 。 求star求follow~ 什么是Promise ? Promise是JS異步編程中的重要概念&#xff0c;異步抽象處理對象&#xff0c;是目前比較流行Javas…

Web Components 上手指南

現在的前端開發基本離不開 React、Vue 這兩個框架的支撐&#xff0c;而這兩個框架下面又衍生出了許多的自定義組件庫&#xff1a;Element&#xff08;Vue&#xff09;Ant Design&#xff08;React&#xff09;這些組件庫的出現&#xff0c;讓我們可以直接使用已經封裝好的組件&…