当前位置: 首页 > 编程日记 > 正文

DvaJS 入门, 快速上手Dva

为什么要使用Dva?

React 没有解决的问题

React 本身只是一个 DOM 的抽象层,使用组件构建虚拟 DOM。

如果开发大应用,还需要解决一个问题。

  • 通信:组件之间如何通信?
  • 数据流:数据如何和视图串联起来?路由和数据如何绑定?如何编写异步逻辑?等等

#通信问题

组件会发生三种通信。

  • 向子组件发消息
  • 向父组件发消息
  • 向其他组件发消息

React 只提供了一种通信手段:传参。对于大应用,很不方便。

目前流行的数据流方案

  • 路由: React-Router
  • 架构: Redux
  • 异步操作: Redux-saga

Dva介绍

dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。dva 是 React 应用框架,将三个 React 工具库( React-Router + Redux + Redux-saga )包装在一起,简化了 API,让开发 React 应用更加方便和快捷。

dva = React-Router + Redux + Redux-saga

特性

  • 易学易用,仅有 6 个 api,对 redux 用户尤其友好,配合 umi 使用后更是降低为 0 API
  • elm 概念,通过 reducers, effects 和 subscriptions 组织 model
  • 插件机制,比如 dva-loading 可以自动处理 loading 状态,不用一遍遍地写 showLoading 和 hideLoading
  • 支持 HMR,基于 babel-plugin-dva-hmr 实现 components、routes 和 models 的 HMR

数据流图

#核心概念

  • State:一个对象,保存整个应用状态
  • View:React 组件构成的视图层
  • Action:一个对象,描述事件
  • connect 方法:一个函数,绑定 State 到 View
  • dispatch 方法:一个函数,发送 Action 到 State

#State 和 View

State 是储存数据的地方,收到 Action 以后,会更新数据。

View 就是 React 组件构成的 UI 层,从 State 取数据后,渲染成 HTML 代码。只要 State 有变化,View 就会自动更新。

#Action

Action 是用来描述 UI 层事件的一个对象。

{type: 'click-submit-button',payload: this.form.data
}

#connect 方法

connect 是一个函数,绑定 State 到 View。

import { connect } from 'dva';function mapStateToProps(state) {return { todos: state.todos };
}
connect(mapStateToProps)(App);

connect 方法返回的也是一个 React 组件,通常称为容器组件。因为它是原始 UI 组件的容器,即在外面包了一层 State。

connect 方法传入的第一个参数是 mapStateToProps 函数,mapStateToProps 函数会返回一个对象,用于建立 State 到 Props 的映射关系。

#dispatch 方法

dispatch 是一个函数方法,用来将 Action 发送给 State。

dispatch({type: 'click-submit-button',payload: this.form.data
})

dispatch 方法从哪里来?被 connect 的 Component 会自动在 props 中拥有 dispatch 方法。

Model(处理数据和逻辑)

完成 UI 后,现在开始处理数据和逻辑。

dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions 。

新建 model models/products.js :

export default {namespace: 'products',state: [],reducers: {'delete'(state, { payload: id }) {return state.filter(item => item.id !== id);},},
};

这个 model 里:

  • namespace 表示在全局 state 上的 key
  • state 是初始值,在这里是空数组
  • reducers 等同于 redux 里的 reducer,接收 action,同步更新 state

然后别忘记在 index.js 里载入他:

// 3. Model
+ app.model(require('./models/products').default);

Models内包含的:

#State

type State = any

State 表示 Model 的状态数据,通常表现为一个 javascript 对象(当然它可以是任何值);操作的时候每次都要当作不可变数据(immutable data)来对待,保证每次都是全新对象,没有引用关系,这样才能保证 State 的独立性,便于测试和追踪变化。

在 dva 中你可以通过 dva 的实例属性 _store 看到顶部的 state 数据,但是通常你很少会用到:

const app = dva();
console.log(app._store); // 顶部的 state 数据

#Action

type AsyncAction = any

Action 是一个普通 javascript 对象,它是改变 State 的唯一途径。无论是从 UI 事件、网络回调,还是 WebSocket 等数据源所获得的数据,最终都会通过 dispatch 函数调用一个 action,从而改变对应的数据。action 必须带有 type 属性指明具体的行为,其它字段可以自定义,如果要发起一个 action 需要使用 dispatch 函数;需要注意的是 dispatch 是在组件 connect Models以后,通过 props 传入的。

dispatch({type: 'add',
});

#dispatch 函数

type dispatch = (a: Action) => Action

dispatching function 是一个用于触发 action 的函数,action 是改变 State 的唯一途径,但是它只描述了一个行为,而 dipatch 可以看作是触发这个行为的方式,而 Reducer 则是描述如何改变数据的。

