前端-Umi Dva使用

  • Post author:
  • Post category:其他


Umi Dva入门使用,含详细解释



view和model的关系图

在这里插入图片描述



model属性

model主要有

namespace


state


reducers


effects


subscription

5个主要属性。

namespace:定义model名,如果没声明,会以文件名作为namespace。

state:model 的状态。

reducers:reducer 是 Action 处理器,用来处理同步操作。如果不需要调接口时候,我们前台传递的 action 可以直接调用 reducers 里的方法。必须返回一个新的state,否则不会自动更新页面。

effects: Effect用来处理异步操作。内部是一个 Generator 函数,使用 yield 关键字,标识每一步的操作。dva 提供多个 effect 函数内部的处理函数,比较常用的是

call



put

  • call:执行异步函数,比如发送请求
  • put:发出一个 Action,类似于 dispatch

subscriptions:相当于一个监听器,可以监听路由的变化、鼠标、键盘、服务器连接变化等。subscriptions的方法会自动初始化(执行一遍)。



model基本结构

export default {
  namespace: 'myglobal', // 定义model名,如果没声明,会以文名件作为namespace
  state: {obj: []}, // 该 model 当前的状态
  // reducer 是 Action 处理器,用来处理同步操作。如果不需要调接口时候,我们前台传递的 action 可以直接调用 reducers 里的方法。
  reducers: {
    /**
     * queryEnd方法名自定义
     * @param {Object} state 旧的state
     * @param {Object} payload 存放在 action 里面的数据
     * @param {String} propsName 字段名
     * @return {Object} 新的state。(直接重新return一个新的state会丢弃旧的state,所以为了保留旧的state,一般会解构旧的state再合并新的state)
     */
    queryEnd(state, { payload, propsName }) {// 第二个参数为 action = {type,payload}
      return { ...state, [propsName]: payload };
    }
  },
  // Effect用来处理异步操作。内部是一个 Generator 函数,使用 yield 关键字,标识每一步的操作。
  // 如果需要调取接口的话,前台页面就需要调用 effects 里的方法。将数据取出来,再传递给 reducers 里的方法进行数据操作和同步 state。
  effects: {
    /**
     * queryResolved方法名自定义
     * @param {String} propsName 保存在state中的字段名
     * @param {Object} payload 存放在 action 里面的数据
     * @param {function} callback 回调函数
     * @param {function} call dva提供处理异步任务 (与后台服务端接口进行交互)
     * @param {function} put dva提供用来发出action (action可以是异步的effects、同步的reducers)
     * @param {function} select dva提供调用其他model层的state
     * @return {null} 无返回
     */
      *queryResolved({ propsName, payload, callback }, { call, put, select }) {
      try {
        const response = yield call(queryResolvedFetch, payload); // 第一个传参:后台服务器接口对应的名称。第二个参数:入参。
        const homeName = yield select(state => state.home); // 这样我们就可以取到名为 home 的 Model 层里面的 state 数据了。
        yield put({
          type: 'queryEnd',
          payload: response.data.records,
          propsName: propsName
        });
        if (callback) callback(response.data.records);
      } catch (e) {
        console.log('queryResolved异常:', e);
      }
    }
  },
  // subscriptions相当于一个监听器,可以监听路由的变化、鼠标、键盘、服务器连接变化等。subscriptions的方法会自动初始化(执行一遍)。
  subscriptions: {

    setup({ dispatch, history }) {
      console.log('setup');
      window.onresize = () => {   //这里表示的当浏览器的页面的大小变化时就会触发里面的dispatch方法,这里的save就是reducers中的方法名
        dispatch({ type: 'save' })
      }
    },
    onClick ({dispatch}) {
      console.log('onClick');
      document.addEventListener('click',() => {   //这里表示当鼠标点击时就会触发里面的dispatch命令,这里的save就是reducers中的方法名
        dispatch ({ type: 'save' })
      })
    }
  },
};



使用connect将Route页面与Model state 进行绑定

connect是dva提供的api,但在umi3也可以这样导入:import { connect } from “umi”;

import React, { useEffect } from "react";
import { connect } from "umi";

function IndexPage(props) {
  useEffect(() => {
    props.dispatch({
      type: `myglobal/getList`,
      payload: { page: 1, size: 5 },
    });
  }, []);

  return (
    <div></div>
  );
}

IndexPage.propTypes = {};

export const mapStateToProps = ({myglobal}) => {
  return { myglobal }; // myglobal 是 Model 层里面的 namespace
};
export default connect(mapStateToProps)(IndexPage);



使用useSelector将Route页面与Model state 进行绑定

import React, { useEffect } from "react"
import { shallowEqual } from 'react-redux'
import { useDispatch, useSelector } from "umi"

export default function IndexPage(props) {
  const dispatch = useDispatch();
  const commomState = useSelector((state) => {
    return state.myglobal;
  },shallowEqual);
  
  useEffect(() => {
    setTimeout(() =>{
      dispatch({
        type: "myglobal/queryEnd",
        payload: {obj: []}
      })
    }, 3000)
  }, [])

  const count = (date) => {
    console.log('count', commomState, date);
  }

  return (
    <div>
      <h1>Page index</h1>
      <h2>{count(new Date().getTime())}</h2>
      <h3>{new Date().getTime()}</h3>
    </div>
  );
}



useSelector和shallowEqual

useSelector:从umi导出的useSelector实质是react-redux的api,默认使用===做浅比较,第二个参数是一个函数用于自己实现比较逻辑(返回true不刷新组件,返回false刷新)。

shallowEqual:react-redux提供的api,用于优化组件重新渲染的次数。

初始化		改变后的值			是否加shallowEqual	是否刷新组件
111			111					否					否

{}			{}					否					是
{}			{}					是					否
{}			{test: "test"}		是					是
{}			{test: "test"}		否					是

{obj: "aaa"} {obj: "aaa"}		是					否
{obj: "aaa"} {obj: "bbb"}		是					是
{obj: []}	{obj: []}			是					是
{obj: {name: "aaa"}} {obj: {name: "aaa"}} 是		是


[1,2]		[1,2]				否					是
[1,2]		[1,2]				是					否
[1,2]		[2,2]				是					是

总的来说:

useSelector默认会比较引用

shallowEqual第一层是值比较,第二层会比较引用



版权声明:本文为m0_62332650原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。