目录
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
},