dva做数据管理
dva 基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,今天就讲一下具体的使用
实现的效果:计算器的同步增减及异步修改数据
1.创建ui component
return (
<>
测试组件
Option:
变量:{count || 0}
>
)
2.创建model(5个api)
const TestModel={
namespace:"testModel", // 命名空间,model数据做隔离
state:{ // 变量存储,尽量扁平化处理,不要嵌套层级多
count:1,
},
reducers:{ // 同redux中的reducer模块,以key/value定义reducer。用于处理同步操作,唯一可以修改 state 的地方。由 action 触发
add(state, { payload}) {
const count = state.count + payload
return {...state,count:count}
},
reduce(state,{payload}) {
const count = state.count - payload
return {...state,count:count}
},
},
effects:{ // 以 key/value 格式定义 effect。处理异步操作,不直接修改 state。由 action 触发,可以触发 action,可以和服务器交互...
*changeAsync(_, {call,put}) {
yield call(delay,500)
yield put({type:'add',payload:2})
}
},
// 以 key/value 格式定义 subscription。subscription 是订阅,用于订阅一个数据源,然后根据需要 dispatch 相应的 action。在app.start()时被执行,数据源 可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。
subscriptions: { setup({ dispatch, history }, done) { return history.listen((location) => { if ( location.pathname === 'xxx' ) { dispatch({type:'XXX',payload:XXX}) } }); }, },
}
3.connect连接:引入connect模块
import {connect} from 'dva'
export default connect(({testModel})=>(
{
count:testModel.count,
}
))(Index)
4.组件内部使用
① 获取dva存储的变量:组件自带dispact方法和转换后的变量
const Index= (dispatch,state1,state2...)=>{
② 组件内部修改数据通过dispatch方法
dispatch({
type:[namespace]/同步reducer或异步的effects名,
payload:传入的参数
})
5.完整代码
test.js
import React,{useRef,useState,useEffect} from 'react'
import {connect} from 'dva'
const ChildComp = (props) =>{
const {userName,userAge} = props
return <>
ChildComp子页面获取数据
子页面获取到的姓名:{userName}
子页面获取的年龄:{userAge}
>
}
const Index=({dispatch,count,userName,userAge})=> {
const inputRef = useRef()
useEffect(()=>{
// console.log('count数据变化了')
return () =>{
}
},[count])
const handleAdd = () =>{
dispatch({type:'testModel/add',payload:Number(inputRef.current.value)})
}
const handleReduce = ()=>{
dispatch({
type:'testModel/reduce',
payload:Number(inputRef.current.value)
})
}
const handleAsync = ()=>{
dispatch({type:'testModel/changeAsync',payload:Number(inputRef.current.value)})
}
return (
<>
测试组件
Option:
变量:{count || 0}
>
)
}
// const mapStateToProps= (state) =>{
// return {
// count:state.testModel.count,
// userName:state.testModel.userName,
// userAge: state.testModel.userAge
// }
// }
export default connect(({testModel})=>(
{
count:testModel.count,
userName:testModel.userName,
userAge:testModel.userAge
}
))(Index)
model
const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout));
const TestModel={
namespace:"testModel",
state:{
count:1,
userName:'wang'
},
reducers:{
add(state, { payload}) {
const count = state.count + payload
return {...state,count:count}
},
reduce(state,{payload}) {
const count = state.count - payload
return {...state,count:count}
},
changeUserName(state,{payload}) {
return {...state,...payload}
}
},
effects:{
*changeAsync(_, {call,put}) {
yield call(delay,500)
yield put({type:'add',payload:2})
}
}
}
export default TestModel
界面效果:
return (
<>
测试组件
Option:
变量:{count || 0}
>
)
subscriptions: {
setup({ dispatch, history }, done) {
return history.listen((location) => {
if (
location.pathname === '/app/admin/weak/vuln' ||
location.pathname === '/app/admin/weak/vuln/hostadd' ||
location.pathname.indexOf('/app/admin/weak/vuln/host/') !== -1
) {
dispatch({
type: 'init',
payload: {
vulnInstanceType: 'serviceManage',
},
});
}
if (
location.pathname === '/app/admin/weak/vuln/website' ||
location.pathname === '/app/admin/weak/vuln/websiteadd' ||
location.pathname.indexOf('/app/admin/weak/vuln/website') !== -1
) {
dispatch({
type: 'init',
payload: {
vulnInstanceType: 'webserviceManage',
},
});
}
});
},
},