|
|
|
@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
ref="boxRef"
|
|
|
|
|
|
|
|
class="box"
|
|
|
|
|
|
|
|
v-loading="loading"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<div ref="contentRef">
|
|
|
|
|
|
|
|
<h3>———下拉加载更多数据———</h3>
|
|
|
|
|
|
|
|
<h2
|
|
|
|
|
|
|
|
v-for="(item, index) in list"
|
|
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
{{ item }}
|
|
|
|
|
|
|
|
</h2>
|
|
|
|
|
|
|
|
<h1>请使用移动端调试模式打开</h1>
|
|
|
|
|
|
|
|
<h2>这里是模拟数据1</h2>
|
|
|
|
|
|
|
|
<h2>这里是模拟数据1</h2>
|
|
|
|
|
|
|
|
<h2>这里是模拟数据1</h2>
|
|
|
|
|
|
|
|
<h2>这里是模拟数据1</h2>
|
|
|
|
|
|
|
|
<h2>这里是模拟数据1</h2>
|
|
|
|
|
|
|
|
<h2>首屏数据到此</h2>
|
|
|
|
|
|
|
|
<h2>模拟数据不够一页下拉加载</h2>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="jsx">
|
|
|
|
|
|
|
|
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
|
|
|
|
|
|
|
|
import { debounce } from '@pureadmin/utils';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const boxRef = ref(null);
|
|
|
|
|
|
|
|
const contentRef = ref(null);
|
|
|
|
|
|
|
|
const list = ref([]);
|
|
|
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
|
|
|
let startY = 0;
|
|
|
|
|
|
|
|
const beforeHeight = ref(null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getData = () => {
|
|
|
|
|
|
|
|
console.log(contentRef.value.clientHeight, '内部内容的整体高度');
|
|
|
|
|
|
|
|
console.log('加载数据');
|
|
|
|
|
|
|
|
beforeHeight.value = contentRef.value.clientHeight;
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
|
|
loading.value = false;
|
|
|
|
|
|
|
|
let tempList = [];
|
|
|
|
|
|
|
|
let currentLength = list.value.length;
|
|
|
|
|
|
|
|
for (let i = 20; i > 0; i--) {
|
|
|
|
|
|
|
|
tempList.push(`模拟数据${i + currentLength}`);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
list.value = tempList.concat(list.value);
|
|
|
|
|
|
|
|
// 下拉加载数据,滚动条滚动到加载数据前位置
|
|
|
|
|
|
|
|
nextTick(() => (boxRef.value.scrollTop = contentRef.value.clientHeight - beforeHeight.value));
|
|
|
|
|
|
|
|
}, 2000);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleTouchstart = (e) => {
|
|
|
|
|
|
|
|
startY = e.touches[0].clientY;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleTouchmove = (e) => {
|
|
|
|
|
|
|
|
console.log('监听鼠标移动事件', e);
|
|
|
|
|
|
|
|
if (!shouldHandleTouch()) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const currentY = e.touches[0].clientY;
|
|
|
|
|
|
|
|
if (currentY - startY > 100) {
|
|
|
|
|
|
|
|
e.preventDefault && e.preventDefault();
|
|
|
|
|
|
|
|
loading.value = true;
|
|
|
|
|
|
|
|
// 这里调用是因为debounce的原因,debounc会延迟,导致touchend事件先执行,所以这里需要手动触发一次
|
|
|
|
|
|
|
|
handleTouchend();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const debounceHandleTouchmove = debounce(handleTouchmove, 500);
|
|
|
|
|
|
|
|
const handleTouchend = () => {
|
|
|
|
|
|
|
|
if (loading.value) {
|
|
|
|
|
|
|
|
getData();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const shouldHandleTouch = () => {
|
|
|
|
|
|
|
|
console.log(boxRef.value.scrollTop, '整个容器当前滚动条位置');
|
|
|
|
|
|
|
|
if (boxRef.value.scrollTop > 0 || loading.value) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const addTouchEventListeners = () => {
|
|
|
|
|
|
|
|
boxRef.value.addEventListener('touchstart', handleTouchstart);
|
|
|
|
|
|
|
|
boxRef.value.addEventListener('touchmove', debounceHandleTouchmove);
|
|
|
|
|
|
|
|
boxRef.value.addEventListener('touchend', handleTouchend);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const removeTouchEventListeners = () => {
|
|
|
|
|
|
|
|
boxRef.value.removeEventListener('touchstart', handleTouchstart);
|
|
|
|
|
|
|
|
boxRef.value.removeEventListener('touchmove', debounceHandleTouchmove);
|
|
|
|
|
|
|
|
boxRef.value.removeEventListener('touchend', handleTouchend);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
|
|
addTouchEventListeners();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
|
|
|
removeTouchEventListeners();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
|
|
.box {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
|
|
height: calc(100vh - 81px);
|
|
|
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
h2 {
|
|
|
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|