React+Mobx基本使用、模塊化操作
Mobx介紹
1.什么是Mobx
一個(gè)可以和React良好配合的集中狀態(tài)管理工具,和Redux解決的問(wèn)題相似,都可以獨(dú)立組件進(jìn)行集中狀態(tài)管理
mobx與react的關(guān)系,相當(dāng)于vuex與vue的關(guān)系。
同類工具還有:
redux、dva、recoil

2.Mobx有什么優(yōu)勢(shì)
1.簡(jiǎn)單
編寫無(wú)模板的極簡(jiǎn)代碼精準(zhǔn)描述你的意圖 (原生js)
- 輕松實(shí)現(xiàn)最優(yōu)渲染
依賴自動(dòng)追蹤,實(shí)現(xiàn)最小渲染優(yōu)化。
其實(shí)在原生的react上,react的性能并不是強(qiáng)項(xiàng)(vue的渲染速度確實(shí)折服了一票粉絲),但是mobx可以幫助react實(shí)現(xiàn)依賴的自動(dòng)追蹤,實(shí)現(xiàn)優(yōu)化react組件的性能。
架構(gòu)自由
可移植, 可測(cè)試 無(wú)特殊心智負(fù)擔(dān)
React 和 MobX 是一對(duì)強(qiáng)力組合。React 通過(guò)提供機(jī)制把應(yīng)用狀態(tài)轉(zhuǎn)換為可渲染組件樹(shù)并對(duì)其進(jìn)行渲染。而MobX提供機(jī)制來(lái)存儲(chǔ)和更新應(yīng)用狀態(tài)供 React 使用。
對(duì)于應(yīng)用開(kāi)發(fā)中的常見(jiàn)問(wèn)題,React 和 MobX 都提供了最優(yōu)和獨(dú)特的解決方案。React 提供了優(yōu)化UI渲染的機(jī)制, 這種機(jī)制就是通過(guò)使用虛擬DOM來(lái)減少昂貴的DOM變化的數(shù)量。MobX 提供了優(yōu)化應(yīng)用狀態(tài)與 React 組件同步的機(jī)制,這種機(jī)制就是使用響應(yīng)式虛擬依賴狀態(tài)圖表,它只有在真正需要的時(shí)候才更新并且永遠(yuǎn)保持是最新的。
3.社區(qū)評(píng)價(jià)

配置開(kāi)發(fā)環(huán)境
Mobx是一個(gè)獨(dú)立的響應(yīng)式的庫(kù),可以獨(dú)立于任何UI框架存在,但是通常大家習(xí)慣把它和React進(jìn)行綁定使用,用Mobx來(lái)做響應(yīng)式數(shù)據(jù)建模,React作為UI視圖框架渲染內(nèi)容,我們環(huán)境的配置需要三個(gè)部分
- 一個(gè)create-react-app創(chuàng)建好的React項(xiàng)目環(huán)境
- mobx框架本身
- 一個(gè)用來(lái)鏈接mobx和React的中間件
# 創(chuàng)建項(xiàng)目 $ npm create-react-app react_mobx_app # 安裝mobx npm install mobx --save # 中間件工具 mobx-react-lite $ npm install mobx-react-lite # 官網(wǎng)推薦:mobx與react綁定庫(kù) $ npm install mobx-react --save
瀏覽器支持
- MobX >=5 版本運(yùn)行在任何支持 ES6 proxy 的瀏覽器。如果運(yùn)行在像 IE11、Node.js 6 以下版本或依靠與較舊的 JavaScripCore 的安卓端的 React Native。
- MobX 4 可以運(yùn)行在任何支持 ES5 的瀏覽器上,而且也將進(jìn)行持續(xù)地維護(hù)。MobX 4 和 5 的 API 是相同的,并且語(yǔ)義上也能達(dá)到相同的效果,只是 MobX 4 存在一些 局限性。
小貼士: MobX 5 包的主入口點(diǎn)附帶 ES5 代碼,以便向后兼容所有構(gòu)建工具。但因?yàn)?MobX 5 只能運(yùn)行在現(xiàn)代瀏覽器上,所以可以考慮使用速度最快、體積最小的 ES6 構(gòu)建: lib/mobx.es6.js 。例如,通過(guò)設(shè)置 webpack 的別名: resolve: { alias: { mobx: __dirname + "/node_modules/mobx/lib/mobx.es6.js" }}
基礎(chǔ)使用
需求: 使用mobx實(shí)現(xiàn)一個(gè)計(jì)數(shù)器的案例

