兼容性
ie11及以下,mobx4;ie11以上,mobx5(es6 Proxies)
核心思想
源自应用状态的东西都应自动获得
初始化
-
create-react-app
创建项目 -
yarn add -D react-app-rewired customize-cra @babel/plugin-proposal-decorators
装包 -
config-overrides.js
改配置
const { override, addDecoratorsLegacy } = require("customize-cra")
module.exports = override(
addDecoratorsLegacy()
)
-
package.json
改配置
react-scripts
改成react-app-rewired
-
yarn start
启动项目
mobx起步 - 计数器
安装包yarn add mobx mobx-react
index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { observable, action} from 'mobx'
import {observer} from 'mobx-react'
// 1.初始化mobx
class store {
@observable num = 0
@action.bound add () {
this.num ++
}
}
// 2.使用mobx
@observer
class App extends Component {
render() {
const { store } = this.props
return (
<div>
<h1>app components</h1>
<p>{store.num}</p>
<button onClick={store.add}>加一呀</button>
</div>
);
}
}
// 3. 修改容器状态
ReactDOM.render(<App store={new store()} />, document.getElementById('root'));
装饰器
对类进行处理的函数,接收的参数就是类。
@fn1
@fn2(20)
@fn3
class TestClass {
@readonly msg = 'hello fxd' // 只能读
}
function fn1(target) {
target.foo = 'foo'
}
function fn2(value) {
return function (target) {
target.count = value
}
}
function fn3(target) {
target.prototype.name = 'fxd'
}
// target-目标类的prototype name-类成员名 descriptor-描述对象
function readonly(target, name, descriptor) {
descriptor.writable = false
}
console.log(TestClass.foo)
console.log(TestClass.count)
console.log(new TestClass().name)
console.log(new TestClass().msg)
observable
观察数据变化的方法
import { observable, action, autorun} from 'mobx'
在计算器案例中,render
里面加上
autorun( () => {
console.log(store.num)
})
结果为
因此,
autorun
一上来就会执行,数据变化时也会执行
computed
计算属性
引入
import { observable, action, computed} from 'mobx'
计算
class store {
@observable num = 0
@observable price = 0.5
@computed get total () {
console.log('我执行了')
return this.price * this.num
}
}
使用计算结果
<p>总金额:{store.total}元</p>
action
改变store
里值的方法1:直接改变
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { observable } from 'mobx'
import {observer} from 'mobx-react'
class store {
@observable num = 0
}
@observer
class App extends Component {
render() {
const { store } = this.props
// 方法1.直接改变
setTimeout(() => {
store.num = 22
}, 1000);
return (
<div>
<h1>app components</h1>
<p>{store.num}</p>
</div>
);
}
}
ReactDOM.render(<App store={new store()} />, document.getElementById('root'));
改变store
里值的方法2:使用action
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { observable, action, configure } from 'mobx'
import {observer} from 'mobx-react'
// 配置 - 必须通过action修改值
configure({
enforceActions: 'observed'
})
class store {
@observable num = 0
// 写改变方法
// 使用bound是为了让this永远指向容器的实例对象
@action.bound change () {
this.num = 22
}
}
}
@observer
class App extends Component {
render() {
const { store } = this.props
// 方法2.用action来改变值
setTimeout(() => {
store.change()
}, 1000);
return (
<div>
<h1>app components</h1>
<p>{store.num}</p>
</div>
);
}
}
ReactDOM.render(<App store={new store()} />, document.getElementById('root'));
runInAction
是@change
的一种替代写法
引入
import { observable, action, configure, runInAction } from 'mobx'
修改方法
@observer
class App extends Component {
render() {
const { store } = this.props
// runInAction来改变值
setTimeout(() => {
runInAction(() => {
store.num = 33
})
}, 1000);
return (
<div>
<h1>app components</h1>
<p>{store.num}</p>
</div>
);
}
}
异步action
有三种修改方法
- 定义
acion
函数,业务逻辑复杂推荐使用 - 直接调用
acion
函数,原理和1类似,麻烦,不推荐使用 -
runInAction
,业务逻辑简单时使用
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { observable, action, configure, runInAction } from 'mobx'
import {observer} from 'mobx-react'
configure({
enforceActions: 'observed'
})
class store {
@observable num = 0
@action.bound asyncChange () {
setTimeout(() => {
// 方法1.定义acion函数
// this.changeNum()
// 方法2.直接调用action函数
// action('changeNum', () => {
// this.num = 44
// })()
// 方法3.runInAction
runInAction(() => {
this.num = 55
})
}, 1000);
}
@action.bound changeNum () {
this.num = 33
}
}
@observer
class App extends Component {
render() {
const { store } = this.props
store.asyncChange()
return (
<div>
<h1>app components</h1>
<p>{store.num}</p>
</div>
);
}
}
ReactDOM.render(<App store={new store()} />, document.getElementById('root'));
数据监测
-
autorun
一上来就执行,数据改变时执行
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { observable, action, configure, autorun } from 'mobx'
import {observer} from 'mobx-react'
configure({
enforceActions: 'observed'
})
class store {
@observable num = 0
@action.bound changeNum () {
this.num = 22
}
}
@observer
class App extends Component {
render() {
const { store } = this.props
store.changeNum()
// 数据监测
autorun(() => {
console.log('autorun=>', store.num)
})
return (
<div>
<h1>app components</h1>
<p>{store.num}</p>
</div>
);
}
}
ReactDOM.render(<App store={new store()} />, document.getElementById('root'));
-
when
如果满足执行条件,一上来就执行,数据改变时执行
只执行一次,有执行条件
import { observable, action, configure, when } from 'mobx'
// 数据监测
when(
() => {
return store.num > 100
},
() => {
console.log('when=>', store.num)
}
)
-
reaction
只有被监测数据改变时执行,会频繁执行
import { observable, action, configure, reaction } from 'mobx'
// 数据监测
reaction(
() => {
return store.num > 100
},
(data, reaction) => {
if (data) {
console.log('reaction=>', data)
// 手动停止当前reaction的监听
reaction.dispose()
}
}
)