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第一层是值比较,第二层会比较引用