2018-08-06 18:26:30 annroy 阅读数 3499

Dva整体理解


前言

README.md

欢迎阅读,本文档将带你了解dva的整体思路。

介绍

应用 dva 框架搭建平台,dva 是基于 redux 最佳实践实现的framework,简化使用 redux 和redux-saga 时很多繁杂的操作。 dva 文档比较健全,可以访问https://github.com/dvajs/dva-docs/blob/master/v1/zh-cn/tutorial/01-%E6%A6%82%E8%A6%81.md查看更多内容,其中会介绍整个框架的开发思路。

 

关于dva

dva 是基于现有应用架构 (redux + react-router + redux-saga 等)的一层轻量封装;

数据流向: 数据的改变发生通常是通过:

  • 用户交互行为(用户点击按钮等)
  • 浏览器行为(如路由跳转等)触发的

当此类行为会改变数据的时候可以通过 dispatch 发起一个 action ,如果是同步行为会直接通过Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变State 。 所以在 dva 中,数据流向非常清晰简明,如上图。

 

关于Redux-saga

Redus-saga 是一个 redux 的中间件,主要用来简便而优雅的处理 redux 应用里的副作用(side effect相对于pure function这类概念而言的)。它之所以可以做到这一点主要是使用了ES6 里的一个语法: Generator 。使用 Generator 可以像写同步的代码一样编写异步代码,这样更加容易测试。

 

准备

本文档第一部分将带领大家获得项目源码。首先需要的是将 gitlad 上的远程项目仓库克隆到本地;

$ git clone http://gitlab.xxxx.com/xx/xxx.git

克隆完成后,本地目标文件夹里就会出现目标远程仓库的文件;

目录

本文档的第一部分将带领大家了解dva项目 目录结构。在下载源码之后,我们可以看到,整个系统的构建以及管理。目录如下:

工程结构如下:

● xxxx
 ○ public
 ○ src                          #项目源码目录
   ■ assets                     #静态资源
   ■ common                     #路由资源
   ■ components                 #项目组件
   ■ layouts                    #项目布局组件
   ■ models                     #数据模型
   ■ routes                     #路由组件(页面维度)
   ■ services                   #数据接口
   ■ utils                      #工具函数
   ■ index.js                   #入口文件
   ■ router.js                  #路由配置

开始

增加一个新功能

在上面的介绍中中我们已经对 dva 有了一定的认识,接下来我们会一起添加一个较为完善的功能,在实现的过程中,我们逐步完成以下内容:

  1. 添加顶层路由数据
  2. 添加路由
  3. 添加布局
  4. 定义service
  5. 设计Model
  6. 组件设计

添加顶层路由数据

第一步,我们会按照功能在 ./common/nav.js 添加路由数据:(部分代码)

// common/nav.js
{
  name: 'xxx',
  path: 'aaa',
  icon: 'global',
  page: 'ppp',
  grayscale: true,
  children: [
  {
     component: dynamicWrapper(app, ['aaa'], () =>  
                import('../routes/aaa')) 
  },
  //......
  ],
}

 

定义路由

路由决定进入 url 渲染哪些 Component 。 history 默认是 hashHistory;

// router.js
return (
  <LocaleProvider locale={zhCN}>
    <Router history={history}>
      <Switch>
        <Route path="/login" render={props => <XxxLayout {...props}   
        {...passProps} />} />
        <Route path="/sss" component={sss} />
        <Redirect exact from="/" to="/index" />
    </Switch>
   </Router>
  </LocaleProvider>
);

 

设计布局

路由添加完成后,设计布局,这些布局内容被抽象成组件,包含一些布局样式,用于组合其它组件搭建成页面。
本质上还是一种组件,将布局样式抽象成组件,能够保持子组件和父组件的独立性,不用在其中关联到布局信息。

注:若添加的是二级功能,不需要添加新的布局

 

定义service

接下来就是将请求相关抽离出来,单独放到 /services/ 中,进行统一维护管理;
如:

// services/xxx.js
export async function xxx(params) {
return     request(`xxx.json`, {
    method: 'GET',
});
}

设计Model

在完成项目基本的前期以后,我们将要开始设计 model ,在设计 model 之前,我们需要回顾一下项目的功能;
我们可以看出,这部分功能基本是围绕 以用户数据为基础 的操作,其中包含:

  • 用户信息的展示
  • 用户信息的操作

无论是多复杂的项目也基本上是围绕着数据的展示和操作,复杂一点的是组合了很多数据,有关联关系,只要分解开来, model 的结构层次依旧会很清晰,便于维护。
所以抽离 model 的原则就是抽离数据模型。

export default { 
namespace: 'xxx',
state: {
    helps: [],
    task: {},
    data: {
      list: [],
      pagination: {
         current: 1,
      },
    },
},
  effects: {
    * auth() {},
    * list() {};
    * detail() {},
    * xxList() {};
    * xxOperation() {},
  },
  reducers: {
    save(){}
  },
};