在 dva 中,connect Model 的组件通过 props 可以访问到 dispatch,可以调用 Model 中的 Reducer 或者 Effects,常见的形式如:

dispatch({type: 'user/add', // 如果在 model 外调用,需要添加 namespacepayload: {}, // 需要传递的信息
});

#Reducer

type Reducer<S, A> = (state: S, action: A) => S

Reducer(也称为 reducing function)函数接受两个参数:之前已经累积运算的结果和当前要被累积的值,返回的是一个新的累积结果。该函数把一个集合归并成一个单值。

Reducer 的概念来自于是函数式编程,很多语言中都有 reduce API。如在 javascript 中:

[{x:1},{y:2},{z:3}].reduce(function(prev, next){return Object.assign(prev, next);
})
//return {x:1, y:2, z:3}

在 dva 中,reducers 聚合积累的结果是当前 model 的 state 对象。通过 actions 中传入的值,与当前 reducers 中的值进行运算获得新的值(也就是新的 state)。需要注意的是 Reducer 必须是纯函数,所以同样的输入必然得到同样的输出,它们不应该产生任何副作用。并且,每一次的计算都应该使用immutable data,这种特性简单理解就是每次操作都是返回一个全新的数据(独立,纯净),所以热重载和时间旅行这些功能才能够使用。

#Effect

Effect 被称为副作用,在我们的应用中,最常见的就是异步操作。它来自于函数编程的概念,之所以叫副作用是因为它使得我们的函数变得不纯,同样的输入不一定获得同样的输出。

dva 为了控制副作用的操作,底层引入了redux-sagas做异步流程控制,由于采用了generator的相关概念,所以将异步转成同步写法,从而将effects转为纯函数。至于为什么我们这么纠结于 纯函数,如果你想了解更多可以阅读Mostly adequate guide to FP,或者它的中文译本JS函数式编程指南。

#Subscription

Subscriptions 是一种从  获取数据的方法,它来自于 elm。

Subscription 语义是订阅,用于订阅一个数据源,然后根据条件 dispatch 需要的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。

import key from 'keymaster';
...
app.model({namespace: 'count',subscriptions: {keyEvent({dispatch}) {key('⌘+up, ctrl+up', () => { dispatch({type:'add'}) });},}
});

#Router

这里的路由通常指的是前端路由,由于我们的应用现在通常是单页应用,所以需要前端代码来控制路由逻辑,通过浏览器提供的 History API 可以监听浏览器url的变化,从而控制路由相关操作。

dva 实例提供了 router 方法来控制路由,使用的是react-router。

import { Router, Route } from 'dva/router';
app.router(({history}) =><Router history={history}><Route path="/" component={HomePage} /></Router>
);

#Route Components

在组件设计方法中,我们提到过 Container Components,在 dva 中我们通常将其约束为 Route Components,因为在 dva 中我们通常以页面维度来设计 Container Components。

所以在 dva 中,通常需要 connect Model的组件都是 Route Components,组织在/routes/目录下,而/components/目录下则是纯组件(Presentational Components)。

connect (翻译成中文就是链接)

dva 提供了 connect 方法。如果你熟悉 redux,这个 connect 就是 react-redux 的 connect 。

Dva 概念

数据流向(重要)

数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State,所以在 dva 中,数据流向非常清晰简明,并且思路基本跟开源社区保持一致(也是来自于开源社区)。

相关文章:

Static、DynamicResource学习笔记一

定义了资源后&#xff0c;我们可以在元素中直接使用该资源&#xff0c;但又分为StaticResource及DynamicResource两种方式。 StaticResource 静态资源在首次创建窗口时一次性的设置完毕&#xff0c;之后源资源对象本身发生的任何变化都会影响到使用该资源的元素&#xff0c;如果…

javascript迭代器_JavaScript迭代器概述

javascript迭代器by Joanna Gaudyn乔安娜高登(Joanna Gaudyn) JavaScript迭代器概述 (An overview of JavaScript iterators) for&#xff0c;for…in和for…of循环之间的区别 (The difference between for, for…in and for…of loops) Iteration might be one of the most c…

knockout学习笔记目录

关于knockout学习系列的文章已经写完&#xff0c;这里主要是做个总结&#xff0c;并且将目录罗列出来&#xff0c;方便查看。欢迎各位大神拍砖和讨论。 总结 kncokout是一个轻量级的UI类库&#xff0c;通过MVVM模式使前端的UI简单话&#xff0c;减少javascript代码的编写。通常…

ant Design Pro 登录状态管理

