(12)首页开发——④ AJAX 获取首页数据 | React.js 项目实战:PC 端“简书”开发

转载请注明出处,未经同意,不可修改文章内容。

🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。

1 mock “首页”数据

在 AJAX 请求数据前,我们得自己 mock 一些数据辅助我们开发。

1️⃣在项目的 public 目录下 api 文件夹中新增一个 homeData.json 文件:
(12)首页开发——④ AJAX 获取首页数据 | React.js 项目实战:PC 端“简书”开发

2️⃣编写 mock 数据 homeData.json 中的内容:
前置知识:《JavaScript 基础——JS 提供的对象:⑤ JSON》

{
"success": true,
"data": {
"labelList": [{
"id": 1,
"title": "简书电影",
"imgUrl": "https://qdywxs.github.io/jianshu-images/label01.jpg"
},{
"id": 2,
"title": "故事",
"imgUrl": "https://qdywxs.github.io/jianshu-images/label02.jpg"
},{
"id": 3,
"title": "手绘",
"imgUrl": "https://qdywxs.github.io/jianshu-images/label03.jpg"
},{
"id": 4,
"title": "历史",
"imgUrl": "https://qdywxs.github.io/jianshu-images/label04.jpg"
},{
"id": 5,
"title": "人文社科",
"imgUrl": "https://qdywxs.github.io/jianshu-images/label05.jpg"
},{
"id": 6,
"title": "摄影",
"imgUrl": "https://qdywxs.github.io/jianshu-images/label06.jpg"
},{
"id": 7,
"title": "自然科普",
"imgUrl": "https://qdywxs.github.io/jianshu-images/label07.jpg"
}],
"articleList": [{
"id": 1,
"title": "评“超时空同居”浅议爱情电影和奇幻元素的嫁接",
"desc": "这部电影充分照顾到了八零后的情怀,九零后的笑点,零零后嘛,那就是奇幻爱情吧。奇幻爱情喜剧,三种元素都有,但哪种都不出彩,相对来说喜剧元素稍微强一…",
"imgUrl": "https://qdywxs.github.io/jianshu-images/article-img01.jpg",
"author": "苇筱",
"discuss": 31,
"love": 21,
"money": 1
},{
"id": 2,
"title": "生活随记八则",
"desc": "1 不再困惑也不再迷茫,头脑中的构想在现实生活中并驾齐驱地向前推进,虽然困难重重但能够想方设法加以克服。前景广阔而美好,只是有一丝淡淡的凄凉,也…",
"imgUrl": "https://qdywxs.github.io/jianshu-images/article-img02.jpeg",
"author": "Jobs",
"discuss": 31,
"love": 90,
"money": 8
},{
"id": 3,
"title": "“前端一万小时”又惊艳了我一把",
"desc": "Hey guys, 我正在这个平台分发“前端一万小时”这个专栏的一系列文章。这个专栏我已经完成了“从零基础到就业”的相关文章。“从零基础到就业”包含 150+ 篇干货文章,300+ 道经典笔试、面试题。如果你对本系列文章感兴趣,欢迎关注 「公众号:前端一万小时」,并点击菜单栏“全部文章”来加入我们的“一万小时计划”!祝顺利,祝成功^^……",
"imgUrl": "https://qdywxs.github.io/jianshu-images/article-img03.jpg",
"author": "Oli",
"discuss": "9k+",
"love": "10k+",
"money": "100000k+"
}],
"panelsList": [{
"id": 1,
"imgUrl": "https://qdywxs.github.io/jianshu-images/panel01.png"
},{
"id": 2,
"imgUrl": "https://qdywxs.github.io/jianshu-images/panel02.png"
},{
"id": 3,
"imgUrl": "https://qdywxs.github.io/jianshu-images/panel03.png"
},{
"id": 4,
"imgUrl": "https://qdywxs.github.io/jianshu-images/panel04.png"
},{
"id": 5,
"imgUrl": "https://qdywxs.github.io/jianshu-images/panel05.png"
}]
}
}

