mobx 状态管理工具

cnpm i mobx mobx-react -S

与redux的区别:

  1. 仓库可以有多个
  2. 用的是面向对象的语法

注意:mobx用到了装饰器语法,所以需要先配置支持装饰器

原生监控数据: Object.defineProperty(es5)、observable和proxy(es6)

1.mobx-建立一个store示例

官网

1.box&&map的store

修改直接是store.set('xx','xx')

1585387078275

2.class类store

@observable 变量名=值 可以监听数据的变化

@action 修改动作

@computed 类似计算属性

autorun 监听所有数据的变化 autorun(()=>{})
reaction 监听特定数据的变化 reaction(()=>[a,b….],()=>{ })

  1. // store/index.js
  2. import {observable,autorun,reaction,action,computed} from 'mobx'
  3. class Store {
  4. // observable监听数据变化;
  5. @observable a=5;
  6. @observable b=21;
  7. // action修改
  8. @action changeA=()=>{//箭头函数,为了使用this
  9. this.a=999
  10. }
  11. @action getData= async()=>{//异步示例-一般在componentDidMount中使用
  12. fetch('url').then(res=>res.json()).then(res=>{
  13. this.list=res
  14. })
  15. }
  16. // 获取计算属性-不能用箭头函数
  17. @computed get getA(){
  18. return this.a + '经过计算属性包装/筛选'
  19. }
  20. }
  21. let s=new Store()//此时s就是实例化的仓库之一
  22. // autorun对observables做出响应,监听所有数据的变化
  23. autorun(()=>console.log('数据变化了'))
  24. s.a=100
  25. console.log(s.a)
  26. // 监听特定数据的变化(第一个参数回调返回一个数组,只监听数据内的数据变化)
  27. reaction(()=>[s.b],()=>console.log('b数据变化了'))
  28. // 导出仓库
  29. export default s
  30. // 此时,只能获取到第一次的值,仓库的数据其实修改了,但是页面并没响应(且需要组件内部引入仓库-得到或使用仓库的属性和方法)

3.store打印

1585381510134

2.更新视图的方法

2.1更新方法一(类组件的setState和mobx的监听)

手动挡(手动引入store,手动监听,卸载时还要取消监听)

  1. import React, { Component } from 'react'
  2. import store from '@/store'
  3. import {autorun,reaction} from 'mobx'
  4. export default class index extends Component {
  5. constructor(props) {
  6. super(props)
  7. this.state = {
  8. a: store.a//store的初始值
  9. }
  10. }
  11. componentDidMount(){
  12. //this.mobxGuanCha = autorun(()=>{
  13. //监听store的所有数据变化-缺点:一直触发render
  14. // this.setState({
  15. // n:store.n
  16. // })
  17. //})
  18. this.mobxGuanCha = reaction (()=>[store.n],()=>{
  19. //监听store的特定(数组内的)数据变化-多写第一个参数
  20. this.setState({
  21. n:store.n
  22. })
  23. })
  24. }
  25. componentWillUnmount() {
  26. this.mobxGuanCha()//取消观察(监听的返回值就是取消监听的方法,调用即可)
  27. }
  28. render() {
  29. return (
  30. <div>
  31. {this.state.n}
  32. <button onClick={store.changeData}>+</buttom>
  33. </div>
  34. )
  35. }
  36. }

bug:

当卸载组件,监听函数并没有取消,下次创建就会有多个监听。解决:在componentWillUnmount中取消观察(监听的返回值就是取消监听的方法,调用即可)

当网速慢,切换页面注销组件,请求结果回来使用setState也会报错。解决:取消异步请求不好做,投机方法在componentWillUnmount中重写setState这样请求回来后就不会触发react的setState

1585386701313

2.2方法二:import {observer} from ‘mobx-react’ (通过装饰器observer来监听变化)

半自动 - 手动引入store&自动检测数据更新(自动监听)

  1. import React, { Component } from 'react'
  2. import store from '@/store'
  3. import {observer} from 'mobx-react'
  4. @observer//监听所有数据变化
  5. class Test extends Component {
  6. render() {
  7. return (
  8. <div>
  9. {store.a}
  10. <button onClick={store.changeData}>+</button>
  11. </div>
  12. )
  13. }
  14. }
  15. export default Test

2.3.方法三—引入mobx-react传递store

全自动-注入(注入Provider传过来的store的属性和方法到this.props上并且自动监听)

  1. //在根目录index.js中
  2. import store from '@/store'
  3. import {Provider} from 'mobx-react'
  4. //包裹App,传递store <Provider store={store}><App/></Provider>
  5. //报错则是react核心包或者mobx-react版本有问题或丢包https://www.cnblogs.com/inaruto/p/11342559.html
  6. 组件内部:
  7. import React from 'react'
  8. import {observer,inject} from 'mobx-react'
  9. @inject('store')//注入Provider传过来的store的属性和方法到this.props上(其中'store'应该是key值)
  10. @observer //监听仓库数据变化
  11. function Test() {
  12. return (
  13. <div>
  14. {this.props.store.a}
  15. <button onClick={this.props.store.changeData}>+</buttom>
  16. </div>
  17. )
  18. }
  19. export default Test

P^AU9GknXwAd*E

Amazon1123how_