未登录自动跳转到登录页面&#xff0c;登录成功不跳转回登录页面的实现代码调用流程。 ant Design Pro 是一个企业中后台管理框架&#xff0c;开始做他&#xff0c;第一个肯定是要做登录&#xff0c;下面来看一下它是怎么登录的。 先看路由配置 Authorized.jsx代码&#xff1…

初级java开发学习路线_成为初级全栈Web开发人员的10分钟路线图

初级java开发学习路线So you have started your journey into the world of web development. But what do you learn first? The Internet is overloaded with a wealth of information about the millions of different technologies that a web developer can know.因此&am…

国外物联网平台初探(四):Ayla Networks

定位 Ayla企业软件解决方案为全球部署互联产品提供强大的工具 功能 Ayla的IoT平台包含3个主要组成部分&#xff1a; (1) Ayla嵌入式代理Ayla Embedded Agents (2) Ayla云服务Ayla Cloud Services (3) Ayla应用库Ayla Application Libraries 设备 开发者使用任何微控制器、操作系…

《英语语法新思维初级教程》学习笔记(一)名词短语

参考资料&#xff1a; 1. 《英语语法新思维初级教程》 ▶ 知识点 ▼ 英语是“固定词序语言&#xff08;a fixed-word-order language&#xff09;”。 ▼ 语言的构造级别分五个层次&#xff1a;1. 词&#xff08;word&#xff09;&#xff1b;2. 短语&#xff08;phase&#xf…

根据数组中对象的属性值排序倒叙

数组中对象的属性值排序倒叙demo function compare(e) {return function (a, b) {var value1 a[e];var value2 b[e];return parseInt(value1) - parseInt(value2);} } var arr[{a:2},{a:3},{a:1}];var arr2 arr.sort(compare(time)).reverse();console.log(arr2) //[{a:3}…

!! javascript_产量! 产量! 生成器如何在JavaScript中工作。

!! javascriptby Ashay Mandwarya ?️??由Ashay Mandwarya提供吗&#xff1f; 产量&#xff01; 产量&#xff01; 生成器如何在JavaScript中工作。 (Yield! Yield! How Generators work in JavaScript.) If the title doesn’t already give a hint, we will be discussin…

ACM 竞赛高校联盟 练习赛 第二场 BC

B. 题解&#xff1a; 枚举约数即可&#xff0c;判断n个数能否填约数的整数倍 #include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long LL; int main(){LL T, n, m;cin>>T;while(T--){cin>>n>>…

在一个数组中查找两个重复出现的数字

题目如下&#xff1a;现有一个数组长度为n1&#xff0c;里面存放有1到n-2&#xff0c;顺序不定&#xff0c;其中有两个数字出现了两次&#xff0c;现在要找出那两个数字。 例子A{2, 3, 1, 4, 5, 2, 4}&#xff0c; 这个数组长度为7&#xff0c;存放了1到5&#xff0c;但2和4出现…

React 组件生命周期

组件的生命周期可分成三个状态&#xff1a; Mounting&#xff1a;已插入真实 DOMUpdating&#xff1a;正在被重新渲染Unmounting&#xff1a;已移出真实 DOM 生命周期的方法有&#xff1a; componentWillMount 在渲染前调用,在客户端也在服务端。 componentDidMount : 在第一…

银行软件开发实习生_如何找到学生的软件开发人员实习生

银行软件开发实习生by Grazietta Hof由Grazietta Hof 如何找到学生的软件开发人员实习生 (How to find a Software Developer Internship as a student) Side note: Although this article is directed at students (because I am one so I can easily relate), I’m sure a l…

MAC OS X El CAPITAN 搭建SPRING MVC (1)- 目录、包名、创建web.xml

一、 下载STS&#xff08;Spring Tool Suite&#xff09; 官方地址&#xff1a;http://spring.io/tools/sts 下载spring tool suite for mac 最新版本。这个IDE是很不错的&#xff0c;其中spring插件已经配置好了。下载解压缩&#xff08;一定要英文目录下&#xff09;&#xf…

iOS小知识点记录

1>UITextField实现leftView: self.inputTextField [[UITextField alloc]initWithFrame:CGRectMake(10, 10, 200, 25)];self.inputTextField.delegate self;self.inputTextField.font [UIFont systemFontOfSize:15];self.inputTextField.placeholder " 想说点什么?…

Ant Design Pro 网络请求,视图绑定model并且渲染到页面 umi-request

