Dva 与 Ant-Desingn-Pro 入门与实战

dva是什么?

  • dva是一个基于Redux与React-saga的数据流解决方案。

  • 为了简化开发流程,另外内置React-Router与Redux。

如何使用 ?

  • 下载dva-cli

    // 第一步
    npm install dva-cli -g
    dva -v  // 查版本 确认安装成功
    // 第二步
    dva new your-project
    cd your-project
    npm run start 
  • dva提供的API

    import dva from 'dva'

    const app = dva({
        //指定给路由用的 history,默认是 hashHistory
        history, 
        //初始化Model中state状态,比Model优先高, 默认 {}
        initialState, 
        // 对应功能钩子函数 
        onError,
        onAction,
        onStateChange,
        onReducer,
        onEffect,
        onHmr,
        extraReducers,
        extraEnhancers,
    })
    // 执行插件
    app.use() 
    // 存储纯函数 修改数据的方法对象
    app.model( required('..model/example.js').defaut )
    // 路由配置文件,可对路由表以JavaScript对象的形式去配置, 如不要路由可直接返回组件,
    app.router( requried('../router').default)
    // 挂载启动
    app.start('element');

  • Model是一个JavaScript对象, 它包含如下


export default {
    // 每个Model 唯一的Key, model 外提交action 需添加 key 例如 example/add
    namespace: 'example',
    // 初始化状态 
    state: 0, 
    // 监听
    subscriptions: { 
        // 函数名可以随便起
        keyEvent({dispatch}){
            window.onresize = function(){
                dispatch({type: 'add'})
            }
        }
    },
    // 纯函树更新状态,触发视图更新
    reducers: { 
        add({example}, action){
            return {
                ...example,
                count: example.count+1
            }
        },
        reduce({example}, action){
            return {
                ...example,
                count: example.count+1
            }
        }
    },
    // 不是纯函数,如提交的异步action 走这里
    effects: {
        *asyncName({ars}, {call, put, select}){
            // 执行异步操作;
            yield call() 
            // Get state 
            yield select(({example}))
            // 提交action
            yield put({type: 'add'}) 
        }
    }

}

  • React Component 如何提交Action


import React from 'react';
import { connect } from 'dva'


class Example extends React.Component {
    render(){
        let {count, dispatch } = this.props;
        return (
            <div>
                <p>{count}</p>
                <button onClick={()=> dispatch({type: 'example/add'}) }>增加</button>
                <button onClick={()=> dispatch({type: 'example/reduce'}) }>减少</button>
            </div>
        )
    }
}
//  组件与dva model 绑定 
const mapStateToprops = ({example}) =>{
    return {...example, count: example.count}
};

export default connect(mapStateToprops)(Example);

Ant-Design-Pro 与 dva 结合使用

  • Router篇


// 通过JavaScript 对配置路由组件信息
const routerConfig = {
    // hideInBreadcrumb: true,
    // name: '工作台',
    // authority: 'admin',
    '/': {
      component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')),
    },
    '/dashboard/analysis': {
      component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Analysis')),
    },
    '/dashboard/monitor': {
      component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')),
    },
    '/dashboard/workplace': {
      component: dynamicWrapper(app, ['project', 'activities', 'chart'], () =>
        import('../routes/Dashboard/Workplace')
      ),
    }
};
     

  • Model篇 effects 与 reducers 的应用

// routes/user/Login.js  登录
handleSubmit = (err, values) => {
    const { type } = this.state;
    const { dispatch } = this.props;
    if (!err) {
        dispatch({
            // model外提交action需要加model key 例如下方
            type: 'login/login', 
            payload: {
                ...values,
                type,
            },
        });
    }
};
// layouts/BasicLayout.js   退出
  handleMenuClick = ({ key }) => {
    const { dispatch } = this.props;
    if (key === 'triggerError') {
      dispatch(routerRedux.push('/exception/trigger'));
      return;
    }
    if (key === 'logout') {
      dispatch({
        type: 'login/logout',
      });
    }
  };

