• 使用 dva + antd 快速开发react应用


    使用 dva + antd 快速开发react应用

    版本说明:

    注意:dva的版本是0.9.2

    $ node -v
    v10.2.1
    
    $ npm -v
    5.6.0
    
    $ dva -v
    dva-cli version 0.9.2

    安装cli脚手架:

    npm install dva-cli -g

    使用脚手架生成应用:

    dva new dva_page

    建议:在new之前最好安装一下淘宝镜像,因为dva new命令会自动安装node_modules,如果使用npm会比较慢。

    npm install -g cnpm --registry=https://registry.npm.taobao.org

    安装antd和babel按需加载插件工具:

    cd dva_page
    
    npm install antd --save
    
    npm install babel-plugin-import --D

    配置babel-plugin-import:

    修改根目录下的.webpackrc文件(注意前面的.,代表linux下的隐藏文件,这是roadhog的webpack配置文件)

    {
      "extraBabelPlugins": [
        ["import", {
          "libraryName": "antd",
          "libraryDirectory": "lib",
          "style": "css"
        }]
      ]
    }

    启动服务:

    npm start

     此时打开浏览器http://localhost:8000/#/可以看到:

    编写routes:

    dva默认的页面写在 src outes 目录下面:

    我们随便引入一个antd组件,写一个demo:

    import React, { Component } from 'react';
    import { connect } from 'dva';
    import { Timeline } from 'antd';
    
    class Demo extends Component {
      render() {
        return (
          <Timeline>
            <Timeline.Item>Create a services site 2015-09-01</Timeline.Item>
            <Timeline.Item>Solve initial network problems 2015-09-01</Timeline.Item>
            <Timeline.Item>Technical testing 2015-09-01</Timeline.Item>
            <Timeline.Item>Network problems being solved 2015-09-01</Timeline.Item>
          </Timeline>
        );
      }
    }
    
    Demo.propTypes = {
    };
    
    export default connect()(Demo);

    修改路由router.js:

    dva的路由配置默认处在 src outes 里,我们在里面增加一个路由:

    import React from 'react';
    import { Router, Route, Switch } from 'dva/router';
    import IndexPage from './routes/IndexPage';
    import Demo from './routes/Demo';
    
    function RouterConfig({ history }) {
      return (
        <Router history={history}>
          <Switch>
            <Route path="/" exact component={IndexPage} />
            <Route path="/demo" exact component={Demo} />
          </Switch>
        </Router>
      );
    }
    
    export default RouterConfig;

    现在我们已经可以在http://localhost:8000/#/demo访问新增的页面了。

    网络请求:

    之前编写的都是静态页面,那么如果有网络请求和数据交互,怎么弄呢?

    先完善下 src outesDemo.js :

    组件在willMount生命周期会dispatch数据到models层中 namespace 为demo的对象, 触发执行effects中的fetch方法。

    import React, { Component } from 'react';
    import { connect } from 'dva';
    import { Timeline } from 'antd';
    
    class Demo extends Component {
      UNSAFE_componentWillMount() {
        // dispatch -> effects -> reducer -> 更新this.props
        this.props.dispatch({
          type: 'demo/fetch', //models里的namespace/effects中的方法名
          payload: {  //models里的namespace/effects中的payload参数
            time: Date.now(),
          },
        }).catch(err => {
            // 异常可以在这里处理,比如网络请求等等
      })
      }
    
      render() {
        // console.log(this.props);
        return (
          <Timeline>
            <Timeline.Item>{`${new Date(this.props.new_time)}`}</Timeline.Item>
          </Timeline>
        );
      }
    }
    
    Demo.propTypes = {
    };
    
    const mapStateToProps = (state) => {  //把state转换为props
      console.log(state);
      // 这里会把return的对象作为props传入到Demo这个类里
      return state.demo;
    };
    
    export default connect(mapStateToProps)(Demo);

    在  srcservices 中新建文件demo.js :

    发送一个网络请求:

    import request from '../utils/request';
    
    export function query(params) {
      return request('/api/users');
    }

    在  srcmodels 中新建文件demo.js :

    先引入service文件  /services/demo.js -> 定义namespace为demo -> 在effects定义generator函数 *fetch ,调用services中的请求,将请求结果放入reducers -> reducer将最终结果传入  src outesDemo.js 

    import * as demo from '../services/demo';
    
    export default {
    
      namespace: 'demo',
    
      state: {
        a: 1
      },
    
      subscriptions: {
        setup({ dispatch, history }) {
        },
      },
    
      effects: {
        // payload 是src
    outesDemo.js dispatch 过来的参数
        *fetch({ payload }, { call, put }) {
          // 调用service中的请求,把请求结果存放在result中
          let result = yield call(demo.query, payload.time); //如果使用  {参数}  ,则是一个对象
          result = { data: payload.time / 1000 };  // 因为没有配后台,所以这里result自己模拟数据
          // 将result放入reducer中
          yield put({
            type: 'save',  //reducers中的方法名
            payload:{
              new_time: result.data  //网络返回的要保留的数据
            }
          });
        },
      },
    
      reducers: {
        save(state, action) {
          // 将state和effects的put方法的payload传给src
    outesDemo.js
          return { ...state, ...action.payload };
        },
      },
    
    };

    /src/index.js 中 注册model:

    import dva from 'dva';
    import './index.css';
    
    // 1. Initialize
    const app = dva();
    
    // 2. Plugins
    // app.use({});
    
    // 3. Model
    // app.model(require('./models/example').default);
    app.model(require('./models/demo').default);
    
    // 4. Router
    app.router(require('./router').default);
    
    // 5. Start
    app.start('#root');

     最后在浏览器http://localhost:8000/#/demo看到:

    总结:

    dva的数据流可以概括为:

    1. 注册model

    2. 使用connect连接mode和page

    3. 数据流方向: page(routes)  ->  (this.props.dispatch)  ->  model ->model/effects -> (call) -> service -> model/effects -> (put) -> reducer -> page -> (this.props)

  • 相关阅读:
    JS中iframe子页面与父页面之间通信
    .NET 大数据量并发解决方案
    angular的性能分析 -随记
    第二次作业
    自我介绍
    总结作业
    2019春第四次课程设计实验报告
    2019春第三次课程设计实验报告
    2019春第二次课程设计实验报告
    第十二周作业
  • 原文地址:https://www.cnblogs.com/shenshangzz/p/9093509.html
Copyright © 2020-2023  润新知