无限加载,上拉刷新

1.触底无限加载

原理:监听父元素的滚动事件;利用元素的滚动距离scrollTop与元素的视口的高度clientHeight之和与该元素的滚动高度scrollHeight进行比较,即el.scrollTop + el.clientHeight >= el.scrollHeight 时,说明元素滚动到底部了,此时,可以调用接口,再加载数据

下面是一个js模拟触底无限加载的效果

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  * {
    padding: 0;
    margin: 0;
  }

  .demo {
    width: 500px;
    height: 800px;
    border: 1px solid #f5f;
    margin: auto;
    overflow-y: auto;
  }

  .demo::-webkit-scrollbar {
    display: none;
  }

  .item {
    width: calc(100% - 20px);
    margin: 10px;
  }

  .load-more {
    width: 60px;
    height: 60px;
    text-align: center;
    margin: 0 auto;
    line-height: 60px;
    border-top: 1px solid #ddd;
    transition: transform 0.3s ease-in-out;
  }

  .text {
    transition: opacity 0.3s ease-in-out;
  }

  .loading {
    animation: scroll 1s infinite linear;
  }

  @keyframes scroll {
    0% {
      transform: rotate(0deg);
    }

    100% {
      transform: rotate(360deg);
    }
  }
</style>

<body>

  <div class="demo">
    <div class="list"></div>
    <div class="load-more">
      <div class="text">加载更多</div>
    </div>
  </div>

  <script>

    var i = 0;
    var data = Array.from({ length: 50 }, () => ({ name: ++i, age: parseInt(Math.random() * 100) })) //随机创建数据
    var moreData = Array.from({ length: 20 }, () => ({ name: "new" + ++i, age: parseInt(Math.random() * 100) })) //更多的数据

    var demo = document.querySelector(".demo") //获取最外层容器
    var list = document.querySelector(".list") //获取列表容器
    var loadMore = document.querySelector(".load-more") //获取加载更多容器
    var text = document.querySelector(".text") //获取父容器
    var isLoading = false //是否在加载

    data.forEach(item => {
      let itemEl = document.createElement("div");
      itemEl.classList.add("item");
      itemEl.innerText = `name: ${item.name}; age: ${item.age}`
      list.appendChild(itemEl)
    })

    demo.addEventListener("scroll", handleScroll) //监听滚动事件

    function handleScroll() {
      if (demo.scrollTop + demo.clientHeight >= demo.scrollHeight && !isLoading) {
        isLoading = true;
        text.style.opacity = "0"
        loadMore.style.transform = "translateY(0)"
        loadMore.classList.add("loading")
        setTimeout(() => {
          addDataChild()
        }, 2000)
      }
    }

    function addDataChild() { //添加数据
      moreData.forEach(item => {
        let itemEl = document.createElement("div");
        itemEl.classList.add("item");
        itemEl.innerText = `name: ${item.name}; age: ${item.age}`
        list.appendChild(itemEl)
      })

      resetStyle()
    }

    function resetStyle() { //重置样式
      text.style.opacity = "1"
      loadMore.style.transform = "translateY(100%)"
      loadMore.classList.remove("loading")
      isLoading = false
    }

  </script>

</body>

</html>
2.上滑刷新

原理:利用dom操作,监听滑动事件

demo.addEventListener("touchstart", handleStart) //开始滑动
demo.addEventListener("touchmove", handleMove) //滑动中
demo.addEventListener("touchend", handleEnd) //滑动结束

//touchstart和touchend都只会触发一次
//touchmove在滑动过程中会一直触发

完整代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<style>
  * {
    margin: 0;
    padding: 0;
  }

  .demo {
    width: 500px;
    height: 700px;
    margin: 100px auto;
    border: 1px solid #ddd;
    background: #f5f5f5;
    overflow-y: auto;
  }

  .fresh {
    transition: transform 0.3 ease-in-out;
    height: 20px;
  }

  .arrow {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.3 ease-in-out;
  }

  .arrow::before {
    content: "";
    position: absolute;
    top: 2px;
    width: 6px;
    height: 6px;
    border: 1px solid transparent;
    border-top: 1px solid red;
    border-right: 1px solid red;
    transform: rotate(-45deg);
  }

  .arrow::after {
    content: "";
    position: absolute;
    top: 2px;
    width: 2px;
    height: 16px;
    background: red;
  }

  .loading {
    animation: scroll 1s infinite linear;
  }

  @keyframes scroll {
    0% {
      transform: rotate(0deg);
    }

    100% {
      transform: rotate(360deg);
    }
  }

  .item {
    height: 20px;
    line-height: 20px;
    margin: 10px;
  }
</style>

<body>

  <div class="demo">
    <div class="fresh">
      <div class="arrow"></div>
    </div>
    <div class="list">

    </div>
  </div>

  <script>

    let demo = document.querySelector(".demo")
    let fresh = document.querySelector(".fresh")
    let arrow = document.querySelector(".arrow")
    let list = document.querySelector(".list")
    let initData = Array.from({ length: 50 }, () => Math.random() * 50) //初始化数据
    let startY = null, currentY = null, isRefresh = false;

    initData.forEach(el => {
      let elItem = document.createElement("div")
      elItem.classList.add("item")
      elItem.innerText = el
      list.appendChild(elItem)
    })

    demo.addEventListener("touchstart", handleStart) //开始滑动
    demo.addEventListener("touchmove", handleMove) //滑动中
    demo.addEventListener("touchend", handleEnd) //滑动结束

    function handleStart(e) {
      if (demo.scrollTop === 0) {
        startY = e.touches[0].clientY
      }
    }

    function handleMove(e) {
      if (startY === null) { //若没有到页面顶部,则不让计算滑动距离
        return
      }

      console.log("e", e);

      currentY = e.touches[0].clientY;
      const diffY = currentY - startY //计算距离

      if (diffY > 0 && !isRefresh) {
        e.preventDefault()

        fresh.style.transform = `translateY(${diffY}px)`;
        
        if (diffY >= 60) { //滑动到一定距离才开始计算刷新

          arrow.style.transform = `rotate(180deg)`

        } else {
          arrow.style.transform = `rotate(0deg)`
        }

      }

    }

    function handleEnd() {
      if (startY === null) {
        return
      }

      if (currentY - startY >= 60 && !isRefresh) {
        isRefresh = true; //开始处理加载
        arrow.style.transform = `rotate(0deg)`
        fresh.style.transform = `translateY(0)`;
        startY = null
        currentY = null
        addDaat() //加载新数据
      } else {
        startY = null
        currentY = null
        isRefresh = false
        arrow.style.transform = `rotate(0deg)`
        fresh.style.transform = `translateY(0)`;
      }
    }

    function addDaat() {
      initData.forEach(el => {
        let elItem = document.createElement("div")
        elItem.classList.add("item")
        elItem.innerText = el
        list.appendChild(elItem)
      })

      isRefresh = false //重置下拉状态
    }

  </script>

</body>

</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值