Umi 通常会搭配 Dva 使用,用于管理页面状态和逻辑

一、注册 model

首先需要在 .umirc.js 中启用 dva 插件

export default {
plugins: [
['umi-plugin-react', {
dva: {
immer: true,
},
}],
],
}

dva 通过 model 的概念把一个模型管理起来,相当于其他状态管理工具中的 store,通常由以下组成

export default {
namespace: '', // 表示在全局 state 上的 key
state: {}, // 状态数据
reducers: {}, // 管理同步方法,必须是纯函数
effects: {}, // 管理异步操作,采用了 generator 的相关概念
subscriptions: {}, // 订阅数据源
};

在 umi 中会按照约定的目录来注册 model,且文件名会被识别为 model 的 namespace

model 还分为 src/models/*.js 目录下的全局 model,和 src/pages/**/models/*.js 下的页面 model

然后在 src/pages/ 下的页面文件中通过 connect 关联对应的 model

import React, { Component } from 'react';
import { connect } from 'dva';
class PageView extends Component {
render() {
return <div>
<h1>PageView for Dva.Model</h1>
</div>
}
};

// 这里的 pageModel 是对应 model 的 namespace
const mapStateToProps = ({ pageModel }) => {
return { ...pageModel };
}; export default connect(mapStateToProps)(PageView);

上面的 mapStateToProps 方法会将对应 model 中的 state 映射到 props

它接受的第一个参数是所有可以使用的 state,即全局 model 和当前页面 model 的 state,需要通过 namespace 区分

二、简单上手

假如有这样的 model:

经过 connect 之后,可以在页面上可以直接通过 props 获取到 state

如果需要修改 state 的值,可以在 reducers 中添加一个函数

然后在页面上通过 dispatch 调用

被 connect 的 Component 会自动在 props 中拥有 dispatch 方法

它需要一个包含 typepayload 的对象作为入参

其中 type 是需要调用的方法名,可以是 reducer 或者 effect,不过需要添加对应 model 的 namespace

payload 是需要传递的信息,可以在被调用的方法中接收

从这里可以看出,只要 State 有变化,视图层就会自动更新

这里就需要介绍一下 dva 的五个核心元素:

State:一个对象,保存整个应用状态

View:React 组件构成的视图层

Action:一个对象,描述事件

connect 方法:一个函数,绑定 State 到 View

dispatch 方法:一个函数,发送 Action 到 State

在 Dva 中,State 是储存数据的地方,我们通过 dispatch 触发 Action,然后更新 State。

如果有 View 使用 connect 绑定了 State,当 State 更新的时候,View 也会更新。

三、异步函数

Dva 中的异步操作都放到 effects 中管理,基于 Redux-saga 实现

Effect 是一个 Generator 函数,内部使用 yield 关键字,标识每一步的操作

每一个 effect 都可以接收两个参数:

1. 包含 dispatch 携带参数 payload 的 action 对象

2. dva 提供的 effect 函数内部的处理函数集

第二个参数提供的处理函数中,常用的有 call、put、select

call: 执行异步函数

put: 发出一个 Action,类似于 dispatch

select: 返回 model 中的 state

完整的示例:

import * as services from '@/services';
export default {
namespace: 'pageModel',
state: {
title: 'Welcome to Wise.Wrong\'s Bolg',
name: 'wise'
},
effects: {
*testEffect({ payload }, { call, put, select }) {
// 获取 state 中的值
const { name } = yield select(state => state.pageModel);
// 接口入参
const params = { name, ...payload };
// services.getInfo 是封装好的请求
const { data } = yield call(services.getInfo, params);
// 请求成功之后,调用 reducer 同步方法更新 state
yield put({
// 调用当前 model 的 action 不需要添加 namespace
type: 'changeTitle',
payload: data,
});
}
},
reducers: {
changeTitle(state, { payload }) {
return {
...state,
title: payload
};
},
},
};

四、常见问题

1. 在 effects 中,如何同步调用两个异步函数?

如果在一个 effect 中,函数 B 的入参需要依赖于函数 A 的执行结果,可以使用 @@end 来阻塞当前的函数

2. 在 model 中使用 router ?

在 model 中引入 umi/router 即可

import router from 'umi/router';

...
router.push(`?${qs.stringify(search)}`);

3. 全局 layout 使用 connect 后路由切换不更新页面

需用 withRouter 高阶一下,注意顺序

import withRouter from 'umi/withRouter';

const mapStateToProps = (state) => {
// ...
}; export default withRouter(connect(mapStateToProps)(Layout));

Umi 小白纪实(二)—— model 的注册与使用的更多相关文章

  1. Umi 小白纪实(三)—— 震惊!路由竟然如此强大!

    在<Umi 小白纪实(一)>中有提到过简单的路由配置和使用,但这只是冰山一角 借用一句广告词,Umi 路由的能量,超乎你的想象 一.基本用法 Umi 的路由根结点是全局 layout  s ...

  2. Umi 小白纪实(一)—— 创建项目&常用配置

    umi 是一个企业级 react 应用框架,也是蚂蚁金服的底层前端框架 <蚂蚁金服的前端框架和工程化实践> 一.安装脚手架 在创建项目之前,需要保证有 node 8.10 以上的环境 可以 ...

  3. HTML 事件(二) 事件的注册与注销

    本篇主要介绍HTML元素事件的注册.注销的方式. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流.事件委托 4. ...

  4. node.js 初学(二)—— 搭建注册/登录服务器

    node.js 初学(二)—— 搭建注册/登录服务器 理论上来说,代码实现在理论和实际上是一样的.但实际上来说,他们不是 做一个最简单的用户注册登录功能 1.接口定义: 注册:/user?act=re ...

  5. SpringCloud实战之初级入门(二)— 服务注册与服务调用

    目录 1.环境介绍 2.服务提供 2.1 创建工程 2.2 修改配置文件 2.3 修改启动文件 2.5 亲测注意事项 3.服务调用 3.1 创建工程 3.2 修改配置文件 3.3 修改启动文件 3.4 ...

  6. SpringCloud(二)- 服务注册与发现Eureka

    离上一篇微服务的基本概念已经过去了几个月,在写那篇博客之前,自己还并未真正的使用微服务架构,很多理解还存在概念上.后面换了公司,新公司既用了SpringCloud也用了Dubbo+Zookeeper, ...

  7. 【Spring Cloud学习之二】服务注册和发现

    环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 Spring Cloud 1.2 一.EurekaEureka是Netflix开源的一个RESTful服务,主要用于服 ...

  8. 玩转springcloud(二):注册中心-Eureka

    一.简介 注册中心 注册中心是服务发现的核心.它保存了各个可用服务实例的网络地址(IP Address和Port).服务注册中心必须要有高可用性和实时更新功能. Netflix Eureka 就是一个 ...

  9. Dubbo系列之 (二)Registry注册中心-注册(2)

    引导 本章主要介绍下AbstractRegistry.FailbackRegistry的作用和源码. AbstractRegistry 首先,直接引出这个类的作用,该类主要把服务提供者信息缓存本地文件 ...

随机推荐

  1. Springboot | 私人订制你的banner

    1. 搭建一个springboot模块 2. 配置POM文件 3. 自定义banner 3.1 自定义文字字符图案banner 3.2 自定义图案字符图案banner 自定义banner有什么用呢? ...

  2. 微服务之docker(二)

    一.SpringCloud/SpringBoot整合docker 使用docker的maven组建构建springboot应用(官方文档:https://spring.io/guides/gs/spr ...

  3. c和c++中读取数据的方式总结

    目录 c 输出 printf() 输入 scanf getchar(), putchar() gets(), puts() c++ 输入 cin() getline() get() 输出 cout 最 ...

  4. 在jsp页面下, 让eclipse完全支持HTML/JS/CSS智能提示

    我们平时用eclipse开发jsp页面时智能提示效果不太理想,今天用了两个小时发现了eclipse也可以像Visual Studio 2008那样完全智能提示HTML/JS/CSS代码,使用eclip ...

  5. Linux系统实现ansible自动化安装配置httpd

    1.使用ansible的playbook实现自动化安装httpd 1)首先配置好ansible的hosts文件,让其对应主机能够受ansible控制 提示:我们在主机清单上配置了所管控的主机地址,但是 ...

  6. Mutual Information

    Mutal Information, MI, 中文名称:互信息. 用于描述两个概率分布的相似/相关程度. 常用于衡量两个不同聚类算法在同一个数据集的聚类结果的相似性/共享的信息量. 给定两种聚类结果\ ...

  7. Codeforces_731_F

    http://codeforces.com/problemset/problem/731/F 其实是暴力枚举,但是有些小技巧,直接保存每个数的数量. 枚举每个起点时,然后依次加上起点大小的分段的数量的 ...

  8. [转载]goldendict下优质词典简介及安装

    使用Arch Linux一年以来,如果要问自己最为中意的词典程序是? 当然是Goldendict啦!想详细了解这款瑞士军刀的请猛戳这里. 以前在Win下都是用的lingoes, 感觉还不错,词典库很全 ...

  9. java 利用POI 读取Execel数据的真实行数

    java 利用poi 读execel文件的操作,读取总的数据行数一般是通过调用 sheet.getLastRowNum() ;可是这样有时候会出现一些问题,例如,当其中一行的数据的确都为空,可是其原本 ...

  10. Go语言实现:【剑指offer】题目汇总

    所列题目与牛客网<剑指offer>专题相对应. 数组: 和为S的两个数字 和为S的连续正数序列 连续子数组的最大和 数字在排序数组中出现的次数 数组中只出现一次的数字 旋转数组的最小数字 ...