实战首页:“加载更多”功能实现

本文将介绍如何实现一个点击“阅读更多”按钮来触发异步请求并获取下一页数据的分页功能,一般将这个功能和列表集成在一起,我们将其放在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.listarticlePage的值更新为action.nextPage。最后返回更新后的状态。

3. 总结

实现加载更多的核心思路是:在页面滚动到底部时,触发异步请求获取更多的数据,将新数据添加到已有数据列表中,从而实现数据的动态加载。

一般实现步骤如下:

  1. 在页面滚动到底部时,通过监听页面滚动事件(scroll)触发回调函数。
  2. 判断当前滚动位置是否已经到达页面底部,即 scrollTop + clientHeight = scrollHeight。其中,scrollTop 表示页面滚动距离,clientHeight 表示当前可见区域高度,scrollHeight 表示页面总高度。
  3. 如果当前已经滚动到页面底部,则发起异步请求获取更多的数据。可以使用 fetchaxios 等网络请求库。
  4. 将获取到的新数据添加到已有数据列表中。为了避免频繁的数据操作,可以使用 Immutable.js 库进行列表操作。
  5. 更新状态或数据,使页面显示新加载的数据。
  6. 如果已经没有更多数据,可以通过在页面显示“没有更多数据”或隐藏加载更多按钮等方式提醒用户。

实现加载更多功能时,需要注意性能问题。一方面,需要避免频繁触发请求和数据操作,另一方面,也需要避免过多的数据加载导致页面渲染变慢。因此,可以通过设置防抖、节流等方式来优化加载更多的实现。

原文链接:https://juejin.cn/post/7229909033896673338 作者:JoernLee

(0)
上一篇 2023年5月7日 上午10:41
下一篇 2023年5月7日 上午10:51

相关推荐

发表评论

登录后才能评论