学习目标:掌握和使用Mobx状态管理工具
目录
一、配置开发环境
Mobx是一个独立的响应式的库,可以独立于任何UI框架存在,但是通常大家习惯把它和React进行绑定使用,用Mobx来做响应式数据建模,React作为UI视图框架渲染内容,我们环境的配置需要三个部分:
- 一个create-react-app创建好的React项目环境
- mobx框架本身
- 一个用来连接mobx和React的中间件mobx-react-lite(这个包只能函数组件用,类组件可以用mobx-react)
# 创建项目
$ yarn create vite react-mobx --template react
# 安装mobx和中间件工具 mobx-react-lite 只能函数组件中使用
$ yarn add mobx mobx-react-lite
#或者是使用npm
$ npm add mobx mobx-react-lite
二、使用Mobx实现一个计数器
图源:柴柴老师
1. 初始化mobx
创建一个类:
(1)定义数据状态state
(2)在构造器中实现数据响应式处理 makeAutoObservble
(3)定义修改数据的函数action
实例化store并导出:
const counter = new counterStore() export default counter
(1)counter.Store.js:
import {makeAutoObservable} from 'mobx'
// 创建一个类:定义状态(即数据)以及一些方法来操作这些状态
class counterStore{
// 定义状态
count= 0
// 响应式处理makeAutoObservable
constructor(){
makeAutoObservable(this)
}
// 定义修改状态的方法、
addCount(){
this.count++
}
}
// 创建实例
const counter = new counterStore()
// 导出实例
export default counter
2. React使用store
实现步骤
- 在组件中导入counterStore实例对象
- 在组件中使用storeStore实例对象中的数据
- 通过事件调用修改数据的方法修改store中的数据
- 让组件响应数据变化(observer)
(2)App.js
// 导入实例对象
import counter from './store/counter.Store.js'
// 导入observer方法——是小写!
import { observer } from 'mobx-react-lite'
function App() {
return (
<div className="App">
{/*直接打点就行 */}
<div>{counter.count}</div>
<button onClick={()=>counter.addCount()}>+</button>
</div>
)
}
// ※ 包裹组件让视图响应数据变化
export default observer(App)
三、计算属性
有一些状态根据现有的状态计算(衍生)得到的,这就需要使用计算属性啦
1、示例
价格已经确定,实现有一个按钮控制数量,当数量增加时,总额也相应变化
(1)test.Store.js
import {computed, makeAutoObservable} from 'mobx'
// 创建一个类:定义状态(即数据)以及一些方法来操作这些状态
class testStore{
// 定义状态
price= 9.9;
count=1;
// 不需要定义,用getter定义
// total=0
// makeAutoObservable 标记是计算属性
constructor(){
makeAutoObservable(this,{
total:computed
})
}
// 更改数量
changeCount(){
this.count++
}
// 定义计算属性
get total(){
return (this.price * this.count).toFixed (2)
}
}
// 创建实例
const test = new testStore()
// 导出实例
export default test
(2)App.js
// 导入类
import test from './store/test.Store.js'
// 导入observer方法——是小写!
import { observer } from 'mobx-react-lite'
function App() {
return (
<div className="App">
{/*直接打点就行 */}
<div>价格:{test.price}</div>
<div>
<span>数量:{test.count}</span>
<button onClick={()=>test.changeCount()}>+</button>
</div>
<div>金额:{test.total}</div>
</div>
)
}
// ※ 包裹组件让视图响应数据变化
export default observer(App)
(3)实现效果
四、模块化
一个项目有很多的业务模块,把所有的代码都写到一起非常不好维护,因此我们可以按照一定的功能将其拆分为多个模块,再将其组合起来。
示例: 在刚刚计算总额模块的基础上,再增加一个展示列表的模块,效果如图所示
1、模块一
test.Store.js(不用实例化)
import {computed, makeAutoObservable} from 'mobx'
// 创建一个类:定义状态(即数据)以及一些方法来操作这些状态
class TestStore{
// 定义状态
price= 9.9;
count=1;
// makeAutoObservable 标记是计算属性
constructor(){
makeAutoObservable(this,{
total:computed
})
}
// 更改数量
changeCount(){
this.count++
}
// 定义计算属性
get total(){
return (this.price * this.count).toFixed (2)
}
}
// 导出
export default TestStore
2、模块二
list.Store.js(不用实例化)
import { makeAutoObservable } from "mobx"
class ListStore{
manList=[
{id:"0",name:"BillKin"},
{id:"1",name:"PP"},
{id:"2",name:"Ohm"},
{id:"3",name:"NaNon"}
]
constructor(){
makeAutoObservable(this)
}
}
export default ListStore
3、组合
// 导入
import testStore from "./test.Store";
import listStore from "./list.Store";
import { createContext, useContext } from "react";
class RootStore{
constructor(){
// 实例化
this.listStore=new listStore()
this.testStore = new testStore()
}
}
// 实例化根store注入context
const rootStore = new RootStore()
// context机制的数据查找链 Provider如果找不到 就找createContext方法执行时传入的参数
const context = createContext(rootStore)
// 封装一个方法,调用时可以得到rootStore实例对象
const useStore =()=>{
return useContext(context)
}
export {useStore}
4、使用
// 导入类
import {useStore} from './store/index.Store'
// 导入observer方法——是小写!
import { observer } from 'mobx-react-lite'
function App() {
// 可以解构,但是解构到实例对象就可以了,防止破坏响应式
const {testStore , listStore} = useStore()
return (
<div className="App">
{/*直接打点就行 */}
<ul>
{listStore.manList.map(item=>
<li key={item.id}>{item.name}</li>
)}
</ul>
<div>价格:{testStore.price}</div>
<div>
<span>数量:{testStore.count}</span>
<button onClick={()=>testStore.changeCount()}>+</button>
</div>
<div>金额:{testStore.total}</div>
</div>
)
}
// ※ 包裹组件让视图响应数据变化
export default observer(App)