推荐文章 | 简介 | 链接 |
---|---|---|
从零玩转系列之腾讯云微信扫码授权系统 | 这篇文章是技术实战类型的,作者通过详细的步骤和代码示例,展示了如何从零开始搭建一个微信扫码授权系统。文章内容涵盖了技术选型、业务流程解析、后端实现、接口调用等多个方面,对于想要了解或实现类似功能的开发人员来说,是一篇非常有价值的参考文章。 |
🐤本篇文章是『从零玩转 TypeScript + React 项目实战』系列文章的第 5 篇,主要介绍『Dva』异步处理
经过上一篇『Dva』管理数据,文章的介绍,了解了如果通过 Dva 来管理我们的数据,了解了一下 Dva 当中的 Model,了解了下如何使用 Model 来保存我们的数据,了解了下如何使用 Model 来保存 Reducer。
那么了解完了这些内容之后呢,本篇文章再来看一下 Model 当中的 Effect。
Effect 的意思就是副作用,这个副作用用什么作用呢?它是专门用来处理异步数据的,怎么处理的呢?其实也非常的简单,这个时候先来看看 DvaJS 的官方文档中的介绍。
DvaJS 文档地址:https://dvajs.xiniushu.com/guide/
然后找到头部右侧的 API
查看一下:
进入到 API 文档页面之后我们找到 Model,找到 Model 之后它就会展示告诉我们如何来编写 Model:
编写 Model 是不是可以指定命名空间,是不是可以指定我们要保存的数据(state),是不是可以指定 reducers,除了可以指定 reducers 外,是不是还可以指定 effects,如下图:
所以说,接下来我该怎么做呢,我先回到我自己的代码当中,找到我编写的 homeModel,在我 homeModel 里面呢,再来给它新增一个 effects,如下图:
新增了 effects 之后,就可以在这里面做一些异步操作了,异步操作怎么做的呢?这个时候回到官方文档进行查看,发现它定义了一个生成器函数,这个生成器函数我们在哪见过,是不是在我之前使用 saga 的时候见过,对吧,所以说这里面是专门用来放什么的呢,这里面就是专门用来放 saga 当中处理异步数据的代码,所以说接下来该怎么做呢,我可以找到我过去讲解 saga 的时候的代码。
过去我在讲解 saga 的时候我是不是定义了一个 myHandler
这么一个生成器函数,专门用它来处理异步数据,是不是只要它被执行了,就会发送网络请求去请求数据,把数据保存到 data 中,保存之后再通过 put,来派发一个任务,然后再把获取到的数据保存到 state 中,这样就可以了:
所以说可以怎么做呢?我可以直接将之前的代码拿过来,再拿过来之前呢,数据是不是将来要保存到某一个地方,先找到 homeModel 中的 state,新增一个 info
属性取值是一个对象,将来呢把数据保存到 info 里面,保存到 info 里面怎么保存是不是通过 reducers 来处理,在 reducers 中新增一个 changeInfo
类型的 action,接收两个参数分别是 state,action,changeInfo action 大致结构如下:
changeInfo: (state, action) => {
return {}
}
好,定义好了,由于 state,中有多个数据,为了避免数据丢失。我应该先把以前的所有数据都全部重新拷贝一次,然后再用新的数据来覆盖掉同名的数据,现在的数据是不是在 action 当中:
changeInfo: (state, action) => {
return {
...state,
info: action.info
}
}
经过如上所实现的 changeInfo 方法,我现在就已经可以保存数据了,接下来我再将之前在 saga 中获取异步数据的代码拷贝到我现在演示的 demo 项目中使用了:
* asyncUserInfo(state, {put}) {
// 获取网络数据
const data = yield fetch('http://localhost:4000/api/data')
.then((response) => {
return response.json();
})
.catch((error) => {
console.log(error);
});
yield put({type: 'changeInfo', info: data.data});
},
异步处理方法名称叫做 asyncUserInfo,这个代码的含义呢代表什么呢?将来只要我派发了一个 type 名称叫做 asyncUserInfo 的这么一个 action,就会执行 asyncUserInfo 中的内容,执行 asyncUserInfo 的时候会将过去的数据(也就是 state)给你,还会给你一个对象,这个对象当中就保存了 saga 当中内置的一些方法,比如说保存了 put,保存了 call,这类似的东西。
这些东西过去我们都是需要自己手动从 saga 中的 effects 当中,手动去导入:
现在呢,现在就不用了当执行 asyncUserInfo 的时候它会直接把 effects 这个对象传递给你,所以说这里可以直接解构出来所需要的方法使用即可。所以如上呢我就解构出来了 put 供我使用,然后通过:
yield fetch('http://localhost:4000/api/data')
.then((response) => {
return response.json();
})
.catch((error) => {
console.log(error);
});
先获取数据,保存到一个 data 变量中,然后再通过 put 派发一个任务,将获取到的数据存起来,我这里派发了一个 changeInfo
任务将本次获取到的数据传递了过去。
这里有个注意点本人要说明一下,http://localhost:4000/api/data
这个请求地址说我本人,用 express 框架搭建起来的服务,供我自己测试使用,其实网上有那种开发式的测试接口,我说没去找,对于懒得搭建的人来说可以去试试,但是呢这个源码我已经上传到我自己的 Git 仓库了。
地址:https://github.com/BNTang/dva-demo-service
clone 下来之后 npm install 然后运行起来即可。好这个问题我说完了。
继续回到 asyncUserInfo
中的派发任务代码处继续讲,这里我派发完任务之后,系统就会找到 changeInfo
这个哥们去执行它,changeInfo 所对应的 type 为 changeInfo,然后 info 中就是存储的一些数据:
到此,已经编写完成了,已经没问题了,没问题之后呢,接下来就到了要使用一下测试一下看看效果的时候了,运行之前,先看看整体流程。
我先贴一张 dva 的图,让大家先回忆一下:
过去我说过,只要通过 dispatch 派发一个 action dva 会把 action 传递给 Reducer 和 Effect,运行过程如下图:
怎么传的呢?首先找到 reducers,看看 reducers 中有没有一个叫做 asyncUserInfo,很显然我们的 reducers 中是没有的,没有的话,它就会去看 effects 看 effects 里面有没有 asyncUserInfo,我代码中是不是编写了,也就是有,有!怎么办,那就执行,执行 asyncUserInfo:
asyncUserInfo 就会去获取网络数据,获取完网络数据之后又派发了一个 changeInfo:
将本次所获取到的数据带过去,这个时候,我们又派发了一个 action 它是不是首先会去找到 reducers,在 reducers 中找有没有 changeInfo,很显然是有,那么就执行,执行完之后就将数据存起来了。
用一下试一下,该怎么做呢,很简单,首先找到,映射数据的代码区域位置,在映射一个 info,更改 mapStateToProps
这个 info 数据从命名空间为 home 的这个 Model 当中去映射:
const mapStateToProps = (state) => {
return {
// 需要从传入的 state 的命名空间中拿到对应 Model 保存的数据
count: state.home.count,
+ info: state.home.info
}
};
映射完之后,就可以进入到使用阶段了,进入到 Home 组件中将数据展示一下,分别定义两个 p 标签,和一个按钮,这个按钮就是用来映射,当按钮点击之后所要执行的方法的。
由于 http://localhost:4000/api/data
接口返回的数据格式如下:
分别有 name、id、role,页面上就只能展示这三个字段的内容:
function Home(props) {
return (
<div>
<p>{props.count}</p>
<button onClick={() => {
props.increment()
}}>+
</button>
<button onClick={() => {
props.decrement()
}}>-
</button>
+ <hr/>
+ <div>dva异步处理</div>
+ <p>{props.info.name}</p>
+ <p>{props.info.role}</p>
+ <button onClick={() => {
+ props.getUserInfo()
+ }}>获取
+ </button>
</div>
)
}
由于按钮需要映射一个 getUserInfo 方法,这个 getUserInfo 方法还没有现在就去编写一下,来到映射方法的代码当中也就是 mapDispatchToProps
的内容。
在 mapDispatchToProps 中开发一个 getUserInfo,通过 getUserInfo 派发一个任务,往命名空间是 home 的这个 Model 当中派发一个 effects 当中的 asyncUserInfo 就可以了代码实现如下:
const mapDispatchToProps = (dispatch) => {
return {
increment() {
dispatch({type: 'home/add', count: 1});
},
decrement() {
dispatch({type: 'home/sub', count: 1});
},
+ getUserInfo() {
+ dispatch({type: 'home/asyncUserInfo'});
+ }
}
};
好,代码编写到这就结束了,将 server 与 dva 项目都起起来看看实际跑起来的情况:
ok,非常的好,这个数据返回的与我服务端返回的是一模一样的,这样就没问题了,这样就可以获取到我们的异步数据了,所以说以后在企业开发当中,如果你是通过 dva 来管理数据,如果说你需要在 dva 里面进行异步操作,怎么办,同步的写到 reducers 中,异步写到 effects 中就可以了。
也就是说,你只需要把过去 saga 当中处理异步数据的生成器函数放到 dva 当中的 effects 当中这样就可以了。
通过本文的学习,您可以掌握以下知识点:
put
方法派发 action 更新 state。mapStateToProps
和 mapDispatchToProps
的用法,能将 state 和 action 映射到组件的 props 中。🐤如果您觉得本文对您有所帮助,欢迎点赞、收藏或分享,您的支持是我创作的最大动力!
这篇文章的内容就介绍到这里,期待我们下次的相遇。感谢您花时间阅读,如果有任何问题或想法,欢迎在评论区留言。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。