• DvaJS入门


    介绍

    dva 是基于现有应用架构 (redux + react-router + redux-saga 等)的一层轻量封装,没有引入任何新概念,全部代码不到 100 行。

    dva 是 framework,不是 library,类似 emberjs,会很明确地告诉你每个部件应该怎么写,这对于团队而言,会更可控。另外,除了 react 和 react-dom 是 peerDependencies 以外,dva 封装了所有其他依赖。

    dva 实现上尽量不创建新语法,而是用依赖库本身的语法,比如 router 的定义还是用 react-router 的 JSX 语法的方式(dynamic config 是性能的考虑层面,之后会支持)。

    他最核心的是提供了 app.model 方法,用于把 reducer, initialState, action, saga 封装到一起,比如:

    app.model({
      namespace: 'products',
      state: {
        list: [],
        loading: false,
      },
      subscriptions: [
        function(dispatch) {
          dispatch({type: 'products/query'});
        },
      ],
      effects: {
        ['products/query']: function*() {
          yield call(delay(800));
          yield put({
            type: 'products/query/success',
            payload: ['ant-tool', 'roof'],
          });
        },
      },
      reducers: {
        ['products/query'](state) {
          return { ...state, loading: true, };
        },
        ['products/query/success'](state, { payload }) {
          return { ...state, loading: false, list: payload };
        },
      },
    });

    简单明了的Dva数据流向

    数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State

    Dva Router控制

    dva 实例提供了 router 方法来控制路由,使用的是react-router

    const app = dva();
    import { Router, Route } from 'dva/router';
    app.router(({history}) =>
      <Router history={history}>
        <Route path="/" component={HomePage} />
      </Router>
    );

    dva 应用的最简结构(带 model)

    dva 提供多个 effect 函数内部的处理函数,比较常用的是 call 和 put。
    call:执行异步函数
    put:发出一个 Action,类似于 dispatch

    // 创建应用
    const app = dva();
    
    // 注册 Model
    app.model({
      namespace: 'count',
      state: 0,
      reducers: {
        add(state) { return state + 1 },
      },
      effects: {
        *addAfter1Second(action, { call, put }) {
          yield call(delay, 1000);//异步操作
          yield put({ type: 'add' });//类似于dispatch发action
        },
      },
    });
    
    // 注册视图
    app.router(() => <ConnectedApp />);
    
    // 启动应用
    app.start('#root');

     AntDesignPro1.0项目中的Dva

    1.index.js

    const app = dva({
      history: createHistory(),//history可以用来跳转路由内含location属性,这里修改history默认接口,其他接口不变----初始化
    });
    
    // 2. Plugins
    app.use(createLoading());//加载插件这里应该加载的是加载动画插件
    
    // 3. Register global model
    app.model(require('./models/global').default);//将src/modles里面的东西灌进去,通过namespace取
    
    // 4. Router
    app.router(require('./router').default);//全局挂载路由信息
    
    // 5. Start
    app.start('#root');
    
    export default app._store; 

    2.router.js

    export const getRouterData = app => {
        const routerConfig = {
            '/': {
                component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')),
            },
            '/person/personbasetwo': {//添加路径指向引入的组件,这条数据会被getRoutes函数渲染成真正的<Route>包裹的路由
              component: dynamicWrapper(app, ['personbaseTwo'], () => import('../routes/Person/PersonBaseTwo')),
            },
            '/person/baseInfo/:id': {//dynamicWrapper函数会吧[]里面数据放到app的model属性里,app是dva的实例
              component: dynamicWrapper(app, ['personbase'], () => import('../routes/Person/PersonBase/BaseInfo')),
            },
            ·······

    3.connect连接model

    这里用解构赋值从model中取值,为组件导入props,loading为dva提供的动画插件*/
    @connect(({ personbaseTwo, loading }) => ({
      personbaseTwo,
      searchLoading: loading.effects['personbaseTwo/getList'],
    //loding被这个异步函数影响,异步操作中就为ture,结束就为false
      loading: loading.effects['personbaseTwo/listpage'],
    }))//从model中取数据生成自己想要的对象结构通过@修饰器放到下面组件中去
    class personbaseTwo extends Component {
      constructor(props){
        super(props);
        this.state = {
        }
      }
      componentWillMount(){//组件将要渲染时拿到默认的一页多少条和当前页这些数据
        const { personbaseTwo:{pagination} }= this.props;
        const { page,pageSize } = pagination;
        this.props.dispatch({//转到namespace为personbaseTwo下面的listpage方法拿到页码为page的数据
          type:'personbaseTwo/listpage',//接口根据page只去此页数据
          payload:{
            page,
            pageSize,
          },
        });
      }
    ·······

    4.跳转路由

    onOk() {//点击确定执行的函数
              const {id}= record;
              than.props.dispatch(routerRedux.push({//用来跳转路由的
                pathname: `/person/baseInfoTwo/${id}`,//用这个pathname重新渲染路由页面并传ID
              }))
            },

    dva请求接口成功后的回调提示

    dispatch({
              type:'upImgModel/upImg',
              payload:{
                from:'DEFAULT',
                name:values.name,
                base64:url.replace(/^data:image/w+;base64,/, ""),
                dimension:JSON.stringify({
                   width,
                  heigh: height
                  }),
              },
              callback: (state, msg) => {
                if(state === 'success') {
                    Toast.success(msg,2,null,false)
                    const url = sessionStorage.getItem("returnUrl")?sessionStorage.getItem("returnUrl"):'/Signature'
                    router.push(url)
                } else {
                    Toast.fail(msg,2,null,false)
                }
              }
            })

    当判断code成功的时候 执行回调

     effects: {
        *upImg({ payload,callback }, { call, put }) {
          const response = yield call(postImg, payload);
          let reg = new RegExp(/0000$/, 'i')
          if(reg.test(response.code)) {
            yield put({
              type: 'save',
              payload: response.data
            });
            yield callback('success', '上传图片成功')
          }else{
            let { message="图片上传失败"} = response
            yield callback('error',message)
          }
         
        }
      },
     
  • 相关阅读:
    echarts圆套圆
    两个对象深度比较,借鉴,记录
    js异步加载的方式
    elementUI使用el-card高度自适应
    如何在页面上实现一个圆形的可点击区域
    清除浮动
    水平垂直居中的几种方式
    BFC原理
    正则表达式
    Vue项目中难点问题
  • 原文地址:https://www.cnblogs.com/minjh/p/13644076.html
Copyright © 2020-2023  润新知