可以不使用redux,在项目代码中直接使用Mobx进行数据状态管理
mobx
- 让项目支持装饰器写法
- 安装mobx mobx-react
如何在组件上使用mobx仓库的数据
- 在最外层包裹一个组件,这个组件由mobx-react提供。还要给这个组件提供一个store数据,属性值就是store的实例
- 使用仓库数据的组件需要通过inject注入Provider组件上的store
- 要去监听仓库数据的变化,需要使用mobx-react中的observer来对组件类做一个装饰
react为使用mobx, 配置装饰器语法
-
安装 decorators 和 mobx
cnpm install --save-dev @babel/plugin-proposal-decorators mobx
-
释放配置文件
npm run eject
-
如果出错:
git add . git commit -am "msg"
-
再去执行释放操作, 完成后进入下一步
-
修改package.json中的babel配置
修改前:
```javascript
"babel": {
"presets": [
"react-app"
]
}
```
修改后:
"babel": {
"presets": [
"react-app"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
]
]
}
vs code报错:对修饰器的实验支持是一项将在将来版本中更改的功能。设置"experimentalDecorators"选项以删除此警告。
文件 > 首选项 > 设置(ctrl + ,)
搜索experimentalDecorators,设置"javascript.implicitProjectConfig.experimentalDecorators": true,该选项默认为false,需要改为true
案例代码:
index.js
import React from 'react'
import ReactDOM from 'react-dom'
// Provider 引入提供者这个组件
import { Provider } from 'mobx-react'
import store from './store'
import App from './App'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById('root'))
App.js
import React from 'react'
import { inject, observer } from 'mobx-react'
@inject('store') // Provider上的store
@observer
class App extends React.Component {
render() {
const {store} = this.props
return (
<div>
<h2>App</h2>
<input type="text" value={store.inputVal} onChange={
(e) => {
let value = e.target.value
// 不推荐直接去修改,推荐使用action
// store.inputVal = value
store.changeInputVal(value)
}
} />
<button onClick={() => {
store.addTodo(store.inputVal)
}}>添加</button>
<p>当前的todos的数量{store.todosSum}</p>
<ul>
{
store.todos.map((item, index) => {
return <li key={index}>{item}</li>
})
}
</ul>
</div>
)
}
componentDidMount() {
this.props.store.initTodos()
}
}
export default App
store/index.js
import { observable, action, computed } from 'mobx'
import * as Mobx from 'mobx'
Mobx.configure({ enforceActions: 'always' }) // 不允许在动作之外进行状态修改
/**
* observable 观察者
* computed 计算属性
* action 方法行为
*/
class AppStore {
@observable inputVal = ''
@observable todos = ['吃饭', '睡觉']
@computed get todosSum() {
return this.todos.length
}
@action changeInputVal(value) {
this.inputVal = value
}
@action addTodo(todo) {
this.todos.push(todo)
this.inputVal = ''
}
// 异步操作 严格模式下有两种方式
@action initTodos() {
fetch('http://localhost:3000/db.json').then(response => response.json()).then(this.setTodo)
}
@action.bound setTodo(data) {
this.todos = data
}
}
export default new AppStore()
public/db.json
[
"苹果",
"香蕉",
"栗子"
]