zoukankan      html  css  js  c++  java
  • React使用Mobx管理数据

    React 和 Vue一样都属于单向数据流,为了更好的进行状态和数据管理官方和第三方也有配套的Redux等插件,本文介绍一个个人觉得更易用使用的组件 Mobx

    核心概念

    MobX 处理你的应用程序状态如下图所示

    常用的几个装饰器 (装饰器解释移步)

    • Actions: 改变state的操作。

    • ObservableState:应用的可被观察的数据状态。

    • Computed: 从state中通过纯函数的操作衍生出的值,state变化它也会跟着变化。

    • Reactions:需要对state变化动态作出反应的东西,它包含不同的概念,基于被观察数据的更新导致某个计算值,或者是发送网络请求以及更新视图等,都属于响应的范畴,这也是响应式编程在 JavaScript 中的一个应用。

    • Autorun: 依赖收集,监听触发,autorun 背后由 reaction 实现。由于 autorun 与 view 的 render 函数很像,我们在 render 函数初始化执行时,使其包裹在 autorun 环境中,第 2 次 render 开始遍剥离外层的 autorun,保证只绑定一遍数据。这样 view 层在原本 props 更新机制的基础上,增加了 autorun 的功能,实现修改任何数据自动更新对应 view 的效果。(ps:使用autoRun实现Mobx-react非常简单,核心思想是将组件外面包上autoRun,这样代码中用到的所有属性都会像上面Demo一样,与当前组件绑定,一旦任何值发生了修改,就直接forceUpdate,而且精确命中,效率最高。)

    React项目中Mobx的安装

    npm或yarn安装插件

    npm install mobx-react --save
    或者
    yarn add mobx-react --save

    装饰器的启用,装饰器目前仍处于提案阶段因此需要做特殊处理

    修改package.json添加如下引用,这个和npm手动安装一个道理

    "@babel/core": "^7.1.0",
        "@babel/plugin-proposal-class-properties": "^7.1.0",
        "@babel/plugin-proposal-decorators": "^7.1.0",
        "@babel/preset-env": "^7.1.0"
    
    使用npm run eject确认显示所有隐藏的配置文件

    注意此步骤不可逆

    在根目录创建.babelrc文件,添加如下内容
    {
      "presets": [
        "@babel/preset-env",
        "@babel/preset-react"
      ],
      "plugins":  [
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        ["@babel/plugin-proposal-class-properties", { "loose": true }]
      ]
    }
    
    删除package.json中babel配置

    几个核心装饰器的解释

    @observable 创建需要被监听的应用状态

    通过对Class的属性简单的使用@observable修饰符,就定义了一个需要被监听的应用状态变量;然后直接在类中定义对应用状态变量的操作;我们就实现了一个灵活的Store层

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import * as serviceWorker from './serviceWorker';
    import TodoBox from './Welcome';
    import {observable, action} from 'mobx';
    
    class Store{
    
        @observable todos=[{
            key:1,
            title: "todo标题",
            done: false,
        },{
            key:2,
            title: "todo-2",
            done: false,
        }];
    }
    

    如上面代码所示,Store是一个store层的类,用来对状态进行管理

    @observer 创建应用状态的监听者

    有多种方式可以创建应用状态的监听者(Reactions),包括autorun、reaction、@observer等

    此处示例显示如何用@observer来监听

    import React, {Component} from 'react';
    import {observer} from "mobx-react";
    import {action} from "mobx";
    
    
    @observer
    class TodoBox extends Component {
    
    
        /**
         *
         * @param props
         */
        constructor(props) {
            super(props);
        }
    
    
        render() {
    
            const store=this.props.store;
            return (
                <div>
                    <ul>
                        {store.todos.map((todo,_) => <li>{todo.title}</li>)}
                    </ul>
                  
                </div>
            )
        }
    }
    
    
    export default TodoBox;
    
    
    @action

    可以看到之前的监听模式下,其实完全可以直接通过store层对数据进行读取和写入,虽然很便捷但却打破了单向数据流向的原则,Mobx也考虑到这点所以特意设计了action,并且要求用户尽可能的使用action来设定更改状态和数据的方法

    class Store{
    
        @observable todos=[{
            key:1,
            title: "todo标题",
            done: false,
        },{
            key:2,
            title: "todo-2",
            done: false,
        }];
    
    
        @action
        changeTitle(){
            // 直接修改仓库中的状态值
            this.todos[0].title = "修改后的todo标题"
        }
    }
    
    

    完整Demo

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import * as serviceWorker from './serviceWorker';
    import TodoBox from './Welcome';
    import {observable, action} from 'mobx';
    
    
    class Store{
    
        @observable todos=[{
            key:1,
            title: "todo标题",
            done: false,
        },{
            key:2,
            title: "todo-2",
            done: false,
        }];
    
    
        @action
        changeTitle(){
            // 直接修改仓库中的状态值
            this.todos[0].title = "修改后的todo标题"
        }
    }
    
    const store1=new Store();
    
    ReactDOM.render(<TodoBox store={store1} />, document.getElementById('root'));
    
    // If you want your app to work offline and load faster, you can change
    // unregister() to register() below. Note this comes with some pitfalls.
    // Learn more about service workers: http://bit.ly/CRA-PWA
    serviceWorker.unregister();
    
    
    import React, {Component} from 'react';
    import {observer} from "mobx-react";
    import {action} from "mobx";
    
    
    @observer
    class TodoBox extends Component {
    
    
        /**
         *
         * @param props
         */
        constructor(props) {
            super(props);
        }
    
    
    
    
        render() {
    
            const store=this.props.store;
            return (
                <div>
                    <ul>
                        {store.todos.map((todo,_) => <li>{todo.title}</li>)}
                    </ul>
                    <div>
                        <input type="button" onClick={() => {
    
                            this.props.store.changeTitle();
                            // // 直接修改仓库中的状态值
                            // this.props.store.todos[0].title = "修改后的todo标题"
                        }} value="点我"/>
                    </div>
    
                </div>
            )
        }
    }
    
    
    export default TodoBox;
    
  • 相关阅读:
    StrCopy、StrCat、StrPas
    WinAPI: FlashWindow 闪烁窗口
    WinAPI: SetVolumeLabel 设置磁盘卷标
    WinAPI: GetActiveWindow 获取当前活动窗口的句柄
    WinAPI: SetCurrentDirectory、GetCurrentDirectory 设置与获取当前目录
    WinAPI: CreateDirectoryEx 根据模版建立文件夹
    WinAPI: CreateDirectory 建立文件夹
    WinAPI: RemoveDirectory 删除空目录
    WinAPI: GetLogicalDriveStrings 获取系统中存在的逻辑驱动器字符串
    filer.js: 一个 Unix 命令风格的 HTML 5 FileSystem API 封装 V2EX
  • 原文地址:https://www.cnblogs.com/linkanyway/p/react-mobx-data-flow.html
Copyright © 2011-2022 走看看