实战首页:“加载更多”功能实现
本文将介绍如何实现一个点击“阅读更多”按钮来触发异步请求并获取下一页数据的分页功能,一般将这个功能和列表集成在一起,我们将其放在List.js组件中。
1. 异步请求
首先需要异步请求后端以获取下一页的List数据,并将其拼接到当前的articleList数组中。下面是关键代码:
首先定义一个样式组件并声明onClick方法:
<LoadMore onClick={getMoreList}>更多文字</LoadMore>
接下来在mapDispatchToProps中定义getMoreList方法:
const mapDispatchToProps = (dispatch) => ({
getMoreList(){
dispatch(actionCreators.getMoreList());
}
});
最后在actionCreators中定义这个action:
export const getMoreList = (page) => {
return (dispatch) => {
axios.get('/api/homeList.json').then((res) => {
const result = res.data.data;
dispatch(addHomeList(result));
})
}
};
const addHomeList = (list) => ({
type: constants.ADD_ARTICLE_LIST,
//利用List方法把list变成immutable,但是List里面的对象还是普通JS对象,所以还是用fromJs
// list: List(list)
list: fromJS(list)
});
最后在reducer中更新文章列表数组:
export default (state = defaultState, action) => {
switch (action.type) {
...
case constants.ADD_ARTICLE_LIST: {
return state.set('articleList', state.get('articleList').concat(action.list));
}
default: {
return state;
}
}
}
2. 分页逻辑
实际开发中,一次点击应该对应一个分页逻辑,需要告诉后端需要哪一页数据。因此,我们需要在store中存储一个当前的页码,并随着点击更多按钮的触发进行更新。在defaultState中定义articlePage:
const defaultState = fromJS({
topicList: [],
articleList: [],
recommendList: [],
articlePage:1
});
触发时需要将page传递给getMoreList方法:
const mapStateToProps = (state) => ({
list: state.getIn(['home', 'articleList']),
page: state.getIn(['home', 'articlePage'])
});
<LoadMore onClick={(page) => getMoreList(page)}>更多文字</LoadMore>
然后在mapDispatchToProps中调用getMoreList方法:
const mapDispatchToProps = (dispatch) => ({
getMoreList(page){
dispatch(actionCreators.getMoreList(page));
}
});
发送请求时使用当前页码:
export const getMoreList = (page) => {
return (dispatch) => {
axios.get('/api/homeList.json?page=' + page).then((res) => {
const result = res.data.data;
dispatch(addHomeList(result,page + 1));
})
}
};
页码进行Store的更新:
const addHomeList = (list,nextPage) => ({
type: constants.ADD_ARTICLE_LIST,
list: fromJS(list),
nextPage
});
export default (state = defaultState, action) => {
switch (action.type) {
...
case constants.ADD_ARTICLE_LIST: {
return state.merge({
'articleList':state.get('articleList').concat(action.list),
'articlePage':action.nextPage
});
}
default: {
return state;
}
}
}
在export default
中,我们定义了一个reducer函数,它有一个默认状态state
,和一个action
参数,用于更新状态。在switch
语句中,我们处理了一个类型为constants.ADD_ARTICLE_LIST
的action,它会把articleList
的值更新为之前的值加上action.list
,articlePage
的值更新为action.nextPage
。最后返回更新后的状态。
3. 总结
实现加载更多的核心思路是:在页面滚动到底部时,触发异步请求获取更多的数据,将新数据添加到已有数据列表中,从而实现数据的动态加载。
一般实现步骤如下:
- 在页面滚动到底部时,通过监听页面滚动事件(
scroll
)触发回调函数。 - 判断当前滚动位置是否已经到达页面底部,即
scrollTop + clientHeight = scrollHeight
。其中,scrollTop
表示页面滚动距离,clientHeight
表示当前可见区域高度,scrollHeight
表示页面总高度。 - 如果当前已经滚动到页面底部,则发起异步请求获取更多的数据。可以使用
fetch
或axios
等网络请求库。 - 将获取到的新数据添加到已有数据列表中。为了避免频繁的数据操作,可以使用 Immutable.js 库进行列表操作。
- 更新状态或数据,使页面显示新加载的数据。
- 如果已经没有更多数据,可以通过在页面显示“没有更多数据”或隐藏加载更多按钮等方式提醒用户。
实现加载更多功能时,需要注意性能问题。一方面,需要避免频繁触发请求和数据操作,另一方面,也需要避免过多的数据加载导致页面渲染变慢。因此,可以通过设置防抖、节流等方式来优化加载更多的实现。
转载自:https://juejin.cn/post/7229909033896673338