黑鸡是从去年十一月份开始接触到阿里的
umi
的,同时也是第一次接触dva
的数据流,不过当时看到models
文件夹下的文件中一大堆yield
、call
、put
等陌生的写法就让我望而却步,当时虽然学习了一些,但是使用的一直不熟练,现在黑鸡准备好好整理一下使用方法,以便以后自己忘记。这里只写使用方法,不说比较深层次的东西(深的黑鸡也不懂)。
umi中dva的使用
首先我们在使用react
的时候在早些时候都会使用redux
来作为全局状态管理,并且我们都知道redux
的学习难度是相对vue
中的vuex
来说是高于后者的,并且个人感觉使用体验也不如vuex
,而dva
就是一个基于redux
和redux-saga
的一个数据流方案,使用起来体验要比redux
好的多。
基本使用
而在umi
中使用dva
还是比较简单的首先建立一个umi
项目
yarn create @umijs/umi-app
然后跑起来,umi
给我们约定了很多东西,所以我们不需要做太多导包什么的操作,首先,在src
下新建一个models
文件夹在下面创建一个global.js
文件
|- src
...
|- models
|- global.js
|- pages
|- index.jsx
|- index.less
获得了如上格式的文件结构后开始在global.js
中撸代码
const GlobalModel = {
namespace: 'global', //命名空间
state: {
count: 1
}, //state是数据仓库
reducers: {
setCount(_, { payload: count }){
return {
count
}
}
}
}
export default GlobalModel
这样就写了一个最最简单的model
文件,接下来来解释一下这段代码的含义。
namespace
是命名空间,我们在组件或者其他model
文件中使用其他model
的方法都需要加上命名空间reducers
可以理解成vuex
中的mutations
,里面可以进行同步操作修改state
仓库,但是要注意和vuex
的区别,vuex
中是只修改state
中的一部分,而dva
中,应该说redux
中是直接返回一个新的仓库
定义好仓库和方法我们如何在组件中使用呢,这得使用umi
中的connect
api
// index.jsx
import React from 'react'
import { connect } from 'umi'
const Index = (props) => {
const { count, dispatch } = props
const addCount = () => {
dispatch({
type: 'global/setCount',
payload: count + 1
})
}
return (
<>
<div>{ count }</div>
<button>增加</button>
</>
)
}
// 这里解构出的global就是我们的global仓库
export default connect(({ global })=>{
return {
count: global.count
}
})(Index)
具体的使用方法如上代码所示,可以通过dispatch
分发action
来操作models
文件中定义的逻辑
connect
connect
的作用是连接组件和仓库,使用connect
连接过的组件可以使用任何仓库中的数据,这样跨组件交流特别的方便。
connect
方法支持一个回调函数作为参数,被此回调返回的数据会被注册到组件的props
中,我们只需将数据中props
中解构出来即可使用(不喜欢解构也可以不解构,但是要多写一个props
)
示例:
import { connect } from 'umi'
const Page = (props) => {
const { count } = props
return (
<div>
{ count }
</div>
)
}
export default connect((store)=>{
//回调中返回的数据会被注册到props中
return {
count: store.global.count
}
})(Page)
这就是基本使用
异步操作effect
上面的models
代码中reducers
中只能进行同步操作,如果我们要发送Ajax请求或者其他异步操作就得把代码写在effect
中了,修改一下global.js
// models/global.js
import { getData } from 'xxx' //封装的Ajax请求
const GlobalModel = {
namespace: 'global', //命名空间
state: {
count: 1,
list: []
}, //state是数据仓库
reducers: {
setCount(state, { payload: count }){
return {
...state,
count
}
},
setList(state, { payload: list }){
return {
...state,
list
}
}
},
effect: {
*getList({ payload }, { call, put }){
//Ajax请求
const data = yield call(getData, payload)
if(data.code === 200){
yield put({
type: 'setList',
payload: data.data //把接口返回的数据传入
})
}
}
}
}
export default GlobalModel
上面就是effect
的用法,注意effect
中必须是一个Generator函数(工厂函数),call
中可以调用接口的请求函数,只需要把封装的请求函数写入call
的第一个参数就行了,第二个参数会被当作Ajax请求的参数,put
相当于dispatch
可以调用models
中的方法,注意call
和put
使用前面都必须加上yield
关键字
subscriptions
接下来说最后一个属性subscriptions
,这个属性中有一个setup
方法,该方法可以监听路由变化并在其中进行一些操作,比如登录判断
// models/global.js
import { getData } from 'xxx' //封装的Ajax请求
import { isLogin } from 'xxx'
const GlobalModel = {
namespace: 'global', //命名空间
state: {
count: 1,
list: []
}, //state是数据仓库
reducers: {
setCount(state, { payload: count }){
return {
...state,
count
}
},
setList(state, { payload: list }){
return {
...state,
list
}
}
},
effect: {
*getList({ payload }, { call, put }){
//Ajax请求
const data = yield call(getData, payload)
if(data.code === 200){
yield put({
type: 'setList',
payload: data.data //把接口返回的数据传入
})
}
}
},
subscriptions: {
setup({ dispatch, history }){
return history.listen(({ pathname }) => {
if(pathname === '/'){
//如果页面是首页,执行某些逻辑
}
if(!isLogin){
//如果没有登录,重定向到登录
history.push('/login')
}
})
}
}
}
export default GlobalModel
以上就是umi
中dva
的基本使用,更深的黑鸡也没接触到,在这里记下以便以后查看,up!up!up!