apicloud ul 动态绑定li_如何优雅的写动态加载

06cd4cbbe59a16c6b4a81a70bf0ca4b1.png

列表上划加载更多是常见需求,与全量加载的列表相比,动态列表多了当前页码、是否加载完全和结果拼接等工作,这些逻辑散落在组件里,既不直观也容易出错,因此思考能不能有更优雅的实现。

改进思路

对于列表组件来说,关注的数据只有 resultisEnd,前者用来展示数据,后者用来在最后一行显示“加载中”还是“已显示全部结果”,那么,希望有一个 loadData 方法,每次调用都返回最新的 { result, isEnd } 供列表组件使用。而对于当前页面、每页大小等其他信息,由 loadData 自己维护。

具体实现

// services.js

export function createLoadData(url, pageSize = 15) {
  const result = []
  let pageNum = 0, isEnd = false

  return async function () {
    if (isEnd) return { result, isEnd }

    const res = await axios.get(`${url}?pageNum=${pageNum++}&pageSize=${pageSize}`);

    // 也可以用 currentCount === totalCount 或其他条件判断是否结束
    if (res.data.length === 0) {
      isEnd = true
    }
    
    result.push(...res.data.map(item => ({
      // 这里进行数据字段适配
      id: item.id,
      name: item.display_name
    })))

    return { result, isEnd }
  }
}

// ItemList.js

import { createLoadData } from './services'

export default function ItemList() {
  const [result, setResult] = useState([])
  const [loadEnd, setLoadEnd] = useState(false)

  const loadFunc = useRef(noop)

  useEffect(() => {
    loadFunc.current = createLoadData(url)
    loadData();
  }, [])

  async function loadData() {
    const { result, isEnd } = await loadFunc.current();
    setResult(result)
    setLoadEnd(isEnd)
  }

  function handleScroll(e) {
    const { scrollTop, scrollHeight, clientHeight } = e.target;

    // 触底加载
    if (scrollTop + clientHeight >= scrollHeight) {
      loadData()
    }
  }

  return (
    <div className='item-list' onScroll={handleScroll}>
      <ul>
        {result.map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
      {loadEnd ? <p>已加载全部数据</p> : <p>加载中</p>}
    </div>
  )
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值