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. I Love GPLT

    这道超级简单的题目没有任何输入. 你只需要把这句很重要的话 —— “I Love GPLT”——竖着输出就可以了. 所谓“竖着输出”,是指每个字符占一行(包括空格),即每行只能有1个字符和回车. 输入 ...

  2. 15、WAN

    WAN wide area network 覆盖较大地理范围的数据通信网络使用网络提供商和电信公司所提供的传输设施传输数据 通过不同WAN协议,将LAN延伸到远程站点的其他LAN广域网接入处于OSI七 ...

  3. OS课程 ucore_lab2实验报告

    练习零:填写已有实验    本实验依赖实验1.请把你做的实验1的代码填入本实验中代码中有"LAB1"的注释相应部分.提示:可采用diff和patch工具进行半自动的合并(merge ...

  4. LeetCode 200. Number of Islands 岛屿数量(C++/Java)

    题目: Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is s ...

  5. java代码之美(16) ---Java8 Optional

    Java8 Optional 一句话介绍Optional类:使用JDK8的Optional类来防止NullPointerException(空指针异常)问题. 一.前言 在我们开放过程中,碰到的异常中 ...

  6. Django表单Form类对空值None的替换

    最近在写项目的时候用到Form,发现这个类什么都好,就是有些空值的默认赋值真是很不合我胃口. 查阅资料.官方文档后发现并没有设置该值的方式.于是,便开始了我的踩坑之路...... 不过现在完美解决了, ...

  7. 十篇笔记走向Python测试开发之路四(字典)

    字典 字典(dict)是Python的一种内置的数据结构.在其他语言中也称为map,使用键-值(key-value)存储,可以通过查找某个特定的词语(键 key),从而找到他的定义(值 value) ...

  8. 通过 Serverless 加速 Blazor WebAssembly

    Blazor ❤ Serverless 我正在开发 Ant Design 的 Blazor 版本,预览页面部署在 Github Pages 上,但是加载速度很不理想,往往需要 1 分钟多钟才完成. 项 ...

  9. Linux 配置 DNS

    这里不讨论如何在linux上搭建一台DNS服务器: 这里讨论的是 配置 linux系统,让其能够解析域名,使用户可以流畅使用Internet 先了解几个文件,位于/etc目录下的有:hosts,hos ...

  10. React之JSX的语法细节

    带注释 import React, { Component, Fragment } from 'react' import './style.css' class TodoList extends C ...