React 和 Mobx 关系
React 和 MobX 相辅相成,相互合作。
React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用。
mobx的工作流程
1. State(状态)
状态 是驱动应用的数据。 通常有像待办事项列表这样的领域特定状态,还有像当前已选元素的视图状态。 记住,状态就像是有数据的excel表格。
2. Derivations(衍生)
任何 源自状态并且不会再有任何进一步的相互作用的东西就是衍生。 衍生以多种形式存在:
- 用户界面
- 衍生数据,比如剩下的待办事项的数量。
- 后端集成,比如把变化发送到服务器端。
MobX 区分了两种类型的衍生:
- Computed values(计算值) - 它们是永远可以使用纯函数(pure function)从当前可观察状态中衍生出的值。
- Reactions(反应) - Reactions 是当状态改变时需要自动发生的副作用。需要有一个桥梁来连接命令式编程(imperative programming)和响应式编程(reactive programming)。或者说得更明确一些,它们最终都需要实现I / O 操作。
刚开始使用 MobX 时,人们倾向于频繁的使用 reactions。 黄金法则: 如果你想创建一个基于当前状态的值时,请使用 computed
。
回到excel表格这个比喻中来,公式是计算值的衍生。但对于用户来说,能看到屏幕给出的反应则需要部分重绘GUI。
3. Actions(动作)
动作 是任一一段可以改变状态的代码。用户事件、后端数据推送、预定事件、等等。 动作类似于用户在excel单元格中输入一个新的值。
在 MobX 中可以显式地定义动作,它可以帮你把代码组织的更清晰。 如果是在严格模式下使用 MobX的话,MobX 会强制只有在动作之中才可以修改状态。
上手 :
1. 安装 mobx 和 mobx-react 插件
2. 在 src 下新建 store 文件夹
3. 在 store 文件夹下面建对应的 js 文件
基本实例:
store下的 home.js文件
import { observable, action } from 'mobx'
import { get } from '@/utils/request'
import api from '@/services/api'
class Home {
// 定义数据
@observable age = 22
@observable data = []
// 定义方法 action
@action async getData() {
const data = await get(api.hotWordsUrl)
this.data = data.data
}
@action setAge(option) {
this.age = option
}
}
const home = new Home()
export default home
homejsx 文件
import React, { Component } from 'react'
import { observer, inject } from 'mobx-react'
export default
@inject('home') // 多个文件 直接逗号隔开引入
@observer
class Home extends Component {
async componentDidMount() {
// 调用store定义的请求接口数据
await this.props.home.getData()
}
onClick = () => {
// 点击调用改变age的方法
this.props.home.setAge(99)
}
render() {
return (
<div>
{this.props.home.age}
{this.props.home.data.map((v, i) => {
return <p key={i}>{v.title}</p>
})}
<button onClick={this.onClick}>修改Age</button>
</div>
)
}
}
根目录 index.js文件 配置
import React from 'react'
import ReactDOM from 'react-dom'
import Router from './router'
import store from './store/index'
import { Provider } from 'mobx-react'
import './styles/index.less'
ReactDOM.render(
<Provider {...store}>
<Router />
</Provider>,
document.querySelector('#root')
)