feat: 首页高度是否足够适配下拉加载历史数据

master
LCJ-MinYa 12 months ago
parent 53381c93e7
commit c1f98b5c16

@ -36,6 +36,14 @@ const titleArr = [
key: 'borderArrow', key: 'borderArrow',
title: 'div边框箭头和阴影问题', title: 'div边框箭头和阴影问题',
}, },
{
key: 'pullLoadData',
title: '首页高度不够,手写移动端下拉加载历史数据',
},
{
key: 'autoLoadData',
title: '首页高度足够,自动触发下拉加载数据',
},
]; ];
// @/views/demo/**/*.vue // @/views/demo/**/*.vue

@ -0,0 +1,96 @@
<template>
<div
ref="boxRef"
class="box"
v-loading="loading"
@scroll.passive="handleScroll"
>
<div ref="contentRef">
<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">
/**
* 自动下拉加载数据注意事项
* 1. 布局容器必须是一个外层box并且设置高度纵向允许滚动,否则监听滚动事件不生效 大约是 => 100vh => 667px这种(举例高度设备不一样高度不一样)
* 2. 内容容器content, 自动高度由内容决定滚动时其高度一定是超过容器高度的 如果有三页内容高度为(667 * 3)px
*/
import { ref, onMounted, nextTick } from 'vue';
import { debounce } from '@pureadmin/utils';
const boxRef = ref(null);
const contentRef = ref(null);
const list = ref([]);
const loading = ref(false);
const beforeHeight = ref(null);
const getData = (isFirstLoadData = false) => {
console.log(contentRef.value.clientHeight, '内部内容的整体高度');
loading.value = true;
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);
if (isFirstLoadData) {
//
nextTick(() => contentRef.value.scrollIntoView(false));
} else {
//
nextTick(() => (boxRef.value.scrollTop = contentRef.value.clientHeight - beforeHeight.value));
}
}, 2000);
};
const scrollLoadData = () => {
console.log('监听滚动事件');
const { scrollTop } = boxRef.value;
console.log(scrollTop, '整个容器当前滚动条位置');
console.log(contentRef.value.clientHeight, '内部内容的整体高度');
if (scrollTop < 20) {
getData(false);
}
};
const handleScroll = debounce(scrollLoadData, 500);
onMounted(() => {
getData(true);
});
</script>
<style lang="scss" scoped>
.box {
display: flex;
flex-direction: column;
align-items: center;
background: #fff;
// auto
height: calc(100vh - 81px);
overflow-y: auto;
h2 {
height: 150px;
}
}
</style>

@ -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;
// debouncedebounctouchend
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>
Loading…
Cancel
Save