dva的用法_(入门)手把手带你更简单的使用dva

本文是dva.js的入门教程,重点介绍了dva的基本概念和核心特性,包括基于redux和redux-saga的数据流方案、内置react-router和fetch。通过实例展示了如何初始化dva应用、配置路由、创建数据模型以及使用connect方法连接组件和model。旨在帮助有react+redux基础的开发者快速上手dva。
摘要由CSDN通过智能技术生成

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的核心其实是 saga的封装,将action,reducer等等全部引入到model中。

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

"深入"

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

dva new dva-quickstart

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

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

入口文件 index.js

import dva from 'dva'; //引入依赖

import './index.css';

// 1. Initialize

const app = dva(); //初始化 dva应用

// 2. Plugins

// app.use({}); //使用中间件

// 3. Model

// app.model(require('./models/example').default); // 加载model层 (后面详细解释model)

// 4. Router

app.router(require('./router').default); // 引入router

// 5. Start

app.start('#root'); // 挂载dva应用

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

路由匹配 router.js

import React from 'react';

import { Router, Route, Switch } from 'dva/router'; // 引入 router,用的就是 react-router

import IndexPage from './routes/IndexPage'; // 引入路由绑定的高阶组件

// 按照从上到下的顺序开始匹配url规则,匹配到了就是展示对应的组件view

function 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. Model

app.model(require('./models/List').default); // 引入model

// 4. Router

app.router(require('./router').default);

// 5. Start

app.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),也可以在当前组件触发,如OnAdd

function List({

OnAdd,

OnDelete,

list

}) {

const List = list.map((num, index) => );

return (

{List}

Add

);

}

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中的namespace

function 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);

总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>