model 包含了关于操作的 state ,处理异步的 effect(dispatch action) ,以及修改 state 的reducers

视图设计

数据设计完成后,我们着手新增组件的编写,在 ./routes 中添加新增组件,根据 @connect 包裹组件的 props 进行操作的编写:

@connect(({ a1, a2 }) => ({
  a1,
  a2: ......,
}))
export default class xxx extends PureComponent {
  state = {
    page: 1,
    type: 1,
    //.....
  }

  componentDidMount() {
    const { dispatch } = this.props;
    dispatch({
      type: 'xx/auth',
    });
    dispatch({
      type: 'xx/list',
      payload: {
        page: 1,
        type: 1,
      },
    });
  }

 

组件设计

在确定了大体的设计方法以后,让我们来看看如何设计 dva 中的 React 组件。
React 应用是由一个个独立的 Component 组成的,我们在拆分 Component 的过程中要尽量让每个Component 专注做自己的事。

对组件分类,主要有两个好处:

  • 让项目的数据处理更加集中;
  • 让组件高内聚低耦合,更加聚焦;

 

注:本平台使用 ant design 进行组件的设计,避免样式表的复杂编写;

 

写在最后

dva将所有与数据操作相关的逻辑集中放在一个地方处理和维护,在数据跟业务状态交互比较紧密的场景下,会使我们的代码更加清晰可控。

对于一个大型管理系统,由于要进行大量的数据操作,在设计model时将不同类型的业务需求数据操作分开处理,便于维护。

项目的开发流程一般是从设计 model state 开始进行抽象数据,完成 component 后,将组件和model 建立关联,通过 dispatch 一个 action ,在 reducer 中更新数据完成数据同步处理;当需要从服务器获取数据时,通过 Effects 数据异步处理,然后调用 Reducer 更新全局 state 。是一个单向的数据流动过程。解决了 redux 中代码分散和重写问题,总之,Dva:Build redux application easier and better。

官方地址
Ant Design
Redux-saga 中文文档
dva-knowledgemap
dva: react application arch in ant financial

2019-05-29 19:17:26 qq_33559093 阅读数 839

先初始化一个react native的项目

npm install -g yarn react-native-cli

react-native init AwesomeProject

准备安装dva 、react-navigation

1.yarn add  dva-core

2.yarn add react-redux

3.yarn add react-navigation

4.yarn add react-native-gesture-handler

5.react-native link react-native-gesture-handler

然后是集成步骤

1.集成dva,使用dva-core和react-redux,新建app文件夹

app文件夹中新建.root.js

import * as React from 'react';
import indexModel from './models/index'
import { Provider  } from 'react-redux';
import App from './routes'//    这个是react-navigation路由文件

import { create } from 'dva-core';

const models = [indexModel];

const app = create(); // 创建dva实例,可传递配置参数。https://dvajs.com/api/#app-dva-opts

models.forEach((o) => { // 装载models对象
  app.model(o);
});

app.start(); // 实例初始化

const store = app._store; // 获取redux的store对象供react-redux使用

export default class Container extends React.Component {
  render() {
    return (
      <Provider store={store}>//    注入dva
        <App/>
      </Provider>
    );
  }
}

2.编写路由,react-navigation

app文件夹下新建routes.js

import React, { PureComponent } from 'react'
import {
  TabBarBottom, addNavigationHelpers, createSwitchNavigator,
  createBottomTabNavigator, createStackNavigator, createAppContainer
} from 'react-navigation'
import AuthLoadingScreen from './components/loading/index'
import {StatusBar, View, Platform} from "react-native";

import Home from './pages/Home/Home'
import Order from './pages/Order/Order'
import Get from './pages/Get/Get'
import Register from './pages/Register/index'
import Establish from './pages/Establish/index'
import Restore from './pages/Restore/index'

const AuthStack = createStackNavigator(
  {
    Register: Register,
    Establish: Establish,
    Restore: Restore
  },
);
const HomeNavigator = createBottomTabNavigator(
  {
    Home: { screen: Home },
    Order: { screen: Order },
    Get: { screen: Get }
  }
);

const AppNavigation = createSwitchNavigator(
  {
    App: HomeNavigator,
    Auth: AuthStack,
    AuthLoading: AuthLoadingScreen
  },
  {
    initialRouteName: 'AuthLoading',
  }
);

const App = createAppContainer(AppNavigation);

export default App

3.链接项目

根目录下的index.js

import {AppRegistry} from 'react-native';
import App from './app/root';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

最后,如何在组件中使用dva,点我的另外一篇文章----->点这里

2019-11-20 13:58:43 qq_17025903 阅读数 18

一、基本概念

dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,还额外内置了

react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。

