html
复制代码
<template>
<div class="root">
<div class="container" ref="container" @scroll="onScroll">
<!-- 瀑布流列表 -->
<transition-group name="list" tag="div" class="list">
<div
v-for="(item, index) in items"
:key="item._uid"
class="list-item"
>
{{ item.text }}
</div>
</transition-group>
<!-- 加载状态 -->
<div class="loading" v-if="loading">加载中...</div>
<div class="loading" v-else-if="allLoaded">没有更多数据了</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
page: 1,
pageSize: 10,
allLoaded: false,
loading: false,
pushTimer: null, // 定时器
};
},
created() {
this.loadMore();
// 定时推送消息,每 3 秒一次
this.pushTimer = setInterval(() => {
this.pushMessage();
}, 3000);
},
beforeDestroy() {
// 清理定时器
if (this.pushTimer) {
clearInterval(this.pushTimer);
}
},
methods: {
loadMore() {
if (this.loading || this.allLoaded) return;
this.loading = true;
setTimeout(() => {
const newItems = Array.from({ length: this.pageSize }).map((_, i) => ({
_uid: Date.now() + Math.random() + i,
text: `列表数据 第${(this.page - 1) * this.pageSize + i + 1}条`,
}));
this.items = [...this.items, ...newItems];
this.page++;
this.loading = false;
if (this.page > 5) this.allLoaded = true;
}, 500);
},
pushMessage() {
const message = {
_uid: Date.now() + Math.random(),
text: `【推送消息】 ${new Date().toLocaleTimeString()}`,
};
// 插入到最前面
this.items = [message, ...this.items];
},
onScroll() {
const container = this.$refs.container;
if (!container) return;
const scrollBottom =
container.scrollHeight - container.scrollTop - container.clientHeight;
if (scrollBottom < 100) {
this.loadMore();
}
},
},
};
</script>
<style scoped>
.root {
display: flex;
flex-direction: column;
align-items: center;
}
.container {
width: 400px;
height: 500px;
overflow-y: auto;
border: 1px solid #ccc;
padding: 10px;
box-sizing: border-box;
margin-bottom: 10px;
}
.list {
display: flex;
flex-direction: column;
}
.list-item {
background: #f0f0f0;
margin-bottom: 10px;
padding: 15px;
border-radius: 8px;
transition: all 0.3s ease;
}
/* transition-group 动画 */
.list-enter-active {
animation: fadeInDown 0.4s;
}
.list-leave-active {
animation: fadeOutUp 0.4s;
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeOutUp {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-20px);
}
}
.loading {
text-align: center;
padding: 10px;
color: #999;
}
</style>