专栏首页独行猫a的沉淀积累总结React + Dva + Antd+umi 实践

React + Dva + Antd+umi 实践

记录一下最近项目所用到的技术React + Dva + Antd + umi ,以免忘记。之前没有用过它们其中一个,也是慢慢摸索,了解数据整个流程。

先了解下概念

React 不多说,3大框架之一;

Dva 是由阿里架构师 sorrycc 带领 team 完成的一套前端框架,在作者的 github 里是这么描述它的:“dva 是 react 和 redux 的最佳实践”。现在已经有了自己的官网 https://dvajs.com;

Antd 是阿里的一套开箱即用的中台前端/设计解决方案,UI框架,官网 http://ant-design.gitee.io/index-cn;

umi 是 dva 作者 sorrycc 最近整的新玩意,2018.2.26 发布的 1.0 版本。sorrycc 认为之前 dva 固然好,但还要用户自己引入 UI 工具 antd,打包工具 roadhog,路由 react-router,状态管理器 dva,这些很麻烦,所以弄了这个,官网 https://umijs.org;

在dva中主要分3层,models,services,components,其中models是最重要概念,这里放的是各种数据,与数据交互的应该都是在这里。services是请求后台接口的方法。components是组件了。

services层:

export function doit (body) {
    return request({
        method: "post",
        url: `${wechatApi}/doit`,
        data: JSON.stringify(body),
    })
}

这里就是请求后台接口的方法,其中这里的request是封装了axios的函数,所以它是返回的是一个promise对象,url就是要请求的地址,body就是请求参数了。

那个request如下

import axios from "axios"

export default async function request (options) {
    let response
    try {
        response = await axios(options)
        return response
    } catch (err) {
        return response
    }
}

models层:

