【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操作系统下可以使用安装向导和压缩包形式安装.下面详细讲解这 ...
随机推荐
- 力扣(LeetCode)整数反转 个人题解
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: ...
- PHP的两种选择防止sql注入
1.使用PDO: $stmt = $pdo->prepare('SELECT * FROM user WHERE name = :name'); $stmt->execute(array( ...
- Unix, Linux以及NT内核和它们各自衍生的系统关系图
- react antd Table动态合并单元格
示例数据 原始数组 const data = [ { key: '0', name: 'John Brown', age:22, address: 'New York No. 1 Lake Park' ...
- HDFS之DataNode
DataNode工作机制 1)一个数据块在datanode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳. 2)DataNode启动后 ...
- Java核心技术第八章-泛型
摘要 本文根据<Java核心技术 卷一>一书的第八章总结而成,部分文章摘抄书内,作为个人笔记. 文章不会过于深入,望读者参考便好. 为什么要使用泛型程序设计 泛型程序设计(Generic ...
- asp.net core 从 3.0 到 3.1
asp.net core 从 3.0 到 3.1 Intro 今天 .net core 3.1 正式发布了,.net core 3.1 正式版已发布,3.1 主要是对 3.0 的 bug 修复,以及一 ...
- MySQL数据库day20190922
1.dos命令 set names gbk; 2.MySQL练习#创建school数据库: create database school;#切换school数据库: use school; # pri ...
- Nginx源码构建
1.上传或下载nginx软件包,并解压 rz 2.搭建nginx安装环境 yum install gcc-c++ zlib-devel pcre-devel openssl-devel automak ...
- C语言|博客作业10
问题 回答 C语言 博客作业10 这个作业要求在哪里 作业要求 我在这个课程的目标是 熟练循环语句的用法 这个作业在哪个具体方面帮助我实现目标 pta作业 参考文献 <C语言程序设计> 1 ...