MobX實現組件通訊的小案例

可以不使用redux,在項目代碼中直接使用Mobx進行數據狀態管理

mobx

  1. 讓項目支持裝飾器寫法
  2. 安裝mobx mobx-react

如何在組件上使用mobx倉庫的數據

  1. 在最外層包裹一個組件,這個組件由mobx-react提供。還要給這個組件提供一個store數據,屬性值就是store的實例
  2. 使用倉庫數據的組件需要通過inject注入Provider組件上的store
  3. 要去監聽倉庫數據的變化,需要使用mobx-react中的observer來對組件類做一個裝飾

react爲使用mobx, 配置裝飾器語法

  1. 安裝 decorators 和 mobx

    cnpm install --save-dev @babel/plugin-proposal-decorators mobx
    
  2. 釋放配置文件

    npm run eject
    
  3. 如果出錯:

    git add .
    git commit -am "msg"
    
  4. 再去執行釋放操作, 完成後進入下一步

  5. 修改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

[
    "蘋果",
    "香蕉",
    "栗子"
]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章