記錄一下最近項目所用到的技術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:{
},
* fetchUser(_,{call,put}) {
// XXXXXXX代碼
}
}, subscriptions:{ // 訂閱監聽,比如我們監聽路由,進入頁面就如何,可以在這寫;
//這里的代碼,運行起來就會自動執行,在任意models寫都可以。而且方法名是任意的,這個setup是自己起的名字。
} )
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)