//model里面这些"namespace,state,reducers,effects,subscriptions"是一个整体,不能缺少,不然会报错
export default {
    namespace: "test", //命名空间名字,必填  
    state: { num: 0 },//state就是用来放初始值的
    // 能改变界面的action应该放这里,这里按官方意思不应该做数据处理,只是用来return state 从而改变界面
    reducers:{
     addNum ( // addNum可以理解为一个方法名 
        // 这里state就是上面初始的state,这里理解是旧state
        state, { payload: { num }}// num 是传过来的,名字随便起,不是state中的num,这接收一个action       )         { //return新的state,这样页面就会更新 es6语法,就是把state全部展开,然后把num:num重新赋值,这样后面赋值的num就会覆盖前面的。也是es6语法,相同名字可以写成一个,所以上面接收处写了num
        return { ...state, num} 
      },
      },
    // 与后台交互,处理数据逻辑的地方
      effects:{
      * fetchNum({ payload2 }, { call, put,select }) {//fetchNum方法名,payload2是传来的参数,是个对象,如果没参数可以写成{_,{call,put,select}}

        const { data } = yield call(myService.doit, {anum:payload2.numCount}) // myService是引入service层那个js的一个名字,anum是后台要求传的参数,data就是后台返回来的数据

        //const m = yield select((state) => state.test.num) //select就是用来选择上面state里的,这里没用上

        yield put({

          type: "addNum",// 这就是reducer中addNum方法, put就是用来触发上面reducer的方法,payload里就是传过去的参数。 同时它也能触发同等级effects中其他方法。

          payload: {

            num: data, // 把后台返回的数据赋值给了num,假如那个reducer中方法是由这里effects去触发的,那个num名必须是这里名字num,如果reducer中方法不是这触发,那名字可随便起

          },

        })

      },
     * fetchUser(_,{call,put}) {
      // XXXXXXX代码
    }
    },
      subscriptions:{
      // 订阅监听,比如我们监听路由,进入页面就如何,可以在这写
        setup ({ dispatch, history, query }) {

          return history.listen(async ({ pathname, search, query}) => {

            if (pathname==="/testdemo") {// 当进入testdemo这路由,就会触发fetchUser方法

              dispatch({ type: "fetchUser" })

              }

          })

      }
)

components层:

clickHandler = () => {
        dispatch({
                        type: "test/fetchNum",// 这里就会触发models层里面effects中fetchNum方法(也可以直接触发reducer中方法,看具体情况) ,test就是models里的命名空间名字
                        payload: {
                            numCount: ++1,
                        },
                    })
}

所以整体流程是:

点击页面按钮,会触发clickHandler,——>触发models层effect的fetchNum——>触发services层doit,获取到后台返回数据——>触发models层的addNum,把返回数据传给addNum,再去更新models里的state,components应用了models层中的state的num的话,就会触发页面render方法重新渲染,界面就会更新。

render方法什么时候会触发

当state或props变化时就会触发render,我们一般在render里只获取props和state,尽量不做逻辑处理(数据逻辑处理基本在render上面的函数或者models中处理)。当父组件给子组件传递props时,子组件那个props最好不要在render里面做逻辑计算赋值,不然传递过去,子

组件有可能拿不到最新的值。比如传了个数组arr,arr在render里做了数据处理,赋值,render会运行多次(这里举例3次)所以结果可能是[1,2,3] [1,2,3] [1,2],子组件拿到的值是[1,2,3]而不是最终的[1,2],所以当你出现

子组件无法获取父组件传递过来最后正确的值,看看是不是值在render做了运算赋值,解决方法就是把数据逻辑放在models层处理,然后再返回,这样就没问题了。

页面要应用models层的数据要用connect

import { Component } from "react"
import { connect } from "dva"


class TheDemo  extends Component {
    clickHandler = () =>{xxxx}
   render () {
    const {num} = this.props //获取下面的num
        return (
        <div>
            <button onClick={this.clickHandler}><button>
            <p>{num}</p>
        </div>
)
    }
}

//字面意思就是,把models的state变成组件的props
function mapStateToProps (state) {
    const { num} = state.test // test就是models命名空间名字 
    return {
        num, // 在这return,上面才能获取到
    }
}

export default connect(mapStateToProps)(TheDemo)    

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android数据库存储模块封装,让操作记录更好用可复用

    要实现一款POS机,需要存储模块、配置文件操作模块,通信模块,卡操作模块,界面显示模块。

    特立独行的猫a
  • go-zero 微服务框架介绍

    go-zero 是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验。

    特立独行的猫a
  • Eclipse配合GDB和jlinkGDBServer仿真调试STM32

    在Eclipse的IDE环境下,除了可以搭建STM32的编译环境外,还可以配合jlink仿真器实时仿真调试stm32.

    特立独行的猫a
  • mysql循环插入记录例子

    delimiter // create procedure myproc()  begin  declare num int;  set num=1;  wh...

    用户1220053
  • 抛出和接收异常的顺序

    异常(exception)是C++语言引入的错误处理机制。它 采用了统一的方式对程序的运行时错误进行处理,具有标准化、安全和高效的特点。C++为了实现异常处理,...

    Dabelv
  • C++抛出和接收异常的顺序

    异常(exception)是C++语言引入的错误处理机制。它 采用了统一的方式对程序的运行时错误进行处理,具有标准化、安全和高效的特点。C++为了实现异常处理,...

    Dabelv
  • Array - 59. Spiral Matrix II

    Given a positive integer n, generate a square matrix filled with elements from 1...

    用户5705150
  • 月入多少的java程序员才可以养得起成都小甜甜?

    8月28号抖音上一个#最好养活小姐姐#成都小甜甜火了,原因是在“成都最街坊”话题中,视频里小姐姐的回答温暖了千万网友。

    美的让人心动
  • 对RAM初始化怎么做

    RAM的初始化并没有那么神秘,如果是采用Xilinx的IP Core,只需提供一个.coe文件,其内容就是RAM的初始值,只需要注意coe文件的格式就好,这里就...

    Lauren的FPGA
  • 基于SiN波导的级联Mach-Zehnder型DeMux

    最近工作比较忙,公众号许久没有更新。好几位朋友留言问啥时候更新,感谢大家对小豆芽一直以来的关注。

    光学小豆芽

扫码关注云+社区

领取腾讯云代金券