全局状态管理 Mobx。
设计理念:任何从应用派生出的状态,都应被自动(获得更新),包括UI、序列化数据、服务通信等。
Mobx
使用了class
语法以及装饰器,参考:ES6 class语法、装饰器
在create-react-app
配置使用mobx
由于mobx
使用了装饰器语法,所以需要配置在react中使用装饰器@**
首先,安装mobx/mobx-react
npm install mobx mobx-react
通过增加babelbabel-preset-mobx
,预设支持。
npm install babel-preset-mobox --save-dev
最后配置config-overrides.js
,
const {
override,
addWebpackAlias,
addBabelPresets,
} = require("customize-cra");
const path = require("path");
module.exports = override(
// 预设支持 mobx 装饰器语法
...addBabelPresets(["mobx"]),
addWebpackAlias({
["@Component"]:path.resolve(__dirname,'src/example')
})
);
mobx/mobx-react
使用
mobx
通过
observable
观测属性,computed
计算属性,通过已观测属性计算出新属性;
用户实体类对象声明;用户列表实体对象声明。
/**
* 用户属性监听
*/
import {observable,computed} from 'mobx';
// 单用户实体信息
class UserInfo{
id = Date.now();
@observable name = "";
@observable age = "";
@observable online = false;
constructor(name,age,online){
this.name = name;
this.age = age;
this.online = online
}
}
// 多用户列表
class UserList{
constructor(list){
this.userList = list;
}
@observable userList = [];
@computed get onlineNum(){
// 统计用户列表中在线用户
return this.userList.filter(user=>user.online).length;
}
}
export {UserInfo,UserList}
在react
中使用mobx
,通过mobx-react
可关联观测组件,所有依赖观测属性的组件,在属性变化时触发组件更新。
/**
* Mobx.js 用于全局状态管理
* Mobx-react 将mobx全局数据状态绑定到react
*/
import React from 'react';
import {observer} from 'mobx-react';
import {Form,Checkbox} from 'antd';
import {UserInfo,UserList} from './UserInfo';
@observer
class ListUser extends React.Component{
constructor(props){
super(props);
this.state = {}
}
render(){
return (<div>
<p>Online Total:{this.props.userList.onlineNum}</p>
<ul>
{this.props.userList.userList.map(user=><UserItem key={user.id} user={user} />)}
</ul>
</div>)
}
}
const formLayout = {
labelCol:{
span:3
},
wrapperCol:{
span:4
}
}
const UserItem = observer(({user})=><li>
<Form layout="horizontal" {...formLayout} initialValues={{
'online':user.online
}}>
<Form.Item label="姓名" name="name">
<span>{user.name}</span>
</Form.Item>
<Form.Item label="年龄" name="age">
<span>{user.age}</span>
</Form.Item>
<Form.Item label="是否在线" name="online" valuePropName="checked">
<Checkbox onChange={e=>user.online = e.target.checked} />
</Form.Item>
</Form>
</li>);
测试组件ListUser
,传入props属性userList
// 测试数据
let user1 = new UserInfo("admin",32,true);
let user2 = new UserInfo("test",12,false);
let user3 = new UserInfo("小明",22,false);
let list = new UserList([user1,user2,user3]);
export default function MobxDemo(){
return (<ListUser userList = {list} />)
};
测试截图:
核心API
常用的用于状态属性管理的API说明。
observable
,创建可观测属性,包括基本数据类型/引用类型、类实例、数组和映射。
observable(value)
方法创建;// 直接使用observable 方法,定义观测数据对象 let store = observable({ name:"hello" }); // 定义观测组件 const Test = observer((props)=><> <span>{props.obj.name}</span> <button onClick={e=>props.obj.name="world"}>更新</button> </>); // 组件使用,传入数据 <Test obj = {store} />
@observable classProperty = value
观测class类属性
装饰器相关,调节属性的可观察性。控制特定属性的转换规则。
computed
创建一个计算的衍生属性。action
创建一个动作,用于更新状态;可以用于处理异步动作。decorate
无法使用装饰器@
,可应用属性观测的方法// 手动定义可观测对象的属性的观测方式 decorate(UserList,{ userList:observable, onlineNum:computed });
autorun(fn)
创建一个响应式函数,初始立即触发一次啊,然后依赖关系改变时再次被触发。执行后返回一个清理autorun 的函数when(()=>Boolean,effect?:()=>void,options)
观察并运行给定的语句,知道返回true。一旦返回true,执行effect
比较redux
对比redux
,个人方面使用更顺手,同Vue.js
绑定原理一样,通过收集依赖组件,对其进行更新:
- 使用装饰器
@**
更简洁的属性、组件观测。 - 使用class语法声明对象实体,观测属性声明。
- 属性更新的方式,直接通过元素的监听事件更新或者更新传入观测组建的对象
// 动态更新 传入ListUser组件的属性对象 setTimeout(()=>{ list.userList.push(new UserInfo("小李",20,false)); },3000); export default function MobxDemo(){ return (<ListUser userList = {list} />) };
局限:
Observable
数组并非真正的数组,在传递给第三方库之前,通过.slice()
操作。- 对已存在的observable对象动态添加属性不会被捕获,可通过映射代替或者使用工具函数