  • 易学易用,仅有 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
     

个人理解 :简化了React的setState跨组件传输数据的耦合,数据通过mapStateToProps

就可以共享数据,并且比Redux传输数据操作要更简单,可以自动处理等待状态,如果会

Redux入门可以更迅速 ,更快的上手。

二、代码详解

可以通过  npm install  dva-cli  或  yarn add dva-cli 安装

创建model文件夹和viewer.js

export default {

  namespace: "viewer",

  state: {
    cesiumViewer:undefined
  },

  subscriptions: {
    setup({ dispatch, history }) {  // eslint-disable-line
    },
  },
  effects: {
    * fetch({ payload }, { call, put }) {  // eslint-disable-line
      yield put({ type: "save" });
    }
  },
  reducers: {
    /**
     *
     * @param {*}state 状态
     * @param {*}action 动作
     * @returns {*} 结果
     */
    save(state, action) {
      return { ...state, ...action.payload };
    },
    /**
     *
     * @param {*}state 状态
     * @param {*}action 动作
     * @returns {*} 结果
     */
    changeAction(state, action){
      return { ...state, ...action.payload };
    }
  },
}

namespace:可以通过空间名找到对应的model下的 viewer.js
state: {cesiumViewer:undefined} 存储共享的数据
subscriptions:常用来监听浏览器地址输入的参数
effects:异步处理
reducers:同步处理
save:自定义方法里的 state为当前的数据,action.payload为传过来要改变的数据

调用save方法只需要用  dispatch type类型为 namespace(viewer) 和自定义方法名(save)  payload 传递改变的参数

    this.props.dispatch({
      type: "viewer/save",
      payload: {
        cesiumViewer:123456
      },
    });

save 加上回调和异常处理则为

    this.props.dispatch(
      {
        type: "viewer/save",
        payload: {
           cesiumViewer:123456
        },
        callback:(result)=>{
          console.log(result)
        },
        errorcallback:()=>{
          message.warning("服务异常");
        }
      }
    )

需要拿到共享参数则为 this.props.viewer.cesiumViewer 就可以拿到 viewer 空间下的共享数据

function mapStateToProps(state) {
  return {
    viewer:state.viewer,
  };
}
export default connect(mapStateToProps)(绑定的class);

三、Dva原理图

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

个人理解:通过URL调用渲染组件初始化dom的时候,会通过connect(mapStateToProps) 加载共享数据,并且调用dispatch会触发action 进行同步或异步操作或者监听地址栏是否传入参数的处理。

 

2017-07-10 14:47:44 weiyongliang_813 阅读数 3637

昨天才用create-react-app创建了react的开发环境,以为今后就用它来创建开发环境咯,谁知道才用了一天,才发下dva也是用来创建react开发环境的。
dva是淘宝团队弄的,为了支持国货,赶紧试试看咋用吧
第一步:安装 dva-cli

cnpm install dva-cli -g

第二步:采用dva来创建项目:

dva new react_two
cd react_two

用webstorme打开react_two项目:文件解构大概如下:
这里写图片描述

第三步:npm start 启动起来访问路径:http://localhost:8000/ 界面效果如下:

这里写图片描述

我个去哦,界面效果跟用create-react-app创建的工程的界面效果基本一样。
其实原理跟create-react-app里创建工程的react-scripts原理基本一样,在此就不分析咯,其实就是换汤不换药而已。

2017-12-28 16:39:39 bbsyi 阅读数 2819

 

作者:zhenhua-lee
链接:https://www.zhihu.com/question/51831855/answer/225446217
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  1. 框架: dva是个框架,集成了redux、redux-saga、react-router-redux、react-router
  2. 快速初始化: 可以快速实现项目的初始化,不需要繁琐地配置
  3. 简化开发:将initState、saga、reducer集成到一个model里面统一管理,避免文件散落在各个文件里面,便于快速查找与开发
  4. 简洁的API:整个项目中只有dva、app.model、app.router、app.use、app.start几个API
  5. 无缝对接:跟react的生态没有冲突,例如可以直接使用redux devtool工具
  6. 动态机制:app.start以后,仍然可以注册model,灵活性较高

再说说个人觉得不太爽的地方吧:

  1. namespace不统一: dva中的action.type格式是namespace/XXX,且在model中不需要添加前缀namespace,但是在组件中dispatch,却需要添加prefix
  2. action问题:action会散落在两个地方,一个是saga里面,另外一个是component dispatch的时候,当然这个问题在使用redux-saga的时候就会存在,只是dva仍然没有很好地统一起来。

 

dva+react+antd

阅读数 491

react-dva 笔记

阅读数 20

dva+react+ant.design

阅读数 1062

react+dva+antd

阅读数 370

react+dva

博文 来自: cater_bjut
没有更多推荐了,返回首页