3、Mock 数据
接下来我们来实现刷新和加载更多的功能。在实现这个功能之前,我们首先将数据改造成 mock 的方式,毕竟在一个实际的项目里,这些数据都应该是从后端请求得到的。
对于 mock 我们推荐使用 YApi,它是我们开发的 API 管理平台,她提供了全方位的 API 管理功能,让团队的合作更加的高效,具体的使用可以参考 YApi 使用手册。这里我们已经建好了一个接口,它的 mock 地址为http://yapi.corp.qunar.com/mock/1239/api/list,接下来我们把请求这个接口所返回的数据作为列表页 List 组件的数据源。
首先我们修改下 reducers,增加覆盖更新(UPDATE_LIST,对应下拉刷新)和增量更新(CONCAT_LIST,对应加载更多)的 Action type:
export default (state = {
list: []
}, action) => {
const { type, payload } = action;
switch (type) {
case 'UPDATE_LIST': {
return {
...state,
list: payload.data
}
break;
}
case 'CONCAT_LIST': {
return {
...state,
list: state.list.concat(payload.data)
}
break;
}
default: {
console.log(state);
return state;
}
}
};
接下来编写 actions。在 src 目录下新建 actions 目录,在新建目录下创建 index.js:
export const fetchList = page => dispatch => (
fetch('http://yapi.corp.qunar.com/mock/1239/api/list')
.then(res =>res.json()
.then(data => {
if (page === 1) {
return dispatch({
type: 'UPDATE_LIST',
payload: data
})
} else {
return dispatch({
type: 'CONCAT_LIST',
payload: data
})
}
}
))
);
将 action 方法绑定到列表页组件中。
import { fetchList } from '../../actions';
...
const mapStateToProps = state => ({
list: state.list
});
const mapDispatchToProps = dispatch => ({
fetchList: params => dispatch(fetchList(params))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(Detail);
在组件中调用绑定的 action 方法以触发请求:
class Detail extends Component {
constructor() {
super();
this.page = 1;
}
refresh() {
const { fetchList } = this.props;
this.page = 1;
fetchList(this.page);
}
fetch() {
const { fetchList } = this.props;
fetchList(++this.page);
}
componentDidMount() {
this.fetch(this.page);
}
render() {
const { list } = this.props;
if (list && list.length > 0) {
return (
<div className="yo-flex">
<Header title="列表页" right={{
title: '点我',
onTap: () => alert('hello')
}}/>
<List
ref="list"
extraClass="flex m-list"
dataSource={list}
renderItem={(item, i) => <div>{ i + ':' + item.text}</div> }
infinite={true}
infiniteSize={20}
itemHeight={44}
usePullRefresh={true}
onRefresh={() => {
setTimeout(() => {
this.refresh();
this.refs.list.stopRefreshing(true);
}, 500);
}}
useLoadMore={true}
onLoad={() => {
setTimeout(() => {
this.fetch();
this.refs.list.stopLoading(true);
}, 500);
}}
itemExtraClass={(item, i) => {
return 'item ' + i;
}}
onItemTap={(item, i, ds) => {
yoHistory.push('/detail');
}}
/>
</div>
);
} else {
return null;
}
}
}
现在列表页组件的数据就完全交给 Redux 来管理了,整个组件已经不再有自己的 state 了。
当然你也可以用 YKit 来实现数据的 mock 功能,具体可见 YKit:代理工具 的Mock服务章节。