- 跟着三元大佬做的一款网易云音乐的 WebApp(三元大佬电子书链接:https://sanyuan0704.github.io/react-cloud-music/)
- 主要技术栈:react hooks + redux + immutable.js + rem
- 这一章主要讲
axios与redux的数据层开发。
axios 封装请求
安装 axios
1 | $ npm install axios --save |
因为这个项目用的是被人写的 node.js 项目提供 api,所以先去 GitHub 上面 clone 这个项目:GitHub网易云音乐接口,然后把它运行在其他端口上,保证不和当前前端服务端口冲突。
配置 axios
关于 api 的调用我们写在 api 文件夹里,在这个文件夹下面创建 config.js 文件,里面编写 axios 的配置:
1 | import axios from 'axios'; |
这个是 axios 的实例配置,它会在所有请求前方加上 http://localhost:3300,即让所有数据从这个端口号请求。
本来还应该有下面的配置的:
1 | timeout: 5000, // request timeout 设置请求超时时间 |
响应拦截器很好理解,就是服务器返回给我们的数据,我们在拿到之前可以对他进行一些处理。例如:如果后台返回的状态码是2开头的,则正常返回数据。
封装不同的网络请求
在 api 文件夹下创建 request.js 文件,这个文件就封装不同的网络请求:
1 | import { axiosInstance } from "./config"; |
这里封装了需要的两个接口,到时候直接调这些函数即可。
reudx 开发
在 Recommend 目录下,新建 store 文件夹,然后新建以下文件:
1 | actionCreators.js // 放不同action的地方 |
这是很自然的分离,如果用 rudex 的话,一般都会选择这样创建 reudx 结构。
这里是创建的 Recommend 组件的 store,然后我们会把它整合到整体的 store 中,即 src 的 store 中。
初始化 reducer:
在 Recommend 的 store/reducer.js 中写入如下代码,这就是一开始的 reducer 文件的内容:
1 | // 获取常量 |
理所当然,此时的 constants.js 和 actionCreators.js 中还没有任何的内容。
链接到主仓库
既然定义了 reducer,就需要把它链接到主仓库 src/store/reducer.js 中去,我们这里使用 Recommend/store/index.js 文件来做导出,在里面写入下面的代码:
1 | // 导入仓库 |
然后去 src/reducer.js 中导入 Recommend/store/reducer/js 并合并:
1 | // 合并 reducer 函数 |
使用 connect
去 Recommend/index.js 中导入
1 | // 负责将 ui 组件包装成容器组件 |
connect 的使用方法是:
1 | // 映射Redux全局的state到组件的props上 |
修改 reducer
首先是在 Recommend/store/reducer.js 中创建 bannerList 和 recommendList:
1 | // 获取常量 |
然后在 constants 中定义常量:
1 | //constants.js |
再重新定义 reducer 函数:
1 | export default (state = defaultState, action) => { |
index 中获取 redux 的数据
去 Recommend/index.js 中修改,我们先把之前的 mock 的数据删除了,换上重 redux 中获取的数据:
这里就需要使用我们之前的 mapStateToProps 方法了:
1 | // 映射Redux全局的state到组件的props上 |
getIn 是用来指定获取哪一个子 reducer 里的哪一个数据的,因为我们获取数据还是要通过全局的 src/reducer.js 来获取,所以我们要用这种方法指定数据的位置。getIn 的参数是一个数组,数组的第一个元素是在 src/recuder.js 中我们给 Recommend/store/reducer.js 命的名,第二个参数是 Recommend/store/reducer.js 中对应数据的名称。
把之前的 mock 数据改为下面的:
1 | // 对象结构 |
这里我们要转一下获取到的数据的数据类型,因为我们 redux 中是 immutable 数据,而我们能使用的是 js 数据。
理所当然,我们的传递给子组件的数据也要修改一下:
1 | return ( |
此时如果 redux 中有数据,我们就已经获取到了,可是现在 redux 中还没有数据,所以接下来我们用 axios 来获取数据。
定义 axios 获取数据的函数
去 actionCreators.js 中写下如下代码:
1 | // 导入常量 |
通过 axios 获取轮播图的数据:
1 | // 获取轮播图数据 |
这里使用了之前定义的网络请求 getBannerRequest,所以它完整的请求路径其实是:http://localhost:4000/banner。
然后定义 changeBannerList,它是用来获取到数据后定义要传送给 redux 的数据的格式的:
1 | export const changeBannerList = (data) => ({ |
传给 redux 的数据格式是 type 和 data,type 是我们定义的常量,而 data 因为我们获取的是 js 数据的原因,这里要先转成 immutable 数据格式才能给 redux 使用。
用同样的写法获取推荐列表的数据,下面是整个 actionCreators 的代码:
1 | // 导入常量 |
在 Recommend 中使用获取数据的函数
首先拿到我们获取数据的方法,这里就用到了 mapDispatchToProps:
1 | // 映射dispatch到props上 |
然后使用它:
1 | // 对象解构 |
以上,有了获取数据的方法,有了使用数据的方法,只要启动GitHub网易云音乐接口,然后把它运行在其他端口上,并在 api/config.js 中的 baseUrl 配置成你运行的端口号,那么我们的页面数据应该已经可以正常使用了。
总结
Recommend/index.js
1 | import React, { useEffect } from 'react'; |
Recommend/store/reducer.js
1 | // 获取常量 |
Recommend/store/actionCreators.js
1 | // 导入常量 |
Recommend/store/constants.js
1 | //constants.js |
src/store/reducer.js
1 | // 合并 reducer 函数 |