1. 初始化mobx
初始化步驟
- 定義數(shù)據(jù)狀態(tài)(state)
- 在構(gòu)造器中實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式處理
- 定義action函數(shù)
- 實(shí)例化store并導(dǎo)出
// 編寫第一個(gè)mobx store小案例
import { makeAutoObservable } from 'mobx'
class CounterStore {
// 1.定義數(shù)據(jù)
count = 0
constructor() {
// 2.把數(shù)據(jù)弄成響應(yīng)式
makeAutoObservable(this)
}
// 3.定義action函數(shù),用來(lái)修改數(shù)據(jù)
addCount = () => {
this.count++;
}
}
// 4.實(shí)例化導(dǎo)出給react使用
const counterStore = new CounterStore()
export { counterStore }
2. React使用store
實(shí)現(xiàn)步驟
- 在組件中導(dǎo)入counterStore實(shí)例對(duì)象
- 在組件中使用storeStore實(shí)例對(duì)象中的數(shù)據(jù)
- 通過(guò)事件調(diào)用修改數(shù)據(jù)的方法修改store中的數(shù)據(jù)
- 讓組件響應(yīng)數(shù)據(jù)變化
import { counterStore } from '../store/counter'
import { observer } from 'mobx-react-lite'
function Count() {
return (
<div>
{/* 1.把store中的count渲染出來(lái) */}
<button>{counterStore.count}</button>
<br /><hr />
{/* 2.通過(guò)點(diǎn)擊事件觸發(fā)action函數(shù),修改count值 */}
<button onClick={counterStore.addCount}>點(diǎn)我+1</button>
</div>
)
}
// 包裹組件讓視圖響應(yīng)數(shù)據(jù)變化
export default observer(Count)Mobx - computed
計(jì)算屬性(衍生狀態(tài))
概念: 有一些狀態(tài)根據(jù)現(xiàn)有的狀態(tài)計(jì)算(衍生)得到,我們把這種狀態(tài)叫做計(jì)算屬性, 看下面的例子

實(shí)現(xiàn)步驟
- 聲明一個(gè)存在的數(shù)據(jù)
- 通過(guò)get關(guān)鍵詞 定義計(jì)算屬性
- 在 makeAutoObservable 方法中標(biāo)記計(jì)算屬性
不標(biāo)記不影響計(jì)算屬性的使用,這里的標(biāo)記只是為了讓代碼更直觀,程序員一看到這行代碼就知道filterList是通過(guò)計(jì)算屬性得來(lái)的。
- 修改聲明的數(shù)據(jù),計(jì)算屬性的數(shù)據(jù)也會(huì)一起改變
- Mobx提供的計(jì)算屬性與
vue中的computed差別不大
// counterStore.js
import { makeAutoObservable, computed } from 'mobx'
class CounterStore {
// 1.聲明一個(gè)list數(shù)組
list = [1, 2, 3, 4, 5, 6]
constructor() {
makeAutoObservable(this, {
// 3.標(biāo)記計(jì)算屬性
// 不標(biāo)記不影響計(jì)算屬性的使用,這里的標(biāo)記只是為了讓代碼更直觀,程序員一看到這行代碼就知道filterList是通過(guò)計(jì)算屬性得來(lái)的
filterList: computed
})
}
// 2.定義計(jì)算屬性
get filterList() {
return this.list.filter(item => item > 2)
}
changeList = () => {
this.list.push(7, 8, 9)
}
}
const counterStore = new CounterStore()
export { counterStore }
// Count.jsx
import { counterStore } from '../store/counter'
import { observer } from 'mobx-react-lite'
function Count() {
return (
<div>
{/* 使用計(jì)算屬性 */}
{counterStore.filterList.join('-')}
<button onClick={counterStore.changeList}>修改List</button>
</div>
)
}
// 包裹組件讓視圖響應(yīng)數(shù)據(jù)變化
export default observer(Count)
Mobx - 模塊化
場(chǎng)景: 一個(gè)項(xiàng)目有很多的業(yè)務(wù)模塊,我們不能把所有的代碼都寫到一起,這樣不好維護(hù),為了提供可維護(hù)性,需要引入模塊化機(jī)制

