也是代替原生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
"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());
// 装饰器
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)
observable
直接改、action
,.bound
保证函数中this始终是实例;autorun, observe,reaction
使用上,不再有装饰器写法,可以不用安装装饰器插件;
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()
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))