H5 下拉加载更多(模拟微信聊天记录)
作者:互联网
前言
前段时间用H5实现一个实时聊天的功能。发现很难实现像微信聊天记录一样下拉加载更多记录。市面上大部分的 Web 项目实现的效果都是上拉加载,下拉刷新。下拉加载更多很少见,下拉在加载数据方面与上拉是一样的,但是如何做到像微信聊天记录一样,下拉之后还是保留在原有的位置就需要思考一下了。
下拉与上拉区别
下拉与上拉在加载数据上面基本一致,但是因为方向不同,所以也存在以下不同之处。
- 上拉是将数据加载到原数据后面,所以用的是数组拼接 concat 方法。而下拉是将数据添加到原数据前面,所以需要使用 unshift 方法。
- 上拉是滑动到底部时触发,下拉是滑动到顶部时触发,因此判断 scrollTop 为 0 时触发,触发完之后需要将 scrollTop 重置一下。
- 为了模拟微信聊天记录加载方式,下拉之后需要滑动到原先的位置。通过 scrollTo 方法实现,scrollTo(x,y) 接收两个参数,x 为页面 X 轴,y 为页面 Y 轴,这里显然是需要修改 Y 轴的距离。x 为 0 即可。而 y 值就是第一次的 scrollHeight 滑动高度,因为每次加载的数据都是一样的,所以使用 scrollHeight 作为上次滑动位置。
- 代码中有很多定时器的使用,主要是为了防止用户频繁滑动(节流)以及在列表渲染之后再去获取 DOM 属性。
实现思路
- 封装一个加载数据的方法,首先加载初始数据;
- 获取列表的 scrollHeight,将记录定位到最底部,也就是最新的记录在可视区域的最下面。
- 监听滑动,当滑动到最顶部时,加载一屏数据,同时滑动定位到上次初始的位置。
完整代码如下
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.container {
width: 300px;
height: 300px;
overflow: auto;
border: 1px solid;
margin: 100px auto;
}
.item {
height: 29px;
line-height: 30px;
text-align: center;
border-bottom: 1px solid #aaa;
}
</style>
</head>
<body>
<div id="app">
<div class="container" ref="container">
<div class="item">{{loadText+"第"+pageNum+"页"}}</div>
<div v-for="(item, index) in list" :key="index" class="item">{{item}}</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
scrollHeight: 0,
list: [],
loadText:"加载中...",
pageSize:20,
pageNum:1,
},
mounted() {
this.initData();
const container = this.$refs.container;
//这里的定时是为了列表首次渲染后获取scrollHeight并滑动到底部。
setTimeout(() => {
this.scrollHeight = container.scrollHeight;
container.scrollTo(0, this.scrollHeight);
}, 10);
container.addEventListener('scroll', (e) => {
//这里的2秒钟定时是为了避免滑动频繁,节流
setTimeout(() => {
if(this.list.length>=90){
this.loadText = "加载完成";
return;
}
//滑到顶部时触发下次数据加载
if (e.target.scrollTop == 0) {
//将scrollTop置为10以便下次滑到顶部
e.target.scrollTop = 10;
//加载数据
this.initData();
//这里的定时是为了在列表渲染之后才使用scrollTo。
setTimeout(() => {
e.target.scrollTo(0, this.scrollHeight - 30);//-30是为了露出最新加载的一行数据
}, 100);
}
}, 2000);
});
},
methods:{
//初始数据
initData() {
for (var i = 20; i > 0; i--) {
this.list.unshift(i)
}
this.pageNum++;
}
}
})
</script>
</body>
</html>
标签:container,微信,聊天记录,H5,scrollTop,滑动,数据,scrollHeight,加载 来源: https://blog.csdn.net/Sensation_cyq/article/details/112661714