DvaJS浅析

891 阅读2分钟

dva

官方文档 dvajs.com/guide/

dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。

图解

dva路由 内置了react-router

  • routes文件夹一般放路由配置的组件
  • components一般放通用组件 使用高阶组件withRouter写入路由,完成子组件跳转首页 使用history路由

dva的models

引入models index.js

  • namespace 也就是命名空间
  • state状态
  • reducers处理actions payload也就是dispatch传过来的参数 必须返回一个state
  • Effect异步 基于redux-saga
  • put是发起一个action给reducers处理
  • 异步的话使用call一个参数是接口函数,第二个参数是要传的值
  • subscriptions类似于订阅,可以监听路径发生变化然后发起一个dispatch执行reducers的方法,通过方法修改state

models/indexTest.js

import * as apis from "../services/example";
export default {
  namespace"indexTest",
  state: {
    name"bbter",
    cnodeData:[]
  },
  reducers: {
    setName(state, payload) {
      // console.log(payload.data.name);
      let newState = JSON.parse(JSON.stringify(state));
      newState.name = payload.data.name;
      console.log(state);
      return newState;
    },
    setCnodeDataList(state,payload) {
      let newState = JSON.parse(JSON.stringify(state));
      // console.log(payload)
      newState.cnodeData = payload.data
      console.log(newState)
      return newState
    },
    testPath(state,payload) {
      console.log("用户页")
      return state
    }
  },
  effects: {
    *setNameAsync({ payload }, { put, call }) {
      yield put({
        type"setName",
        data: {
          name"超人强",
        },
      });
    },
    *testCnode({ payload }, { put, call }) {
      let rel = yield call(apis.testCnode);
      if (rel.data) {
        // yield put
        // console.log(rel.data.data);
        yield put({
          type"setCnodeDataList",
          data:rel.data.data
        })
      }
    },
  },
  subscriptions: {
    haha({ dispatch, history }) {
      history.listen(({pathname}) => {
        if (pathname === '/user') {
          dispatch({
            type:"testPath"
          })
        }
      })
    }
  }
};

routes/indexPage

import React from "react";
import { connect } from "dva";
// import * as apis from "../services/example"
class IndexPage extends React.Component {
  handleSetName = () => {
    // console.log(this.props)
    this.props.dispatch({
      // 命名空间加函数名
      type"indexTest/setName",
      data: {
        name:"猪猪侠"
      }
    })
  }
  handleSetNameAsync = () => {
    this.props.dispatch({
      // 命名空间加函数名
      type"indexTest/setNameAsync",
      data: {
        name:"猪猪侠"
      }
    })
  }
  componentDidMount() {
    // apis.testCnode().then((res) => {
    //   console.log(res)
    // })
  }
  testCnode = () => {
    this.props.dispatch({
      // 命名空间加函数名
      type"indexTest/testCnode",
    })
  }
  render() {
    console.log(this.props.cnodeData)
    return (<div>
      我是首页
      {this.props.msg}
      <div>
        {this.props.name}
      </div>
      <button onClick={this.handleSetName}>setName</button>
      <button onClick={this.handleSetNameAsync}>setNameAsync</button>
      <button onClick={this.testCnode}>testCnode</button>
      </div>);
  }
}
const mapStateToProps = state => {
  return {
    msg"我爱北京天安门",
    name: state.indexTest.name,
    cnodeData:state.indexTest.cnodeData
  }
}
export default connect(mapStateToProps)(IndexPage);

services里一般写接口函数

dva mock测试

mock/testMock.js

module.exports = {
  "GET /api/mockdata": (requestresponse) => {
    console.log(request);
    response.send({
      msg: "登录成功",
    });
  },
};

在.roadhogrc.mock.js注册mock

export default {
  ...require("./mock/testMock")
};

在services/example.js注册mock接口

import request from "../utils/request";
// 注册mock接口
export function mockData() {
  return request("api/mockdata");
}

routes/indexPages.jsx视图层测试mock