可以不使用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
[
"蘋果",
"香蕉",
"栗子"
]