mobx 入门

2019-08-21 16:30:27 浏览数 (1)

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

当函数内的观察对象属性值变化时,将触发该函数, 默认初始调用一次

代码语言:javascript复制
    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 类似, 只对函数内的值作响应

代码语言:javascript复制
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

指定响应值

代码语言:javascript复制
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

筛选响应

某些时候,我们希望存在多个观察值的情况下,只对其中的某些值做或某些情况响应.

代码语言:javascript复制
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
代码语言:javascript复制
let pm =  when(() => Rogan.age === 110)

pm.then(

    () => console.log('dead'),
    () => console.log('live')

)
  • action

状态修改函数

将多个状态修改,合并为一次提交给 autorun

代码语言:javascript复制
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 对异步内的回调时无效的

代码语言:javascript复制
class 
React
  • 安装 mobx-react 依赖
代码语言:javascript复制
// 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>
            
        )
        
    }
    
    
}

0 人点赞