美文网首页
2019-09-27umi+dva+ant-design项目搭建

2019-09-27umi+dva+ant-design项目搭建

作者: 菩灵 | 来源:发表于2019-09-27 18:30 被阅读0次

    新建文件夹在webstorm中打开itcast-react

    一、安装和使用yarn包管理工具

    参考:yarn常用用法

    推荐使用 yarn 管理 npm 依赖,并使用国内源(阿里用户使用内网源)。

    配置yarn国内源:

    
    yarn config set registry https://registry.npm.taobao.org --global
    
    yarn config set disturl https://npm.taobao.org/dist --global
    
    
    # 国内源
    $ npm i yarn tyarn -g
    # 后面文档里的 yarn 换成 tyarn
    $ tyarn -v
    
    # 阿里内网源
    $ tnpm i yarn @ali/yarn -g
    # 后面文档里的 yarn 换成 ayarn
    $ ayarn -v
    
    

    tyarn 是走的国内淘宝的npm.taobao.org镜像
    当我们通过yarn安装太慢的时候,可以借助tyarn来安装我们所需要的依赖

    1.tyarn 安装
    npm install yarn tyarn -g
    
    
    2.tyarn 安装、升级、卸载和yarn的一样
    //eg:
    tyarn add antd
    
    
    3.全局安装umi
    #下面开始安装umi 
    tyarn global add umi 
    umi #进行测试
    
    4.添加yarn安装目录到环境变量
    • 如果提示 umi: command not found,你需要将 yarn global bin 路径配置到环境变量中,方法如下:
    # windows系统:
    # 获取 global bin 的路径
    $ yarn global bin
    C:\Users\Administrator\AppData\Local\Yarn\bin
    # 复制上面的 global bin 的路径,添加到系统环境变量 PATH。
    

    坑:配置完环境变量之后还是非内部或外部命令-----> 只要关闭Terminal再重新开一下就好

    二、初始化测试项目目录

    1.初始化yarn环境
    • tyarn init -y
    • 此时文件夹中多出来package.json文件
    2.通过umi命令创建index.js
    • umi g page index
    • 可以看到在pages下创建好了index.js和index.css文件
    3.通过命令行启动umi的后台服务,用于本地开发
    • umi dev
    4.添加本地开发环境中umi依赖
    • tyarn add umi --dev

    三、创建umi-dva-react开发环境

    • 新建文件名为umi-react
    • 右键在webstorm中打开
    • tyarn init -y
    • tyarn add umi --dev
    • 新建目录以及文件/config/config.js
      写入:
    //导出一个对象,暂时设置为空对象,后面再填充内容 
    export default {};
    
    • 新建目录及文件:/src/pages/HelloWorld.js
      写入:
    export default () => { return <div>hello world</div>; }
    
    • tyarn add umi-plugin-react --dev

    四、umi项目中开启dva进行使用

    • /config/config.js中进行如下修改:
    export default {
        plugins:[
            ['umi-plugin-react',{
                // 开启dva
                dva:true
            }]
        ]
    };
    
    • 创建model层管理数据
      • 新建目录及文件/src/model/DataList.js
        写入:
    export default {
        namespace:'list',
        state:{
            data:[1,2,3],
            maxNum:3
        }
    }
    

    注意:在umi中,约定大于配置,约定在src/models文件夹中定义model,所以,在 该文件夹下创建ListData.js文件,通过@connect方法与view进行连接

    坑:modules和models容易搞混,module(模块),model(模型),如果一不小心写错,会报错:Could not find "store" in the context of "Connect(List)". Either wrap the ...,名字改过来就好了,如果改名之后还不行,不要慌张,Ctrl+C终结服务,再重新umi dev就好了

    • 按需引入connect方法 import { connect } from 'dva'
    • 在view中使用的时候用到ES6语法中的修饰符
    • @connect函数接收两个参数,第一个参数接收一个函数,这个函数的参数为state,state是一个全局state变量,需要借助命名空间来指定对应的具体module,这个函数的作用是返回module中的数据,并且绑定到this.props上面,所以最后记得要return
     // /src/pages/List.js
    import React,{Component} from 'react'
    // 导入dva的connect方法进行page和model的连接
    import { connect } from 'dva'
    
    // 定义一个命名空间
    const namespace = 'list'
    // 定义@connect函数第一参数(函数)
    const mapStateToProps = state => {
        // 此时的state是一个全局对象
        // 必须搭配namespace下标形式映射到对应的model
        // 并且可以直接获取对应model中state上的值
        const listData = state[namespace].listData
        const maxNum = state[namespace].maxNum
        // 此函数需要return一个对象
        // 该对象将直接映射到该组件的this.props上
        return {
            listData,
            maxNum
        }
    }
    
    // 通过@connect修饰符建立映射
    @connect(mapStateToProps)
    
    export default class List extends Component{
        render(){
            return <div>
                {
                    this.props.listData.map((item,index) => {
                        return <li key={index}>{item}</li>
                    })
                }
                <button>增加</button>
            </div>
        }
    }
    
    页面效果
    • 流程说明:
        1. umi框架启动,会自动读取models目录下model文件,即ListData.js中的数据
        1. @connect修饰符的第一个参数,接收一个方法,该方法必须返回{},将接收到 model数据
        1. 在全局的数据中,会有很多,所以需要通过namespace进行区分,所以通过 state[namespace]进行获取数据
        1. 拿到model数据中的data,也就是[1, 2, 3]数据,进行包裹{}后返回
        1. 返回的数据,将被封装到this.props中,所以通过this.props.listData即可获取到 model中的数据

    五、dva框架中修改state值的操作方法

    1、首先,在model层(/models/ListData.js)中对操作方法进行定义
    // 定义修改状态值的方法集合reducers
    reducers:{
        addNewData:function(state){ // 这里的state是指更新之前的状态数据
            let maxNum = state.maxNum + 1
            let newArray =[...state.listData,maxNum]
            // 操作完业务逻辑之后,通过return即可更新state对象
            // 类似于独立组件的this.setState()方法
            return {
                listData:newArray,
                maxNum
            }
        }
    }
    
    2、在src/pages/List.js中绑定事件并且传递action

    原理说明:

    • @connect(参数1,参数2)
    • 参数1将page层和model层进行连接,返回model中的数据,并且将数据绑定到this.props上
    • 参数2将定义的函数绑定到this.props中,并且可以调用model层定义的函数
    • 参数2也是一个函数,接收dispatch参数,此参数作用是调用model层定义的函数,有返回值,返回值是一个对象,其中的函数可以被this.props调用
    • 参数2函数的返回值对象的函数中,通过调用dispatch方法,传入对象即可调用model中定义的方法,所传入对象的第一个值格式为type:namespace + '/model中函数名'
      代码如下:
    // 定义@connect函数的第二个参数(函数)
    onst mapDispatchToProps = dispatch => { // 需要接收dispatch作为参数
       return { // 返回一个装满函数的对象,直接绑定到this.props上
           add : function () {
               dispatch({ // 在返回的函数内部调用dispatch方法,参数为一个对象
                   type:namespace + '/addNewData' // 对象第一个值为type,格式为:namespace + '/model中的方法名'
               })
           }
       }
    / 通过@connect修饰符建立映射
    connect(mapStateToProps,mapDispatchToProps)
    
    // 绑定事件:
    <button onClick={this.props.add}>增加</button>
    
    界面效果

    坑:dispatch哪来的?----->内置函数

    六、dva框架model中请求数据

    1. 创建目录以及文件/src/Utils/request.js
      写入内容(固定写法):
    // /src/util/request.js
    // import fetch from 'dva/fetch';
    
    function checkStatus(response) {
        if (response.status >= 200 && response.status < 300) {
            return response;
        }
    
        const error = new Error(response.statusText);
        error.response = response;
        throw error;
    }
    
    /**
     * Requests a URL, returning a promise.
     *
     * @param  {string} url       The URL we want to request
     * @param  {object} [options] The options we want to pass to "fetch"
     * @return {object}           An object containing either "data" or "err"
     */
    export default async function request(url, options) {
        const response = await fetch(url, options);
        checkStatus(response);
        return await response.json();
    }
    
    1. model文件中,和namespacestatereducers平级,新增effects配置,用于异步请求加载数据
        // 增加effects配置用于进行异步数据请求
        effects: {
            *initData(params, sagaEffects) { //定义异步方法---->generator函数
                const {call, put} = sagaEffects; // 需要传入sagaEffects以获取到call、put方法
                const url = "/ds/list"; // 定义请求的url
                let data = yield call(request, url); //执行请求,call方法需要request作为参数
                yield put({ // 调用reducers中的方法并且传入对象作为参数,对象中有type和data两个属性
                    type : "addNewData", //指定调用方法名
                    data : data //ajax请求传递回来的数据
                });
            }
        }
    
    1. 由于call方法需要request作为参数,所以在头部引入
      import request from '../util/request';
    2. 调用时机:ComponentDidMount
    componentDidMount(){
        this.props.init ()
    }
    
    1. mapDispatchToProps中建立映射
      return的对象中新增:
    init : () => {
                dispatch({
                    type:namespace + '/initData'
                })
            }
    

    七. 处理请求的url地址

    由于url = "/ds/list"不存在所以会报错

    url地址不存在
    • mock模拟请求服务器
      • 新建目录及文件/src/mock/MockListData.js
        写入:
    export default {
        'get /ds/list': function (req, res) { //模拟请求返回数据
            res.json({
                data: [1, 2, 3, 4, 5],
                maxNum: 5
            });
        },
    }
    
    • 坑:一定要重启服务才能正确请求到!

    • 注意请求回来的数据值类型,需要和state类型一致


      model中返回值类型
    • reducers中被触发的函数的第二个参数为effects中函数传来值,其上的result.data和state类型一致,可以直接return并修改sate


      image.png

    八.项目中使用antd

    1. umi+dva中引入antd
      在 umi 中,你可以通过在插件集 umi-plugin-react 中配置 antd 打开 antd 插件,antd 插件会帮你引入 antd 并实现按需编译。


      config.js中配置以引入antd
    2. 新建文件用于演示/src/pages/MyTabs.js

    坑:在config.js中antd:true之后仍然要重启服务

    ES6对象的结构赋值特性:

    1. 通过同一对象中属性扩散可覆盖属性值
    const state = {
        num:0
    }
    let num = 2
    // 将state对象结构,num实际为num = num,覆盖之前state解构出来的属性值
    console.log({...state,num})  // {num:2}
    
    const state1 = {
        num1:0,
        a:21,
        b:12
    }
    let [num1,a,b] = [23,54,67]
    console.log({...state1}) // {num1: 0, a: 21, b: 12}
    
    const state3 = {
        x:0,
        y:21,
        z:12
    }
    let [x,y,z] = [23,54,67]
    console.log({...state3,y,z}) // {x: 0, y: 54, z: 67}
    
    
    1. 区分变量和模式
      变量必须与对象的属性同名,才能取到正确的值,如果没有对应的同名属性,取不到值的话,值为undefined
    var {bar, foo} = {foo:'aaa',bar:'bbb'}//foo的值是'aaa',bar的值是'bbb'
    //注意真正被赋值的是谁
    var {foo:baz} = {foo:"aaa",bar:"bbb"}//baz的值是"aaa"而不是foo的值是“aaa”,foo是个“模式”
    

    谁后面有“:”,谁就是模式,并不是变量

    1. 从对象的多个属性中只继承一个属性
    const state = {
        size: 'large',
        icon:'download'
      };
    let { size } = state
    console.log( value )
    

    扩展资料:

    #Umi + Dva + Antd的React项目实践
    #React + Dva + Antd + Umi 概况

    相关文章

      网友评论

          本文标题:2019-09-27umi+dva+ant-design项目搭建

          本文链接:https://www.haomeiwen.com/subject/veeouctx.html