目录

1.js

2.vue2

3.vue3

4.element组件 


 元素的滚动距离:scrollTop

 元素的可视距离:offsetHeight

 元素的滚动条总距离:scrollHeight

1.js

监听全局window

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Scroll Demo</title>
  </head>

  <body>
    <style>
      .box {
        height: 5000px;
        text-align: center;
      }
    </style>

    <div class="box" id="box">打开控制台查看</div>

    <!-- 引入节流方法 -->
    <script src="https://cdn.jsdelivr.net/npm/throttle-debounce@5.0.0/umd/index.min.js"></script>

    <script>
      // 滚动方向枚举值
      const DIRECTION_ENUM = {
        DOWN: "down",
        UP: "up",
      };

      // 距离顶部或底部的阈值
      const threshold = 20;

      // 记录前一个滚动位置
      let beforeScrollTop = 0;

      function handleScroll() {
        // 距顶部
        var scrollTop =
          document.documentElement.scrollTop || document.body.scrollTop;
        // 可视区高度
        var clientHeight =
          document.documentElement.clientHeight || document.body.clientHeight;
        // 滚动条总高度
        var scrollHeight =
          document.documentElement.scrollHeight || document.body.scrollHeight;

        // 打印数值
        console.table([
          {
            label: "距顶部",
            value: scrollTop,
          },
          {
            label: "可视区高度",
            value: clientHeight,
          },
          {
            label: "滚动条总高度",
            value: scrollHeight,
          },
          {
            label: "距顶部 + 可视区高度",
            value: scrollTop + clientHeight,
          },
        ]);

        // 确定滚动方向
        let direction = DIRECTION_ENUM.DOWN;
        if (beforeScrollTop > scrollTop) {
          direction = DIRECTION_ENUM.UP;
        }

        // 通过滚动方向判断是触底还是触顶
        if (direction == DIRECTION_ENUM.DOWN) {
          // 滚动触底
          if (scrollTop + clientHeight + threshold >= scrollHeight) {
            console.log("滚动触底");
          }
        } else {
          // 滚动到顶部
          if (scrollTop <= threshold) {
            console.log("滚动到顶部");
          }
        }

        beforeScrollTop = scrollTop;
      }

      // 滚动节流
      const throttleHandleScroll = throttleDebounce.throttle(
        1000,
        handleScroll
      );

      // 监听滚动
      window.addEventListener('scroll', throttleHandleScroll);

    </script>
  </body>
</html>

监听盒子内滚动

<style>
  .box-wrap {
    height: 500px;
    overflow-y: auto;
  }

  .box {
    height: 5000px;
    text-align: center;
  }
</style>

<div class="box-wrap" id="box">
  <div class="box">打开控制台查看</div>
</div>

<script>
  // 监听滚动
  let box = document.querySelector("#box");
  box.addEventListener("scroll", function (e) {
    let scrollTop = e.target.scrollTop;
    let clientHeight = e.target.clientHeight;
    let scrollHeight = e.target.scrollHeight;

    // 打印数值
    console.table([
      {
        label: "距顶部",
        value: scrollTop,
      },
      {
        label: "可视区高度",
        value: clientHeight,
      },
      {
        label: "滚动条总高度",
        value: scrollHeight,
      },
      {
        label: "距顶部 + 可视区高度",
        value: scrollTop + clientHeight,
      },
    ]);
  });
</script>

2.vue2

html

<template>
<div class="list" ref="scrollRef">
        <div class="li" v-for="item, index in pending" :key="index">
            <p>{{item.name}}</p>
        </div>
</div>
</template>

 js

mounted() {
    this.$nextTick(()=>{
        this.$refs.scrollRef.addEventListener('scroll',this.scroll)
    })
}

methods:{
    scroll(e) {
            let scrollTop = e.target.scrollTop; //滑入屏幕滚动条滚动时,距离顶部的距离
            let windowHeitht = e.target.clientHeight; //能看到的页面的高度
            let scrollHeight = e.target.scrollHeight; //监控的整个div的高度(包括现在看到的和上下隐藏起来看不到的)
            let total = scrollTop + windowHeitht
            if(total == scrollHeight){
                console.log("到底了")
                //加载操作
            }else {
                console.log("还没有到底")
            } 
        }
}

3.vue3

<template>
<div class="list" ref="scrollRef">
        <div class="li" v-for="item, index in pending" :key="index">
            <p>{{item.name}}</p>
        </div>
</div>
</template>

<script setup lang="ts">
import { onBeforeMount,  ref } from 'vue';
import { my_task } from "@/api"
// 分页
const page = ref(1)
const scrollRef = ref()//名字需要跟上面ref绑定的一样
// 数据列表
const pending = ref("")
// 请求列表数据
async function get_init() {
  // 筛选请求数据
  let res: any = await my_task({
    page: page.value
  })
  if (page.value > 1) {
    pending.value = [...pending.value, ...res.data.data]
  } else {
    pending.value = res.data.data
  }
}
// 滚动加载分页
onMounted(() => {
  scrollRef.value.addEventListener('scroll', () => {
    const { scrollTop, offsetHeight, scrollHeight } = scrollRef.value
    // console.log(scrollTop, offsetHeight, scrollHeight);
    let num = scrollTop / 1000
    //滚动条到达底部
    if (page.value < num) {
      page.value = Math.floor(num) + 1
      console.log("第", page.value, "页");
      get_init()  //筛选数据
    }
  })
})
</script>

<style lang="less" scoped>
.list {
    width: 518px;
    margin: 30px auto;
    border: 1px solid #a5a0a0;
    overflow-y: scroll;
    max-height: 550px;

    .li {
      padding: 20px;
      height: 114px;
      line-height: 20px;
      background-color: rgba(255, 255, 255, 1);
      color: rgba(16, 16, 16, 1);
      font-size: 14px;
      text-align: center;
      font-family: Roboto;
      margin-bottom: 15px;
      box-shadow: 0 0 5px #96969691;
    }
}
</style>

如果页面还有其他功能会改变页面数据 比如:筛选列表数据 会重新生成新的列表

需要清除当前的分页状态

page.value = 1 // 恢复初始值

scrollRef.value.scrollTop = 0 //滚动到顶部

4.element组件 

data里面定义

newlist: [], //列表数据

page: 1,//列表页数

last_page: 1, //最大页数

这些数据都是后端返回的,在请求数据后赋值到data

<ul class="infinite-list" v-infinite-scroll="load" style="overflow:auto">
    <li v-for="i in count" class="infinite-list-item">{{ i }}</li>
  </ul>

不需要在css设置高度

// 滚动到底部刷新数据
        load() {
                // 判断加载到了最后一页就不请求了,不然会到底部重复加载
            if (this.page < this.last_page) {
                this.page += 1
                this.remind(this.page)
            }
            // console.log("下一页",this.page);
        },
 // 提醒数据 以下是我的请求数据方法 不用复制
        async remind(page: any) {
            let res: any = await remind({ page })
            // 最大页数赋值
            this.last_page = res.data.list.last_page
            // console.log(res.data.list);
            if (page == 1) {
                this.newlist = res.data.list.data
            } else {
                let list: any = this.newlist
                 // 数据合并,不然只有当前请求的一页的数据
                let newlist: any = [...list, ...res.data.list.data]
                this.newlist = newlist
            }
            // 数据总条数
            this.badge = res.data.total
        },