實(shí)現(xiàn)步驟
- 拆分模塊js文件,每個(gè)模塊中定義自己獨(dú)立的state/actions
- 在store/index.js中導(dǎo)入拆分之后的模塊,進(jìn)行模塊組合
- 利用React的useContext的機(jī)制導(dǎo)出統(tǒng)一的useStore方法,給業(yè)務(wù)組件使用
代碼實(shí)現(xiàn)
項(xiàng)目結(jié)構(gòu)
src ├─App.jsx ├─index.js ├─store | ├─count.Store.js | ├─index.js | └list.Store.js ├─components | ├─Count.jsx | └List.jsx
/src/store/count.Store.js
import { makeAutoObservable } from 'mobx'
class CountStore {
count = 0
constructor() {
makeAutoObservable(this)
}
addCount = () => {
this.count++
}
}
export { CountStore }
/src/store/list.Store.js
import { makeAutoObservable } from "mobx";
class ListStore {
constructor() {
makeAutoObservable(this)
}
list = ['react', 'vue']
changeList = () => {
this.list.push('angular')
}
}
export { ListStore }
/src/store/index.js
// 組合子模塊 封裝統(tǒng)一導(dǎo)出的供組件使用的方法
import React, { useContext } from "react";
import { CountStore } from "./count.Store";
import { ListStore } from "./list.Store";
class RootStore {
constructor() {
// 對(duì)子模塊進(jìn)行實(shí)例化操作
// 將來(lái)實(shí)例化rootstore的時(shí)候,rootstore實(shí)例上有兩個(gè)屬性,分別存放了子模塊的兩個(gè)實(shí)例。
this.countStore = new CountStore()
this.listStore = new ListStore()
}
}
// 使用react context機(jī)制,完成統(tǒng)一方法封裝
// 1.實(shí)例化rootStore注入context
const rootStore = new RootStore()
const context = React.createContext(rootStore)
// 2.導(dǎo)出useStore方法,供組件通過(guò)調(diào)用該方法使用根實(shí)例
// 作用:通過(guò)useContext拿到rootStore實(shí)例對(duì)象,然后返回
// 只要在業(yè)務(wù)組件中 調(diào)用useStore() 就可以拿到 rootStore實(shí)例對(duì)象
const useStore = () => useContext(context)
export { useStore }
組件使用模塊中的數(shù)據(jù)
import { observer } from 'mobx-react-lite'
import { useStore } from './store'
function App() {
const { countStore } = useStore()
return (
<div className="App">
<button onClick={() => countStore.addCount()}>
{countStore.count}
</button>
</div>
)
}
// 包裹組件讓視圖響應(yīng)數(shù)據(jù)變化
export default observer(App)
Mobx - 總結(jié)
1.初始化Mobx的過(guò)程是怎樣的?
聲明數(shù)據(jù) -> 響應(yīng)式處理 -> 定義action函數(shù) -> 實(shí)例化導(dǎo)出
2.Mobx如何配合react,需要依賴什么包?
mobx-react-lite作為連接包,導(dǎo)出
observer方法,包裹組件
3.模塊化解決了什么問(wèn)題?
維護(hù)性問(wèn)題
4.如何實(shí)現(xiàn)Mobx的模塊化?
按照功能拆分store模塊,根模塊中組合子模塊,利用
context機(jī)制依賴注入
到此這篇關(guān)于React+Mobx基本使用、模塊化的文章就介紹到這了,更多相關(guān)React Mobx使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解react內(nèi)聯(lián)樣式使用webpack將px轉(zhuǎn)rem
這篇文章主要介紹了詳解react內(nèi)聯(lián)樣式使用webpack將px轉(zhuǎn)rem,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
ReactNative 之FlatList使用及踩坑封裝總結(jié)
本篇文章主要介紹了ReactNative 之FlatList使用及踩坑封裝總結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
如何用webpack4.0擼單頁(yè)/多頁(yè)腳手架 (jquery, react, vue, typescript)
這篇文章主要介紹了如何用webpack4.0擼單頁(yè)/多頁(yè)腳手架 (jquery, react, vue, typescript),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
JavaScript的React Web庫(kù)的理念剖析及基礎(chǔ)上手指南
這篇文章主要介紹了JavaScript的React Web庫(kù)的理念剖析及基礎(chǔ)上手指南,React Web的目的即是把本地的React Native應(yīng)用程序項(xiàng)目變?yōu)閃eb應(yīng)用程序,需要的朋友可以參考下2016-05-05
D3.js(v3)+react 實(shí)現(xiàn)帶坐標(biāo)與比例尺的散點(diǎn)圖 (V3版本)
散點(diǎn)圖(Scatter Chart),通常是一橫一豎兩個(gè)坐標(biāo)軸,數(shù)據(jù)是一組二維坐標(biāo),分別對(duì)應(yīng)兩個(gè)坐標(biāo)軸,與坐標(biāo)軸對(duì)應(yīng)的地方打上點(diǎn)。由此可以猜到,需要的元素包括circle(圓)和axis(坐標(biāo)軸),接下來(lái)通過(guò)本文大家分享D3.js(v3)+react 實(shí)現(xiàn)帶坐標(biāo)與比例尺的散點(diǎn)圖 (V3版本) ,一起看看2019-05-05
如何使用Redux Toolkit簡(jiǎn)化Redux
redux-toolkit是目前redux官方推薦的編寫redux邏輯的方法,針對(duì)redux的創(chuàng)建store繁瑣、樣板代碼太多、依賴外部庫(kù)等問(wèn)題進(jìn)行了優(yōu)化,官方總結(jié)了四個(gè)特點(diǎn)是簡(jiǎn)易的/有想法的/強(qiáng)勁的/高效的,總結(jié)來(lái)看,就是更加的方便簡(jiǎn)單了2022-12-12

