• 【MobX】391- MobX 入门教程(下)


    640?wx_fmt=png
    点击上方“前端自习课”关注,学习起来~

    三、MobX 常用 API 介绍

    3. 修改可观察数据

    在上一部分内容中,我们了解到,对可观察的数据做出反应的时候,需要我们手动修改可观察数据的值。这种修改是通过直接向变量赋值来实现的,虽然简单易懂,但是这样会带来一个较为严重的副作用,就是每次的修改都会触发 autorun 或者 reaction 运行一次。多数情况下,这种高频的触发是完全没有必要的。

    比如用户对视图的一次点击操作需要很多修改 N 个状态变量,但是视图的更新只需要一次就够了。

    为了优化这个问题, MobX 引入了 action

    3.1 (@)action

    action 是修改任何状态的行为,使用 action 的好处是能将多次修改可观察状态合并成一次,从而减少触发 autorun 或者 reaction 的次数。

    可以理解成批量操作,即一次动作中包含多次修改可观察状态,此时只会在动作结束后,做一次性重新计算和反应。

    action 也有两种使用方法,这里以 decorate 方式来介绍。

    import { observable, computed, reaction, action} from 'mobx'
    
    class Store {
        @observable string = 'leo';
        @observable number = 123;
        @action bar(){
            this.string = 'pingan'
            this.number = 100
        }
    }
    let store = new Store()
    reaction(() => [store.string, store.number], arr => {
        console.log(arr)
    })
    store.bar() // ["pingan", 100]
    

    当我们连续去修改 store.stringstore.number 两个变量后,再运行 store.bar() 会发现,控制台值输出一次 ["pingan", 100] ,这就说明 reaction 只被执行一次。

    知识点:action.bound

    另外 action 还有一种特殊使用方法:action.bound,常常用来作为一个 callback 的方法参数,并且执行效果也是一样:

    import { observable, computed, reaction, action} from 'mobx'
    
    class Store {
        @observable string = 'leo';
        @observable number = 123;
        @action.bound bar(){
            this.string = 'pingan'
            this.number = 100
        }
    }
    let store = new Store()
    reaction(() => [store.string, store.number], arr => {
        console.log(arr)
    })
    let bar = store.bar;
    function foo(fun){
        fun()
    }
    foo(bar) //["pingan", 100]
    

    知识点:runInAction(name?, thunk)

    runInAction 是个简单的工具函数,它接收代码块并在(异步的)动作中执行。这对于即时创建和执行动作非常有用,例如在异步过程中。runInAction(f)action(f)() 的语法糖。

    import { observable, computed, reaction, action} from 'mobx'
    class Store {
        @observable string = 'leo';
        @observable number = 123;
        @action.bound bar(){
            this.string = 'pingan'
            this.number = 100
        }
    }
    let store = new Store()
    reaction(() => [store.string, store.number], arr => {
        console.log(arr)
    })
    runInAction(() => {
        store.string = 'pingan'
        store.number = 100
    })//["pingan", 100]
    

    四、 Mobx-React 简单实例

    这里以简单计数器为例,实现点击按钮,数值累加的简单操作,如图:

    640?wx_fmt=png
    2019102301.png

    在这个案例中,我们引用 mobx-react 库来实现,很明显可以看出 mobx-react 是作为 mobxreact 之前的桥梁。

    它将 react 组件转化为对可观察数据的反应,也就是将组件的 render 方法包装成 autorun 方法,使得状态变化时能自动重新渲染。

    详细可以查看:https://www.npmjs.com/package/mobx-react 。

    接下来开始我们的案例:

    1. 安装依赖和配置webpack

    由于配置和前面第二节介绍差不多,所以这里会以第二节的配置为基础,添加配置。

    首先安装 mobx-react 依赖:

    cnpm i mobx-react -D
    

    修改webpack.config.js,在 presets 配置中添加 react 进来:

    // ... 省略其他
    - entry: path.resolve(__dirname, 'src/index.js'),
    + entry: path.resolve(__dirname, 'src/index.jsx'),
    module: {
        rules: [{
            test: /.jsx?$/,
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
                options: {
    -                 presets: ['env'],
    +                 presets: ['env', 'react'],
                    plugins: ['transform-decorators-legacy', 'transform-class-properties']
                }
            }
        }]
    },
    

    2. 初始化 React 项目

    这里初始化一下我们本次项目的简单骨架:

    // index.jsx
    import { observable, action} from 'mobx';
    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    import {observer, PropTypes as observablePropTypes} from 'mobx-react'
    
    class Store {
    }
    const store = new Store();
    class Bar extends Component{
    }
    class Foo extends Component{
    }
    ReactDOM.render(<Foo />, document.querySelector("#root"))
    

    这些组件对应到我们最后页面效果如图:

    640?wx_fmt=png
    2019102302.png

    2. 实现 Store 类

    Store 类用于存储数据。

    class Store {
        @observable cache = { queue: [] }
        @action.bound refresh(){
            this.cache.queue.push(1)
        }
    }
    

    3. 实现 Bar 和 Foo 组件

    实现代码如下:

    @observer
    class Bar extends Component{
        static propTypes = {
            queue: observablePropTypes.observableArray
        }
        render(){
            const queue = this.props.queue;
            return <span>{queue.length}</span>
        }
    }
    
    class Foo extends Component{
        static propTypes = {
            cache: observablePropTypes.observableObject
        }
        render(){
            const cache = this.props.cache;
            return <div>
              <button onClick={this.props.refresh}>点击 + 1</button> 
            当前数值:<Bar queue={cache.queue} />
            </div>
        }
    }
    

    这里需要注意:

    1. 可观察数据类型中的数组,实际上并不是数组类型,这里需要用 observablePropTypes.observableArray 去声明它的类型,对象也是一样。

    2. @observer 在需要根据数据变换,而改变UI的组件去引用,另外建议有使用到相关数据的类都引用。

    3. 事实上,我们只需要记住 observer 方法,将所有 React 组件用 observer 修饰,就是 react-mobx 的用法。

    4. 使用 Foo 组件

    最后我们使用 Foo 组件,需要给它传递两个参数,这样 Bar 组件才能拿到并使用:

    ReactDOM.render(
      <Foo cache={store.cache} 
        refresh={store.refresh}
      />,
      document.querySelector("#root")
    )
    

    结尾

    本文参考:

    • 《MobX 官方文档》
    • 茵风泳月《MobX 入门基础教程》

    个人博客:http://www.pingan8787.com 微信公众号【前端自习课】和千万网友一起,每日清晨,享受一篇前端优秀文章。 目前已连续推送文章 600+ 天,愿每个人的初心都能一直坚持下去!
  • 相关阅读:
    EXCEL中用VLOOKUP功能,根据A列的值,把B列也填充上对应的值
    ReNamer批量重命名文件,如何给杂乱无章的文件名重新命名
    小米手机亲情守护(风筝守护)怎么解绑?
    PHP正则表达式遇到的一个utf8乱码坑
    筹米网你用过没?是套路还是真能帮你提前抢购域名?
    CSS选取第一个、最后一个、偶数、奇数、第n个标签元素
    winscp会话超时及尝试关闭优化连接缓冲大小
    Linux下压缩和解压
    一步一步学Linux下vi/vim的使用(案例比纯理论好学)
    Linux使用find命令,搜索文件名中带有通配符*,报错: paths must precede expression
  • 原文地址:https://www.cnblogs.com/pingan8787/p/11838045.html
Copyright © 2020-2023  润新知