1. 安装
# mobx核心库
npm install --save mobx
# mobx绑定react
npm install mobx-react --save
2. 兼容装饰器语法
安装下面的插件
npm install @babel/plugin-proposal-decorators --save
npm install @babel/plugin-proposal-class-properties --save
3. 配置
- vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react({
babel: {
plugins: [
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-proposal-class-properties", { loose: true }]
]
}
})],
})
- jsconfig.json(没有的话,新建一个)
{
"compilerOptions":{
"experimentalDecorators": true
}
}
- eslint 可能也会报错,自己修改一下
3. 项目结构截图
4. 上代码
- userStore.js
import { observable, computed, action, makeObservable, runInAction } from "mobx";
import axios from "axios";
class UserInfo {
// Observable 值可以是JS基本数据类型、引用类型、普通对象、类实例、数组和映射
@observable name = 'zrs'
@observable sex = '男'
@observable age = 20
@observable hobbys = ['羽毛球', '游戏']
constructor() {
// 捕获已经存在的对象属性并且使得它们可观察
makeObservable(this);
}
@computed get getHobbys() {
return this.hobbys
}
@action addHobby(val) {
this.hobbys = [...this.hobbys, val]
console.log("this", this.hobbys);
}
@action delHobby(val) {
console.log(val);
this.hobbys = this.hobbys.filter(it => it !== val)
}
@action getHobbyList = () => {
axios
.get(
'url'
)
.then((res) => {
// 创建一个会被立即调用的临时 action。在异步进程中非常有用
// 将状态修改代码包装成动作
runInAction(() => {
this.hobbys = res.data;
});
})
.catch((err) => {
});
};
}
const userInfo = new UserInfo()
export default { userInfo }
- main.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import store from './store/userStore.js'
import { Provider } from 'mobx-react'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<Provider {...store}>
<App />
</Provider>
</React.StrictMode>
)
- app.jsx
import React, { Component } from 'react'
import { inject, observer } from 'mobx-react'
import Child1 from './components/child1'
import Child2 from './components/child2'
@inject('userInfo')
@observer
export default class App extends Component {
constructor() {
super()
this.state = {
hobby: ''
}
}
render() {
console.log('userInfo', this.props.userInfo)
const { name, age, getHobbys } = this.props.userInfo
return (
<div>
<h1>app</h1>
{name}--------------{age}
<input
type="text"
value={this.state.hobby}
onInput={(e) => {
this.setState({
hobby: e.target.value
})
}}
/>
<button
onClick={() => {
console.log('this.state.hobby', this.state.hobby)
this.props.userInfo.addHobby(this.state.hobby)
this.setState({ hobby: '' })
}}
>
确认
</button>
<ul>
{getHobbys.map((it) => (
<li key={it}>
{it}-----------
<button
onClick={() => {
store.userInfo.delHobby(it)
}}
>
删除
</button>
</li>
))}
</ul>
<hr />
<h1>child1</h1>
<Child1 />
<hr />
<h1>child2</h1>
<Child2 />
</div>
)
}
}
参考文章:mobx装饰器语法快速使用及 runInAction flow - 掘金 (juejin.cn)
- child1.jsx
import React, { Component } from 'react'
import { observer } from 'mobx-react'
import store from '../store/userStore'
@observer
export default class child1 extends Component {
render() {
return (
<div>
<ul>
{/* 计算属性的使用 */}
{store.userInfo.getHobbys.map((it) => (
<li key={it}>
{it}-----------
<button
onClick={() => {
store.userInfo.delHobby(it)
}}
>
删除
</button>
</li>
))}
</ul>
</div>
)
}
}
- child2.jsx
import React, { Component } from 'react'
export default class child2 extends Component {
render() {
return <div>child2</div>
}
}
5. 一些有用的东西
1. makeAutoObservable 和 makeObservable
参考文章:MobX 学习 - 03 makeAutoObservable 和 makeObservable_皮蛋很白的博客-CSDN博客
2.异步
参考文章:mobx装饰器语法快速使用及 runInAction flow - 掘金 (juejin.cn)
// 异步action最佳解决方案
getData = flow(function* () {
try {
const res = yield axios.get(
"url"
); // 用 yield 代替 await
console.log("getData", res);
// 异步代码块会被自动包装成动作并修改状态
this.projectsList = res.data.Data;
} catch (error) {
console.log("getData", err);
}
});
3.其他
- Mobx里启用严格模式的函数就是useStrict,注意和原生JS的"use strict"不是一个东西。如果设置成严格模式,则只有@action才可以修改观测中的值。
- action只能影响当前运行的函数,而不能影响函数中的异步回调函数,因此需要对异步回调函数也使用action标注。如果是用async function,则可以使用runInAction函数来解决。