博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(入门)手把手带你更简单的使用dva
阅读量:5884 次
发布时间:2019-06-19

本文共 6342 字,大约阅读时间需要 21 分钟。

介绍()

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

前言

我的个人理解:dva的核心其实是 无状态组件的封装。

这是react组件的创建:

class HelloWorld extends Component {  constructor() {    super()    this.state = {  }  }  sayHi () {    alert('Hello World')  }  render () {    return (      
Hello World
) }}

什么是无状态的组件呢?

const HelloWorld = (props) => {  const sayHi = (event) => alert('Hello World')  return (    
Hello World
)}

dva更好的实现了react的思想,组件的复用在于没有多余的业务相关的状态。

dva中,将组件的state抹杀,全部通过connect 获取store作为props。

过多的废话也就不再阐述了,欲知详情,请看官网,本文的目的就是快速开始,让一个拥有react+redux基础的人可以快速使用dva.js

"深入"

配置环境安装依赖之类的就不多说了,请看官方文档

dva new dva-quickstart

我们得到初始项目,目录结构如下:

接下里将会逐个目录解释,请注意看注释

clipboard.png

入口文件 index.js

import dva from 'dva';   //引入依赖import './index.css';// 1. Initializeconst app = dva();       //初始化 dva应用// 2. Plugins// app.use({});          //使用中间件// 3. Model// app.model(require('./models/example').default); // 加载model层 (后面详细解释model)// 4. Routerapp.router(require('./router').default);           // 引入router // 5. Startapp.start('#root');                                // 挂载dva应用

基本上就是这样,多余的没什么好说的

路由匹配 router.js

import React from 'react';import { Router, Route, Switch } from 'dva/router';  // 引入 router,用的就是 react-routerimport IndexPage from './routes/IndexPage';          // 引入路由绑定的高阶组件 // 按照从上到下的顺序开始匹配url规则,匹配到了就是展示对应的组件viewfunction RouterConfig({ history }) {                   return (    
);}export default RouterConfig;

路由页面 routes/IndexPage.js

在routes目录下,是路由页面,由多个高阶组件渲染而成,当然,刚初始化的项目自然没有写高阶组件,在后面的实战操作中,我们将以 路由页面 => 高阶组件 => 基础组件 路由绑定model层,高阶组件绑定路由的action事件,基础组件绑定原生事件,在路由中触发action更新数据流 的逻辑 完成一个简单标准的dva过程

import React from 'react';import { connect } from 'dva';import styles from './IndexPage.css';// 在这个方法中,我们返回一个dom结构// 并且 在圆括号中 可以接受一个大对象(包含很多东西),也可以解构 只取其中的state和dispatch,具体可以在后面看function IndexPage() {  return (    

Yay! Welcome to dva!

);}IndexPage.propTypes = {};// 这里 connect方法就是redux的connect,后面的IndexPage表示绑定的高阶组件// 在connect的第一个括号中,是可以拿到所有的model对象,这样就可以把对应的model对象绑定到我们的高阶组件上export default connect()(IndexPage);

看了上面的注释很蒙也没关系,因为纸上谈兵,甚至,我兵都没有出来,你只需要知道,connect的作用及过程就好了

数据模型 model/emample.js

