【react】react18的学习(八)–mobx介绍

也是代替原生redux的公共状态管理方式,搭配mobx-react使用;
mobx@5版本需要浏览器支持es6 proxy,且使用了许多装饰器;
mobx@6移除了装饰器语法;

装饰器

装饰器本质:一个函数;

在调用类、类的属性/方法时,先将类、类的属性/方法经过装饰器处理再返回;类似中间件(但前者可以改变了原有值,后者是使用原有值进行操作);

1、给项目设置装饰器支持:先给vscode设置里找decorator设置支持;

yarn add @babel/plugin-proposal-decorators
yarn add @babel/plugin-proposal-class-properties
  • package.json:
"babel": {
    ...
    "plugins": [
      [
        "@babel/plugin-proposal-decorators",
        {
          "legacy": true
        }
      ],
      [
        "@babel/plugin-proposal-class-properties",
        {
          "loose": true
        }
      ]
    ]
  }

2、类装饰器

  • 一般装饰器
const addY = target => {
  // 类自身
  target.y = 200
  // 类的原型
  target.prototype.z = 300
}
// 固定写法
@addY
class Demo {
  // 实例
  x = 100
  // 类的原型
  getZ() {
    return this.z
  }
}
let d = new Demo()
console.log(d.getZ());//300
  • 传参装饰器
const sum = (x, y) => {
  return target => {
    target.prototype.sum = x + y
  }
}
// 固定写法
@sum(10, 20)
class Demo {
  // 类的原型
  getSum() {
    return this.sum
  }
}
let d = new Demo()
console.log(d.getSum()) //30

  • 返回值装饰器
const addY = target => {
  return 100
}
// 固定写法
@addY
class Demo {
  // 实例
  x = 100
}
console.log(Demo);//100

3、类中属性/方法的装饰器

const readOnly = (target, name, desc) => {
  console.log(target)// 类的原型
  console.log(name)// 属性名x
  console.log(desc)
  // 属性的规则描述
  // configurable: true:是否可以删除
  // enumerable: true:是否可枚举
  // initializer: ƒ ():对于属性来说,内部返回属性的值
  // value: f ():对于方法来说,就是方法本身
  // writable: true:是否可修改
  // 如果有返回值,必须是对象,将替代desc
  return {...}
}
// 固定写法
class Demo {
  // 实例
  @readOnly
  x = 100
  getX() {
    return this.x
  }
}
let d = new Demo()
console.log(d.getX());

mobx 5

// 装饰器
import { observable, autorun, observe, reaction } from 'mobx'
// 公共状态
class Store {
  @observable x = 10;
  @observable y = 20;
  @action.bound change(){
      this.x = 20;
      this.y = 30;
  }
}
let store = new Store
// 传入函数组件,@autorun 只用于类组件
autorun(() => {
  console.log(store.x)//x修改才更新
})

setTimeout(() => {
  // 修改方式1,组件更新两次
  store.x = 20;
  store.y = 30
  // 修改方式2,异步修改,只更新一次
  store.change()
}, 2000)

  • proxy数据劫持公共对象、原始值,设置哪些属性需要被监听;observable
  • 修改发布者;直接改、action.bound保证函数中this始终是实例;
  • 更新对应订阅者;autorun, observe,reaction

mobx6

使用上,不再有装饰器写法,可以不用安装装饰器插件;

  • 创建mobx公共状态
import { runInAction, makeAutoObservable } from 'mobx'
import { getTaskList } from '@/api'

export default class TaskStore {
  constructor(root) {
    this.root = root
    makeAutoObservable(this)
  }
  taskList = null
  async queryAllAsync() {
    let list = []
    try {
      let res = await getTaskList({ state: 0 })
      if (+res.code === 200) {
        list = res.data
      }
    } catch (_) {}
    runInAction(() => {
      this.taskList = list
    })
  }
  completeById(id) {
    let { taskList } = this
    if (Array.isArray(taskList)) {
      this.taskList = taskList.map(item => {
        if (+item.id === +id) {
          item.state = 2
          item.complete = new Date().toLocaleString('zh-CN')
        }
        return item
      })
    }
  }
  deleteById(id) {
    let { taskList } = this
    if (Array.isArray(taskList)) {
      this.taskList = taskList.filter(item => {
        return +item.id !== +id
      })
    }
  }
}

import TaskStore from './TaskStore'

class Store {
  constructor() {
    this.task = new TaskStore(this)
  }
}

export default new Store()
  • 给组件传入store
import store from './mobx-store'
import { Provider } from 'mobx-react'
import Task from './views/mobx-task/Task'
const root = ReactDOM.createRoot(document.getElementById('root'))
// 这个render方法用于渲染真实Dom,与类组件中render函数不同
root.render(
  <ConfigProvider locale={zhCN}>
    {/* 
      
     */}
    {/* 
      
     */}
    <Provider {...store}>
      <Task></Task>
    </Provider>
  </ConfigProvider>
  // 严格模式,会渲染两次,对不安全函数会报红色警告也能执行
  // 
)
  • 子组件使用
// 操作store
import { observer, inject } from 'mobx-react'

const Task = props => {
  // 获取state状态和派发
  let { task } = props
  // task.taskList
  // task.queryAllAsync()等
  ...
}
export default inject('task')(observer(Task))

你可能感兴趣的:(react,react.js,学习,javascript)