// models/login.js
export default {
    namescape: 'login',
    status: undefined,
    effects: {
        // 登录 
        *login({ payload }, { call, put }) {
            // fakeAccountLogin 异步函数 
            const response = yield call(fakeAccountLogin, payload);
            yield put({
                type: 'changeLoginStatus',
                payload: response,
            });
            // .......
        },
        // 退出
        *logout(_, { put }) {
            yield put({
                type: 'changeLoginStatus',
                payload: {
                    status: false,
                    currentAuthority: 'guest',
                },
            });
            reloadAuthorized();
             // 切换路由到 登录页
            yield put(
                routerRedux.push({
                    pathname: '/user/login',
                    search: stringify({
                        redirect: window.location.href,
                    }),
                })
            );
        },
    },
    reducers: {
        // 更改状态,触发视图更新
        changeLoginStatus(state, { payload }) {
            setAuthority(payload.currentAuthority);
            return {
            ...state,
            status: payload.status,
            type: payload.type,
        };
    },
  },
}
  • Model篇 subscriptions 的应用

// 监听路由的改变
 subscriptions: {
    setup({ history }) {
      // Subscribe history(url) change, trigger `load` action if pathname is `/`
      return history.listen(({ pathname, search }) => {
        if (typeof window.ga !== 'undefined') {
          window.ga('send', 'pageview', pathname + search);
        }
      });
    },
    keyEvent({ diapatch }) {
        // 监听窗口变化 去改变状态, 监听 表单输入等等。
        window.onresize = function(){
            diapatch({type: 'xx'})
        }
    },
  },

Model篇 effects 的应用

  • call 与 apply 执行异步操作

      // 执行异步操作
     function* asyncFn(){
          yield call(fn, args) 
          yield apply(fn, [args])
    
          // 如果要更改fn的this   
          yield call([this,fn], args)  
          yield apply([this,fn], [args])
     }
    
  • takeEvery 与t akeLatest <作用:监听action>

    // 如事件提交了多个action, 都会保留
     function* asyncFn(){
          // 如事件提交了多个action, 都会保留
          yield takeEvery('监听的aciton', fn) 
    
          // 如事件提交了多个action 只保留最后执行 那个
          yield takeLatest('监听action', fn)
     }
    
  • put <提交action, 通过reducers 改变状态, 渲染视图>

 function* asyncFn(){
        
        yield put({type: 'xxxx', args }) 
   }
  • select 获取module中的state

 function* asyncFn(){
        
        yield select()
   }
  • put 并发请求应用场景使用,effects结合axios.all()

function getUserAccount() {
    return axios.get('/toutiao/index?type=top&key=d2340952fcc9f969b9b920dca141f4fc');
}
  
function getUserPermissions() {
    return axios.get('/wepiao/query?key=f0c96cee32a57753af183345cded5716');
}

function httpAsync(){
    return axios.all([getUserAccount(), getUserPermissions()])
    .then(axios.spread(function (a,b) {
        let params = {a,b}
       return new Promise((reslove, reject)=> reslove(params));
    }));
  
}

export function* incrementAsync() { 
    let data = yield call([obj, httpAsync])
    yield put({ type: 'INCREMENT' })
    
}

// Our watcher Saga: 在每个 INCREMENT_ASYNC action spawn 一个新的 incrementAsync 任务
export function* watchIncrementAsync() {
    yield takeEvery('INCREMENT_ASYNC', incrementAsync)
}

总结

  • Redux 相比 dva, 用dva 文件关联数减少, 节约了文件管理成本,切换成本,代码更简洁。
  • dva 集成了 Redux ,React/Router, React/saga ,dva/fetch, 不要在下载这些包了
  • router 除了可以组件的形式写, 也可通过 JavaScript 对象嵌套配置路由信息
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容

  • dva框架的使用详解及Demo教程 在前段时间,我们也学习讲解过Redux框架的基本使用,但是有很多同学在交流群里...
    光强_上海阅读 61,178评论 5 55
  • 前言 在学习antd的UI框架时,了解到了dva这个轻量级的应用框架,集成了react,redux,redux-s...
    Gary嘉骏阅读 3,368评论 1 2
  • Dva是什么 dva 是基于现有应用架构 (redux + react-router + redux-saga 等...
    黎贝卡beka阅读 46,379评论 2 52
  • 前两篇写了react各种基本操作和主要概念但其实没必要那么复杂直接用框架就好啦这年头前端框架真是一睁眼就多出好几个...
    saint37阅读 25,761评论 9 45
  • 是在哪一刻,突然会意识到已经是夏天来了? 是那场说下就下,酣畅淋漓的暴雨吗?记得雨后的清晨,太阳还没有出,空气中弥...
    TK65秒阅读 324评论 0 1