export default {  namespace: 'example',         // 命名空间 作为 connect方法 中获取model对象state的 id  state: {},                    // 初始化state   subscriptions: {              // 订阅    setup({ dispatch, history }) {  // eslint-disable-line     },  },  effects: {                     // 异步action的handler    *fetch({ payload }, { call, put }) {  // eslint-disable-line      yield put({ type: 'save' });    },  },  reducers: {                    //react-redux的reducers 用来接收action并且处理数据更新    save(state, action) {      return { ...state, ...action.payload };    },  },};

当我们在高阶组件中通过connect绑定了高阶组件和model,并且在index.js中引入这个model,就可以使用标准流程:

在subscriptions方法中订阅路由变化,当路由与高阶组件相对应,调用effects请求数据,拿到数据reducer更新数据

基础组件 components/Example.js

代码就不贴了,大家应该都知道这里面做什么

公共服务 services/example.js

这里封装了一些公共使用的方法

"浅出"

图片描述

项目地址:

接下来,我们将quick-start项目改造成一个按照dva标准流程的小项目(如上图),帮助大家理解和使用

首先我们把上面那些文件夹下面的文件全部删干净

修改路由模式 index.js

import dva from 'dva';import './index.css';import createHistory from 'history/createBrowserHistory';// 这个方法里面 可以配置router的 路由模式,比如hash或者H5 histroy,// 具体区别可以参考我的文章 vue-router,单页应用原理一致的const app = dva({    history: createHistory()});// 2. Plugins// app.use({});// 3. Modelapp.model(require('./models/List').default); // 引入model// 4. Routerapp.router(require('./router').default);// 5. Startapp.start('#root');

创建基础组件 components/Item.js

import React from 'react';const Item = ({    num,    id,    OnDelete}) => {    return (        
  • OnDelete(id)}> {num}
  • );};Item.propTypes = {};export default Item;

    创建数据模型 models/List.js

    export default {  namespace: 'list', // 这个namespace 是model的唯一识别id,在connect中需要使用这个绑定  state: {},  subscriptions: {    setup({      dispatch,      history    }) { // eslint-disable-line      return history.listen(({        pathname      }) => {        if (pathname === '/') {          dispatch({            type: 'fetch',            payload: {}          });        }      });    },  },  effects: {    * fetch({      payload    }, {      call,      put    }) { // eslint-disable-line      // 这里假装 获取到了服务器的数据      const fetchData = [0, 1, 2, 3]      yield put({        type: 'save',        list: fetchData      });    },  },  reducers: {    // 保存    save(state, action) {      return {...state,        list: action.list      };    },    // 新增    add(state, action) {      const [..._arr] = {...state      }.list;      _arr.push(_arr.length)      return {        ...state,        list: _arr      }    },    // 删除    del(state, action) {      return {        ...state,        list: state.list.filter((item, index) => {          return index !== action.id        })      }    },  },};

    写好model 是要在index.js中引入的,不然没有效果

    创建高阶组件 components/List.js

    import React from 'react';import Item from './Item'// 通过prop 把路由页面的action触发方法绑定过来,传递给子组件(OnDelete),也可以在当前组件触发,如OnAddfunction List({  OnAdd,  OnDelete,  list}) {  const List = list.map((num, index) => 
    ); return (
    {List}
    );}List.propTypes = {};export default List;

    创建路由页面 routes/IndexPage.js

    import React from 'react';import {  connect} from 'dva';import List from '../components/List'//我们在路由页面里面渲染高阶组件,写好action,通过prop传递给基础组件// 这里引入的list 对应 model中的namespacefunction IndexPage({  dispatch,  list}) {  function handleAdd() {    dispatch({      type: 'list/add'    });  }  function handleDelete(id) {    dispatch({      type: 'list/del',      id: id,    });  }  return (    
    );}IndexPage.propTypes = {};// 通过connect方法绑定路由页面和model,你可以把connect方法的第一个参数(方法里的) 打印出来看看都有什么东西,不要让解构扰乱了你的眼睛,connect((obj)=>{console.log(obj)})()export default connect(({ list}) => { return list; // 这里是state中的list,通过connect,在每次数据更新的时候,流向我们的view,更新视图,你可以在这里"打桩",看看具体的数据流动})(IndexPage);

    总结

    以上是我最近学习的想法和思考后得到的内容,希望对大家有所帮助,写的比较随意,在内容中如果有问题或者想法不对,请予指正,也可以提出新的问题,我们共同探究.

    转载地址:http://crlix.baihongyu.com/

    你可能感兴趣的文章
    基于express框架的应用程序骨架生成器介绍
    查看>>
    Spring学习11-Spring使用proxool连接池 管理数据源
    查看>>
    2016第6周五
    查看>>
    ASP.NET 免费开源控件
    查看>>
    面向对象葵花宝典阅读思维导图(二)
    查看>>
    volatile关键字与线程间通信
    查看>>
    优秀大数据GitHub项目一览
    查看>>
    TCP/IP详解学习笔记(8)-DNS域名系统
    查看>>
    通过维基API实现维基百科查询功能
    查看>>
    bootstrap 2
    查看>>
    Annotation研究的一些学习资料
    查看>>
    webpack资料
    查看>>
    DotNet加密方式解析--散列加密
    查看>>
    OpenSSL使用2(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12概念说明)(转)
    查看>>
    【前端】:HTML
    查看>>
    SSM框架——使用MyBatis Generator自动创建代码
    查看>>
    java数据库操作:JDBC的操作
    查看>>
    35佳以字体为核心的优秀网页设计作品
    查看>>
    基于OpenCV的形态学开源库 V0.2
    查看>>
    在ubuntu下安装和配置vsftpd
    查看>>