封装网络请求,在service中新建接口,在model调用service,在视图绑定model并且得到网络请求的回调函数,获取网络请求的数据渲染到页面。 网络请求数据走向; 1.在utils/request.js 封装网络请求; /*** request 网络请求工具* 更详细的 api 文档: https://github.com/umijs…

2019机器学习比赛_2019顶尖的机器学习课程

2019机器学习比赛With strong roots in statistics, Machine Learning is becoming one of the most interesting and fast-paced computer science fields to work in. There’s an endless supply of industries and applications machine learning can be applied to to mak…

HTML5 canvas画图

HTML5 canvas画图 HTML5 <canvas> 标签用于绘制图像&#xff08;通过脚本&#xff0c;通常是 JavaScript&#xff09;。不过&#xff0c;<canvas> 元素本身并没有绘制能力&#xff08;它仅仅是图形的容器&#xff09; - 您必须使用脚本来完成实际的绘图任务。getCo…

排序算法7---快速排序算法

原理&#xff1a; 通过一趟排序将待排记录分割成独立的两部分&#xff0c;其中一部分记录的关键字均比另一部分记录的关键字小&#xff0c;则可分别对这两部分记录继续进行排序&#xff0c;以达到整个序列有序的目的。 #include <stdio.h> #define MAXSIZE 9typedef stru…

dispatch callback ant design pro 网络请求回调函数

index.jsx 代码解析:在组件初次渲染时调用 model 中 命名空间为 a_models 的 getData 网络请求,传了一个patload 参数和 callback 回调函数过去,然后通过 this.setState ()更新视图的 state。 import { Form, Tabs,Affix, Button,Input,Table } from antd; import Re…

bigquery使用教程_如何使用Python和Google BigQuery构建机器人以自动执行您的笨拙任务...

bigquery使用教程Do you have repetitive tasks? Something that you do regularly, every week or even every day? Reporting might be one of your weekly or daily tasks. You query or ask for the data, and do some visualizations, then give it to your boss. What …

5S后返回首页

1 <!DOCTYPE html>2 <html>3 <head>4 <title>5S后返回首页</title> 5 <meta http-equiv"Content-Type" content"text/html; charsetgkb"/> 6 </head>7 <body>8 <h2>操作成功</h2>…

TypeScript 1

TypeScript 的由来 TypeScript 是 JavaScript 的一个超集&#xff0c;支持 ECMAScript 6 标准。 TypeScript 由微软开发的自由和开源的编程语言。 TypeScript 设计目标是开发大型应用&#xff0c;它可以编译成纯 JavaScript&#xff0c;编译出来的 JavaScript 可以运行在任何…

大龄屌丝自学笔记--Java零基础到菜鸟--028

泛型&#xff0c;for循环增强应用&#xff0c;静态导入&#xff0c;可变参数&#xff0c;asList() 1、泛型 约束了数据类型&#xff0c;格式为 <数据类型>&#xff0c;如&#xff1a;ArrayList<int> aListnew ArrayList<int>(); 泛型通配符&#xff1a;<?…

c# typescript_在任何IDE中从C#,Java或Python代码获取TypeScript接口的简单方法

c# typescriptby Leonardo Carreiro莱昂纳多卡雷罗(Leonardo Carreiro) 在任何IDE中从C&#xff03;&#xff0c;Java或Python代码获取TypeScript接口的简单方法 (The easy way to get TypeScript interfaces from C#, Java, or Python code in any IDE) Who has never experi…

js里的document对象大全(DOM操作)

什么是DOM document object model 的简称&#xff0c;意思为文档对象模型。主要用来对文档中的html节点进行操作。 Dom的操作简单示例&#xff1a; <div id"t1"><div><input type"file" /> <input type"button" value"…

【制作镜像】BCEC制作镜像

如要制作的新镜像已存在标准版本镜像&#xff0c;即linux发行版本相同&#xff08;此处指CentOS6.5 64位&#xff09;&#xff0c;可利用BCEC制作。 在BCEC创建centos6.5系统的可联外网的虚机&#xff0c;ssh到此虚机&#xff0c;用yum方式安装所需的功能&#xff1a; yum&…

Ant Design Pro 组件事件绑定 Input onChange

Input 组件的 onChange 事件绑定语法 render() {this.shop_change e > {const { value } e.target;console.log(shop_change,value)};return (<Input placeholder"" onChange{this.shop_change}></Input>)}

软件访问转向本地_我是如何从完整的初学者转向软件开发人员的,以及如何做到的...

软件访问转向本地by Madison Kanna麦迪逊卡纳(Madison Kanna) 我是如何从完整的初学者转向软件开发人员的&#xff0c;以及如何做到的 (How I went from complete beginner to software developer — and how you can too) Two years ago, I was right where you are today.两…

.NET笔试题集(五)

转载于&#xff1a;http://www.cnblogs.com/ForEvErNoME/archive/2012/09/15/2684938.html 1.什么是受管制的代码&#xff1f; 答&#xff1a;unsafe&#xff1a;非托管代码。不经过CLR运行。 2.net Remoting 的工作原理是什么&#xff1f; 答&#xff1a;服务器端向客户端发送…