3️⃣既然有了 mock 的数据,我们就可以将 home 目录下 store 中的 reducer.js 里写死的“数据”去除掉了:

import {fromJS} from "immutable"; 
const defaultState = fromJS({
// ❗️去除里边写死的“数据”,留下三个“空数组”!
labelList: [],
articleList: [],
panelsList: []
})
export default (state=defaultState, action) => {  
return state;
}

返回页面查看(页面数据都没有了):
(12)首页开发——④ AJAX 获取首页数据 | React.js 项目实战:PC 端“简书”开发

2 异步获取并显示数据

🔗前置知识:《React 进阶——⑧ React 生命周期函数(下):巧用 componentDidMount 进行 AJAX 数据请求》

在上边图片中可以看到,页面基本上什么数据都没有了。但也正符合正常的逻辑——首页的“数据”肯定不是写死在页面上的,作为“首页”的展示“数据”,它会在“首页组件”挂载完成时,去异步获取并显示“数据”。

故,这里就涉及到了“改变数据”的流程!改变什么“数据”呢——将本来的“空数组”,通过异步获取到的“数据”填满。

4️⃣打开 home 目录下的 index.js 文件:

import React, {Component} from "react";
import Content from "./components/Content";
import Label from "./components/Label";
import Panels from "./components/Panels";
import Download from "./components/Download";
import {
Section,
Aside,
Main,
ToTop
} from "./style.js";
/*
❗️❗️❗️4️⃣-①:从 react-redux 中引入 connect 方法(它也是 React-redux 的核心 API 之一),
connect 的作用很明确——就是“连接”的意思!
*/
import { connect } from "react-redux";
import {actionCreators} from "./store"; // ❗️引入 actionCreators!
class Home extends Component {
render() {
return( 
<div>
<Section className="layout clearfix"> 
<Aside>
<Panels />
<Download />
</Aside>
<Main>
<img className="banner-img" src="https://qdywxs.github.io/jianshu-images/carousel01.jpg" alt="" />
<Label />
<Content />
</Main>
</Section>
<ToTop>  
<span className="up">^</span>
<span className="tooltip">回到顶部</span>
</ToTop>
</div>
)
}
componentDidMount() { // 5️⃣当组件挂载完毕,就去请求“数据”;
// 5️⃣-①:这里应该怎么去请求“数据”呢?
/*
❗️5️⃣-③:因此可以通过 this.props.changeHomeData 来调用 store 中
的 changeHomeData;
*/
this.props.changeHomeData();
}
}
/*
❗️❗️❗️4️⃣-⑤:接下来,我们定义哪些“用户的操作”
应该当作 action,并传给 store;
*/
const mapDispatchToProps = (dispatch) => { /*
4️⃣-⑥:把 store 里的“dispatch 方法”
作为“参数”传递给 mapDispatchToProps;
*/
return {
changeHomeData() { /*
5️⃣-②:在这里定义 changeHomeData 会被当作 action
传给 store;
*/
/*
5️⃣-④:Redux-thunk 中,“异步”代码我们是放在 action 中进行。
这里我们仅作方法的“调用”;
*/
const action = actionCreators.getHomeInfo();
dispatch(action)
},
}
}
/*
❗️❗️❗️4️⃣-②:之前我们直接导出的是 Home,可用了 React-redux 后,就不能这样写了!
export default Home;
*/
/*
4️⃣-③:取而代之,我们是导出 connect 方法(
❗️注意看我们给 connect 方法传递了哪些参数!);
*/
export default connect(null, mapDispatchToProps)(Home); /*
4️⃣-④:我们一共要给 connect 传递 3 个参数!
Home 表示:connect 会让“Home 组件”和 store
进行“连接”;
null 表示:这里还会接收一个名叫 
mapStateToProps 的参数,由于这里不需要去获取
“数据”,故用 null 来占位。
mapDispatchToProps 表示:我们把 store 的 
dispatch 方法“挂载”到 Home 组件的 props 上。
即,我们可以定义哪些“用户的操作”应该当作 action,
并传给 store!
*/

