mobx
响应式状态管理库
安装
代码语言:javascript复制// npm
npm i --save mobx
// yarn
yarn add mobx
基础概念
- 所谓的响应式,既是将原有数据结构,例如 数组,对象等转变为可观察对象, 通过对可观察对象的监控,当数据变化做出对应的动作,所以可以大概归纳为:
- 构建观察对象
- 设置响应动作
- 在mobx中构建观察对象存在两种模式
- 函数模式
- 装饰器模式(针对类定义)
函数模式
创建观察对象
代码语言:javascript复制// 引入mobx
import { observable } from 'mobx'
// 对象转换
const obj = observable({
name: 'Rogan',
age: 24
})
// 数组转换
const arr = observable([
1, 2, 3
])
// map 转换
const map = observable(new Map([ ["name", "Rogan"] ]))
/*
注意:
我们实际操作的是观察对象,而非我们创建时传入的值,
我们可能修改保存观察对象的变量,这是将丢失观察对象.
例如: let arr = observable([1)
arr = [2]
*/
响应变化
- autorun
当函数内的观察对象属性值变化时,将触发该函数, 默认初始调用一次
const obj = observable({
name: 'Rogan',
age: 24
})
autorun(() => {
console.log(obj.name)
})
// 默认调用
// -> Rogan
obj.name = 'coco'
// 触发 autorun
// -> coco
obj.age = 24
// 不会触发 autorun
obj.name = 'coco'
// 赋值相同时,不会触发 autorun
- computed](https://cn.mobx.js.org/refguide/computed-decorator.html)
有时我们需要观察对象处理后的数据, 当观察对象值变化后,产生新的值
响应规则与 autorun 类似, 只对函数内的值作响应
computed(get, set)
// get: 获取值函数
// set: 设置值函数
代码语言:javascript复制import { observable, computed } from 'mobx'
const obj = observable({
name: 'Rogan',
age: 24
})
// 取值对象
const userName = computed(() => {
return `username: ${obj.name} `})
// 获取computed 值
console.log(userName.get()) // -> username: Rogan
// 响应 name 变化
userName.name = "Coco"
console.log(userName.get()) // -> username: Coco
// 取值, 设值对象
const userAge = computed(
// 取值方法
() => return obj.name,
// 设值方法
data => console.log(data)
)
console.log(userAge.get()) // -> 24
userAge.set(30) // -> 30
- reaction
指定响应值
reaction( watchFn, actionFn )
// watchFn: 监控函数, 返回被监控数据.
// actionFn: 响应函数, 接收 watchFn 返回的响应数据
代码语言:javascript复制const Rogan = observable({
id: "123",
name: "Rogan",
age: 24
})
// 监控 name age 数据
reaction(() => [Rogan.name, Rogan.age], data => console.log(data) )
// 响应 name age 变化
Rogan.name = "Coco"
// -> [ Coco, 24 ]
Rogan.age = 30
// -> [ Coco, 30 ]
// 不响应 id
Rogan.id = "111"
- when
筛选响应
某些时候,我们希望存在多个观察值的情况下,只对其中的某些值做或某些情况响应.
when(filteFn, actionFn)
// filteFn 过虑函数, 返回 boolean
// actionFn 响应函数,当 filteFn 返回 true 时执行, 只执行一次
代码语言:javascript复制const Rogan = observable({
name: 'Rogan',
age: 100
})
// when 将返回终止函数,调用终止函数后,when的响应函数将不会执行
let dispose = when(() => Rogan.age === 110, () => console.log("dead"))
//终止响应函数
// dispose()
// 触发响应
Rogan.age = 110 // -> dead
// 响应函数只会执行一次
Rogan.age = 0
Rogan.age = 110 // 无输出
- when promise模式
当when 未配置响应函数时, 将返回Promise
let pm = when(() => Rogan.age === 110)
pm.then(
() => console.log('dead'),
() => console.log('live')
)
- action
状态修改函数
将多个状态修改,合并为一次提交给 autorun
const rogan = observable({
id: '123',
name: 'Rogan',
age: 24,
})
autorun(() => {
console.log(rogan.name, rogan.age)
})
// 普通状态修改函数
let change = (name, age) => {
rogan.name = name
rogan.age = age
}
// 合并后的修改函数
let warpChange = action('age', (name, age) => {
rogan.name = name
rogan.age = age
})
change('coco', 30)
// 触发多次 autorun
// -> coco 24
// -> coco 30
warpChange('jeck', 11)
// 只触发一次 autorun
// -> jeck 11
装饰器模式
多数情况下,mobx 配置和 react 使用在类中
类中使用 observable
代码语言:javascript复制class Man {
// 使用装饰器 构建装饰器值
@observable name = ''
@observable age = 0
// 普通属性
id = '0000'
constructor(name, age){
this.name = name
this.age = age
// log
autorun( () => console.log(`update: ${this.name} ${this.age} ${this.id}`))
}
}
const Rogan = new Man('Rogan', 100)
Rogan.name = "Wolf" // -> Wolf 100 0000
Rogan.id = "0001" // 无响应
Rogan.age = 101 // -> Wolf 101 0001
类中使用 action
代码语言:javascript复制class Man {
// 使用装饰器 构建装饰器值
@observable name = ''
@observable age = 0
// 普通属性
id = '0000'
constructor(name, age){
this.name = name
this.age = age
// log
autorun( () => console.log(`update: ${this.name} ${this.age} ${this.id}`))
}
// 使用 .bound 将函数绑定在对象上
// 类似 this.changeName.bind(this)
@action.bound
changeName(name){
this.name = name
}
// 普通方法
changeAge(age){
this.age = age
}
}
const changeName = Rogan.changeName
changeName('Body') // -> Body 101 0001
const changeAge = Rogan.changeAge
changeAge() // 报错 TypeError: Cannot set property 'name' of undefined
类中使用 computed
代码语言:javascript复制class Add {
@observable a = 0
@observable b = 0
@computed get total (){
return this.a this.b
}
// 这里 set 将自动挂载 不需要添加装饰器
set total(data) {
console.log("Cannot set total value")
}
constructor(a, b){
this.a = a
this.b = b
}
}
const add = new Add(10, 12)
console.log(add.total) // -> 22
add.total = 100 // -> Cannot set total value
- action 与 异步函数
action 在绑定异步函数中,外层action 对异步内的回调时无效的
class
React
- 安装 mobx-react 依赖
// npm
npm i --save mobx-react
//yarn
yarn add mobx-react
代码语言:javascript复制import { observable, autorun, computed, action, when, reaction } from 'mobx'
import { observer } from 'mobx-react'
import "./index.less"
// @oberver 将组件内的 rander 函数, 通过 autorun做监听
export default @observer class Cmp extends React.Component{
@observable count = 0
@action.bound
add(){
this.count = 1;
}
render(){
return (
<div>
<div>
{this.count}
</div>
<button onClick={this.add}>
add
</button>
</div>
)
}
}