【MobX】391- MobX 入门教程(下)
三、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.string
和 store.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 简单实例
这里以简单计数器为例,实现点击按钮,数值累加的简单操作,如图:
在这个案例中,我们引用 mobx-react
库来实现,很明显可以看出 mobx-react
是作为 mobx
和 react
之前的桥梁。
它将 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"))
这些组件对应到我们最后页面效果如图:
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>
}
}
这里需要注意:
可观察数据类型中的数组,实际上并不是数组类型,这里需要用
observablePropTypes.observableArray
去声明它的类型,对象也是一样。@observer
在需要根据数据变换,而改变UI的组件去引用,另外建议有使用到相关数据的类都引用。事实上,我们只需要记住
observer
方法,将所有React
组件用observer
修饰,就是react-mobx
的用法。
4. 使用 Foo 组件
最后我们使用 Foo
组件,需要给它传递两个参数,这样 Bar
组件才能拿到并使用:
ReactDOM.render(
<Foo cache={store.cache}
refresh={store.refresh}
/>,
document.querySelector("#root")
)
结尾
本文参考:
- 《MobX 官方文档》
- 茵风泳月《MobX 入门基础教程》
【MobX】391- MobX 入门教程(下)的更多相关文章
- 【MobX】390- MobX 入门教程(上)
点击上方"前端自习课"关注,学习起来~ 本文考虑到篇幅问题,将<MobX 入门教程>分成上.下两篇文章,方便阅读.分配安排: 一.MobX 介绍 首先看下官网介绍: ★ ...
- django入门教程(下)
在两篇文章帮你入门Django(上)一文中,我们已经做了一个简单的小网站,实现了保存用户数据到数据库,以及从后台数据库读取数据显示到网页上这两个功能. 看上去没有什么问题了,不过我们可以让它变得更加完 ...
- jenkins 入门教程(下)
接上回继续学习jenkins,这次主要来看一些疑难杂症: 一.yum install安装方式 除了直接java -jar jenkins.war方式,还可以用yum安装,这种方式下提供了更多的可配置选 ...
- Odoo进销存(采购、销售、仓库)入门教程 - 下
转帖地址:http://blog.csdn.net/wangnan537/article/details/46475105 2. 进销存实务 2.1 销售产品 李逍遥接到客户苏州美尚邻里超市购买10只 ...
- Spring Boot入门教程1、使用Spring Boot构建第一个Web应用程序
一.前言 什么是Spring Boot?Spring Boot就是一个让你使用Spring构建应用时减少配置的一个框架.约定优于配置,一定程度上提高了开发效率.https://zhuanlan.zhi ...
- Spring Boot入门教程2-1、使用Spring Boot+MyBatis访问数据库(CURD)注解版
一.前言 什么是MyBatis?MyBatis是目前Java平台最为流行的ORM框架https://baike.baidu.com/item/MyBatis/2824918 本篇开发环境1.操作系统: ...
- Spring Cloud 入门教程(四): 分布式环境下自动发现配置服务
前一章, 我们的Hello world应用服务,通过配置服务器Config Server获取到了我们配置的hello信息“hello world”. 但自己的配置文件中必须配置config serve ...
- Unity入门教程(下)
一.概要 在 Unity入门教程(上) 中我们创建了一个游戏项目,并且创建了玩家角色和小球这些游戏对象,还通过添加游戏脚本实现了小方块的弹跳.虽然功能比较简单,但是完整地表现了使用Unity开发游戏的 ...
- Arduino可穿戴开发入门教程Windows平台下安装Arduino IDE
Arduino可穿戴开发入门教程Windows平台下安装Arduino IDE Windows平台下安装Arduino IDE Windows操作系统下可以使用安装向导和压缩包形式安装.下面详细讲解这 ...
随机推荐
- mysql 创建用户及授权(2)
一. MySQL初始密码 新安装的MySQL默认是没有密码的,设置初始密码可以用以下命 mysqladmin -u root password 'new-password' mysqladmin -u ...
- thinkphp 6.0 在 initialize 中重定向无效
thinkphp 6.0 在 initialize 中重定向无效 改用 header() 函数 实例: // header('location:/index.php/模块/控制器/方法'); head ...
- Java开发者入职必备条件
01.基础技术体系 我认为知识技能体系化是判断技术是否过关的第一步.知识体系化包含两层含义: 1. 能够知道技术知识图谱(高清版图谱扫文末二维码)的内容 比如分布式系统中常用的RPC技术,其背后就涉及 ...
- 领扣(LeetCode)转置矩阵 个人题解
给定一个矩阵 A, 返回 A 的转置矩阵. 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引. 示例 1: 输入:[[1,2,3],[4,5,6],[7,8,9]] 输出:[[1,4,7] ...
- 小白学 Python 爬虫(3):前置准备(二)Linux基础入门
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 Linux 基础 CentOS 官网: https: ...
- 访问formData的数据
vant-ui 的 Uploader 上传图片时,用到formData let fd = new FormData(); fd.append('upImgs', file.file); postIma ...
- centos7 设置连接无线wifi
安装系统后,首先要联网. 1.首先使用网线连接,之后尝试ping www.baidu.com我的是自动通的 2.需要查看网卡型号,先安装工具 yum -y install pciutils* 3.查看 ...
- 《Java基础教程》第一章学习笔记
Java 是什么呀! 计算机语言总的来说分成机器语言,汇编语言,高级语言.其中Java一种高级计算机语言,它是一种可以编写跨平台应用软件,完全面向对象的程序设计语言. Java划分为三个技术平台,Ja ...
- GO 单例模式
wiki百科: 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对象的类必须保证只有一个实例存在.许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为.比 ...
- typedef & #defiine & struct
#define(宏定义)只是简单的字符串代换(原地扩展),它本身并不在编译过程中进行,而是在这之前(预处理过程)就已经完成了. typedef是为了增加可读性而为标识符另起的新名称(仅仅只是个别名), ...