前面我们把首页中的数据,都定义在了 reducer.js 中,现在,我们将这个数据放在远程,通过ajax 从接口中获取。当然是mock 数据。
首页的数据,我们把它的接口定义为 "/api/home.json"
然后返回数据大致是这样的:
{
success: true,
data: {
topicList: [{
id: 1,
title: '热点--',
imgURL: '//upload.jianshu.io/users/upload_avatars/4802366/4f86b75d-b61b-4126-8be4-87a151c9cd28.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96/format/webp'
}],
articleList: [{
id: 1,
title: '这是标题',
desc: '这个段落的概要的内容。。。',
imgURL: '//upload-images.jianshu.io/upload_images/13910150-3c33a8d64aa623bc.png?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240'
}],
recommendList: [{
id: 1,
imgURL: "http://m.360buyimg.com/babel/jfs/t1/32844/24/9280/5497/5ca56eccEf17f316e/f6810e3e0fb865ed.png"
}]
}
}
好的,知道了接口地址与数据结构。那么我们来mock 数据。
先,下载 mockjs (之前已经安装过了在项目里,跳过)
yarn add mockjs
然后在src 下新建一个文件 mockdata.js(已有,跳过)
我们的mockdata.js 如下。
import Mock from 'mockjs';
Mock.mock("/api/headerList.json",{
"success": true,
"data": [
"风格", "水波", "可以","蓝色","红色","黄色","白色","黑色","紫色","绿色",
"秦始皇","汉武帝","盘古","女娲","黄帝","炎帝","伏羲","雷神","大禹","龙王",
"呼兰河"
]
});
Mock.mock("/api/home.json", {
"success" : true,
"data": {
"topicList": [{
"id": 1,
"title": "热点--",
"imgURL": "//upload.jianshu.io/users/upload_avatars/4802366/4f86b75d-b61b-4126-8be4-87a151c9cd28.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96/format/webp"
}, {
"id": 2,
"title": "桃花--",
"imgURL": '//upload.jianshu.io/users/upload_avatars/3136195/484e32c3504a.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96/format/webp"
}],
"articleList": [{
"id": 1,
"title": "这是标题",
"desc": "这个段落的概要的内容。。。",
"imgURL": "//upload-images.jianshu.io/upload_images/13910150-3c33a8d64aa623bc.png?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240"
},{
"id": 2,
"title": "这是标题2",
"desc": "这个段落的概要的内容2。。。",
"imgURL": "//upload-images.jianshu.io/upload_images/13910150-3c33a8d64aa623bc.png?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240"
}],
"recommendList": [{
"id": 1,
"imgURL": "http://m.360buyimg.com/babel/jfs/t1/32844/24/9280/5497/5ca56eccEf17f316e/f6810e3e0fb865ed.png"
}, {
"id": 2,
"imgURL": "http://m.360buyimg.com/babel/jfs/t1/32844/24/9280/5497/5ca56eccEf17f316e/f6810e3e0fb865ed.png"
}]
}
});
然后,我们可以把src/pages/home/store 下的 reducer.js 中的初始数据置空,如下。
import { fromJS } from 'immutable';
const defaultState = fromJS({
topicList: [],
articleList: [],
recommendList: []
});
export default (state = defaultState, action) => {
switch (action.type) {
default:
return state;
}
}
然后,我们需要在组件中去发送ajax 请求,打开 src/pages/home 下的 index.js ,我们在组件的 componentDidMount 生命周期函数中发送这个请求。如下。
import React, {Component} from 'react';
import {HomeWrapper, HomeLeft, HomeRight } from './style';
import List from './components/List';
import Recommend from './components/Recommend';
import Topic from './components/Topic';
import Writer from './components/Writer';
import bannerImage from '../../statics/ooo.jpg';
import axios from 'axios';
class Home extends Component {
render () {
return (
<HomeWrapper>
<HomeLeft>
<img
className="banner-img"
src={bannerImage}
alt=''
/>
<Topic></Topic>
<List></List>
</HomeLeft>
<HomeRight>
<Recommend></Recommend>
<Writer></Writer>
</HomeRight>
</HomeWrapper>
)
}
componentDidMount () {
axios.get("/api/home.json").then((res) => {
console.log(res);
})
}
}
export default Home;
接下来,我们要把获得的数据,放到redux 中。先在home 组件中发送action 。
import React, {Component} from 'react';
import { connect } from 'react-redux';
import {HomeWrapper, HomeLeft, HomeRight } from './style';
import List from './components/List';
import Recommend from './components/Recommend';
import Topic from './components/Topic';
import Writer from './components/Writer';
import bannerImage from '../../statics/ooo.jpg';
import axios from 'axios';
import { dispatch } from 'C:/Users/ThinkPad/AppData/Local/Microsoft/TypeScript/3.4/node_modules/rxjs/internal/observable/range';
class Home extends Component {
render () {
return (
<HomeWrapper>
<HomeLeft>
<img
className="banner-img"
src={bannerImage}
alt=''
/>
<Topic></Topic>
<List></List>
</HomeLeft>
<HomeRight>
<Recommend></Recommend>
<Writer></Writer>
</HomeRight>
</HomeWrapper>
)
}
componentDidMount () {
axios.get("/api/home.json").then((res) => {
const result = res.data.data;
const action = {
type: "change_home_data",
topicList: result.topicList,
articleList: result.articleList,
recommendList: result.recommendList
};
this.props.changeHomeData(action);
})
}
}
const mapDispatch = (dispatch) => {
return {
changeHomeData (action) {
dispatch(action);
}
}
}
export default connect(null, mapDispatch)(Home);
我们在上面中dispatch 派发的action,除了总的 reducer 能收到外,所有小的reducer 也能收到。也就是说。src/pages/home/store 下的reducer 也能接收到这个action 。然后我们可以在src/pages/home/store 下的reducer做如下修改。
import { fromJS } from 'immutable';
const defaultState = fromJS({
topicList: [],
articleList: [],
recommendList: []
});
export default (state = defaultState, action) => {
switch (action.type) {
case "change_home_data":
state.set("topicList", fromJS(action.topicList));
state.set("articleList", fromJS(action.articleList));
state.set("recommendList", fromJS(action.recommendList));
return state;
default:
return state;
}
}
上面,连写三个 set 可以更简便:
import { fromJS } from 'immutable';
const defaultState = fromJS({
topicList: [],
articleList: [],
recommendList: []
});
export default (state = defaultState, action) => {
switch (action.type) {
case "change_home_data":
return state.merge({
"topicList": fromJS(action.topicList),
"articleList": fromJS(action.articleList),
"recommendList": fromJS(action.recommendList)
});
default:
return state;
}
}
Done!