Umi + Dva + Antd的React項目實踐

記錄一下最近項目所用到的技術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層:

複製代碼
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)    
            
複製代碼

 轉載於https://www.cnblogs.com/lucas27/p/9292058.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章