DVA框架之DVA概念学习笔记

此篇学习笔记完全是DVA官网上指南的复刻,旨在提高自己对DVA的熟悉程度

数据流向

数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由器跳转等)触发的,当此类行为会改变数据的时候可以通过dispatch发起一个action时:

  • 如果是同步行为或直接通过Reducers改变State
  • 若是异步行为(副作用)会触发Effects然后流向Reducers,最终改变State
    所以,在dva中数据流非常清晰简明。

数据流向图

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事件、网络回调,还是WebScoket等数据源获得的数据,最终都会通过dispatch函数调用一个action,从而改变对应的数据。
action必须带有type属性指明具体的行为,其他字段可以自定义,若要发起一个action需要使用dispatch函数;需要注意的是dispatch是在组件connect Models以后,通过props传入的。

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

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

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

dispatch({
    type:'use/add' , //若在model外调用,需要添加namespace
    payload: {}, //需要传递的信息
});
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对象,通过action中传入的值,与当前reducers中的值进行运算获得新的值(也就是新的state)。需要注意的是Reducer必须是纯函数,所以同样的输入必然得到同样的输出,它们不应该产生任何副作用。并且,每一次的计算都应该使用immutable data,这种特性简单理解就是每次操作都是返回一个全新的数据(独立,纯净),所以热重载和时间旅行这些功能才能够使用。

Effect

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

dva为了控制副作用的操作,在底层引入了redux-sagas做异步流程控制,由于采用了generator的相关概念,所以将异步转成同步写法,从而将effects转为纯函数。

Subscription

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

Subscriptions语义是订阅,用于订阅一个数据源,然后根据条件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}>
        <Router path="/" component={HomePage} />
    </Router>
});

Route Components

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值