5️⃣-⑤:打开 home 目录下 store 中的 actionCreators.js 文件,定义这个 action;

// 5️⃣-⑦:引入 axios 模块;
import axios from "axios";
// 5️⃣-⑥:在 action 中添加 AJAX“异步”代码;
export const getHomeInfo = () => {
// 5️⃣-⑧:编写“异步”函数;
return(dispatch) => {
axios.get("/api/homeData.json")
.then((res) => {
const result = res.data.data;
})
.catch(() => {alert("error")})
}
}

返回页面,查看“数据”是否成功获取到(已成功获取):
(12)首页开发——④ AJAX 获取首页数据 | React.js 项目实战:PC 端“简书”开发

6️⃣既然“数据”已成功获取,接下来就用 AJAX 获取到的数据替换初始的“空数组”。又是“修改数据”的套路,那我们继续走 Redux 的工作流程:

6️⃣-①:打开 home 目录下 store 中的 actionTypes.js 文件;

export const INIT_HOME_DATA = "init_home_data"; // ❗️定义好常量~

6️⃣-②:返回 home 目录下 store 中的 actionCreators.js 文件;

import axios from "axios";
// 6️⃣-③:先引入“常量”;
import {INIT_HOME_DATA} from "./actionTypes";
// 6️⃣-⑦:引入 fromJS 方法;
import {fromJS} from "immutable";
// 6️⃣-⑤:在这里定义 action;
const initHomeData = (result) => ({
type: INIT_HOME_DATA, 
/*
❗️❗️❗️6️⃣-⑥:这里请一定注意,这里的“数据”是从“接口”获取到的“数组”对象,
它是一个“JS 对象”。
但在上边的第“3️⃣”步中,“数据项”被 fromJS 修改成了“immutable 对象”,
因此,这里也应该将 result 转换为“immutable 对象”!
*/
// 6️⃣-⑧:将 result 转化为 immutable 对象;
labelList: fromJS(result.labelList),
articleList: fromJS(result.articleList),
panelsList: fromJS(result.panelsList)
});
export const getHomeInfo = () => {
return(dispatch) => {
axios.get("/api/homeData.json")
.then((res) => {
const result = res.data.data;
console.log(result);
// 6️⃣-④:获取到数据后,需要去替换初始的空数组;
const action = initHomeData(result);
dispatch(action); // ❗️6️⃣-⑨:将这个 action 发送给 reducer!
})
.catch(() => {alert("error")})
}
}

7️⃣打开 home 目录下 store 中的 reducer.js 文件:

import {fromJS} from "immutable"; 
// 7️⃣-①:先引入“常量”;
import {INIT_HOME_DATA} from "./actionTypes";
const defaultState = fromJS({
labelList: [],
articleList: [],
panelsList: []
})
export default (state=defaultState, action) => {  
// 7️⃣-②:编写替换“数据”的逻辑;
if(action.type === INIT_HOME_DATA) {
return state.merge({ // ❗️注意 merge 的使用!
labelList: action.labelList,
articleList: action.articleList,
panelsList: action.panelsList
})
}
return state;
}

返回页面查看效果(异步获取到的“数据”正常显示出来了):
(12)首页开发——④ AJAX 获取首页数据 | React.js 项目实战:PC 端“简书”开发

下篇,我们来专门实现“加载更多”这个功能,再次走“改变数据”的流程,熟能生巧!

祝好,qdywxs ♥ you!

原文链接:https://juejin.cn/post/7349542148734533651 作者:itsOli

(0)
上一篇 2024年3月25日 下午4:58
下一篇 2024年3月25日 下午5:08

相关推荐

发表回复

登录后才能评论