黑鸡是从去年十一月份开始接触到阿里的
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中的connectapi
// 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!