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

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