UmiJS使用dva的幾種方式


dva 是 React 應用框架,將React-Router + Redux + Redux-saga三個 React 工具庫包裝在一起,簡化了 API,讓開發 React 應用更加方便和快捷。

dva = React-Router + Redux + Redux-saga

注意使用Umijs創建項目默認就是ts模式,如果不是ts的可以吧數據類型定義和接口約束刪除了 ,吧index.ts改成index.js就可以了

 

在項目加載的時候 定義的dva文件就被默認加載到dva列表中,也就說項目初始化的時候dva就被觸發了,

並且dva是全局和vuex大致類似 下面我們來開始dva文件類型的創建

1.創建文件src/models/index.ts(定義dva)

文件夾必須叫models 這是因為UmiJS的約定式的 model 組織方式,否者他不去校驗這個文件里的內容是否是dva ,就不會吧dva加入dva model 列表中

import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';

export interface IndexModelState {
    name: string;
}

export interface IndexModelType {
    namespace: 'dva';
    state: IndexModelState;
    effects: {
        query: Effect;
    };
    reducers: {
        save: Reducer<IndexModelState>;
        // 啟用 immer 之后
        // save: ImmerReducer<IndexModelState>;
    };
    subscriptions: { setup: Subscription };
}

const IndexModel: IndexModelType = {
    // 命名空間 注意這個namespace對應的值必須是唯一的不能重復,因為可以定義多個dva所以這里必須是唯一的做區分
   namespace: 'dva', // 內部狀態 state: { name: '', }, // 異步程序 effects: { *query({ payload }, { call, put }) { // 正常這里發起請求 response最終獲得接口返回值 // const response = yield call(這里是返回Promise對象發起請求, 參數) yield put({ type: 'save', payload: { name: '馬丁的車夫' } }) }, }, // 同步函數 更新數據 reducers: { save(state, action) {return { ...state, ...action.payload, }; }, // 啟用 immer 之后 // save(state, action) { // state.name = action.payload; // }, }, // 訂閱 一開始就會被執行 subscriptions: { setup({ dispatch, history }) { // 監聽路由變化 根據頁面地址 觸發指定的函數(每次切換路由都會被觸發) return history.listen(({ pathname }) => { if (pathname === '/func') { // 調用 effects 對象里的異步函數體 // dispatch({ // type: 'query', // }); } }); }, }, }; export default IndexModel;

 

1.函數組件使用

方式一:

import { connect } from "umi";
import { Button } from 'antd';

const Index = (props: any) => {
    console.log(props) // 在props中獲取對應的dva中state數據和方法

    // 不想在subscriptions中去訂閱 
    // 就在這里判斷一下初始化的時候調用dva中的effects異步發起請求獲取最新數據
    if (!props.name) {
        props.onDecrease()
    }
    const handleClick = () => {
        props.onDecrease()
    }
    return (
        <div >
            獲取dva中state的默認數據:{props.name}<br/>
            <Button type="primary" onClick={handleClick}>修改</Button>
        </div>
    )
}

// 獲取到最新的state狀態並且返回到函數組件中的props中去
const mapState = (state: any) => {
    const { name } = state.dva
    return {
        name: name
    }
}

// dva 異步操作
const mapDispatchToProps = (dispatch: (arg0: { type: string; payload?: any }) => void) => ({
    onDecrease() {
        dispatch({
            // 因為dva可以定義多個 所以這里要采用命名的方式去區分(一般只定義一個只作為入口)
            type: 'dva/query', // type:'要調用dva中的namespace/要調用dva中的effects具體函數名組成的'
            payload: { a: 111 }// 傳遞參數
        });
    }
})

export default connect(mapState, mapDispatchToProps)(Index)

 

方式二:(推薦)

import { connect, useSelector } from "umi";
import { Button } from 'antd';

const Index = (props: any) => {

    // 只要調用的dva中的state數據更新了 這里就能觸發獲取到最新數據
    const { name } = useSelector(function (state: any) {
        return state.dva
    });
    const handleClick = () => {
        // 調用dva中的effects異步
        props.dispatch({
            type: 'dva/query',
            payload: { a: 111 } //傳遞參數
        }).then(()=>{
            console.log('異步函數執行完畢並且返回結果更新了state')
        })
    }
    return (
        <div >
            獲取dva中state的默認數據:{name}<br />
            <Button type="primary" onClick={handleClick}>修改</Button>
        </div>
    )
}


export default connect(({ dva }: any) => ({ dva }))(Index)

 

2.類(class)組件使用

方式一:

import React, { Component } from "react";
import { Button } from 'antd';
import { connect } from "umi";

// 對組件的props屬性對象里的值做約定
interface IpRops {
    [x: string]: any
}

class Hello extends React.Component<IpRops> {
    handleClick = () => {
        console.log(this.props, '觸發le.com')
        this.props.dispatch({
            type: 'dva/query',
            payload: { a: 111 }
        }).then(() => {
            console.log('更新完畢')
        });
    }
    render() {
        return (
            <div>
                獲取dva中state的默認數據:{this.props.name}<br />
                <Button type="primary" onClick={this.handleClick}>修改</Button>
            </div>
        )
    }
}

const mapStateUsers = (state: any) => {
    return {
        name: state.dva.name
    }
};

export default connect(mapStateUsers)(Hello);

 

方式二:(推薦)

import React, { Component } from "react";
import { Button } from 'antd';
import { connect } from "umi";

// 對組件的props屬性對象里的值做約定
interface IpRops {
    [x: string]: any
}

// this.state做約定
interface StateMode {
    [x: string]: any
}

class Hello extends React.Component<IpRops, StateMode> {

    constructor(props: any) {
        super(props)
        this.state = {}

    }
    componentDidMount() {

    }

    handleClick = () => {
        console.log('點擊發起請求')
        this.props.dispatch({
            type: 'dva/query',
            payload: { a: 111 }
        }).then(() => {
            console.log('更新完畢')
        });
    }
    render() {
        const { name } = this.props.dva
        return (
            <div>
                獲取dva中state的默認數據:{name}<br />
                <Button type="primary" onClick={this.handleClick}>修改</Button>
            </div>
        )
    }
}

export default connect(({ dva }: any) => ({ dva }))(Hello)

 

 

優化建議:

定義一個dva就可以了,作為一個入口文件,吧業務中使用到的模塊用文件的方式進行導入

一個模塊定義一個文件,最終全部導入到入口文件中對應的地方

 

我是馬丁的車夫,歡迎轉發收藏!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM