73 lines
1.6 KiB
Vue
73 lines
1.6 KiB
Vue
|
<template>
|
|||
|
<view class="container">
|
|||
|
<scroll-view
|
|||
|
scroll-y
|
|||
|
class="scroll"
|
|||
|
:scroll-top="scrollTop"
|
|||
|
@scroll="onScroll"
|
|||
|
:scroll-with-animation="false"
|
|||
|
>
|
|||
|
<view
|
|||
|
v-for="(item, index) in renderList"
|
|||
|
:key="index"
|
|||
|
class="item"
|
|||
|
>
|
|||
|
{{ item }}
|
|||
|
</view>
|
|||
|
</scroll-view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script setup>
|
|||
|
import { ref, onMounted, nextTick } from 'vue'
|
|||
|
|
|||
|
// 原始数据
|
|||
|
const baseList = Array.from({ length: 10 }, (_, i) => `第 ${i + 1} 项`)
|
|||
|
const renderList = ref([]) // 显示的3倍数据
|
|||
|
const itemHeight = 100 // 每项高度(rpx)需与你样式保持一致
|
|||
|
const scrollTop = ref(0)
|
|||
|
const totalHeight = baseList.length * itemHeight * 3
|
|||
|
|
|||
|
onMounted(() => {
|
|||
|
// 三倍复制数据(上下留出空间)
|
|||
|
renderList.value = [...baseList, ...baseList, ...baseList]
|
|||
|
|
|||
|
// 滚动到中间(第二组开头)
|
|||
|
nextTick(() => {
|
|||
|
scrollTop.value = baseList.length * itemHeight
|
|||
|
})
|
|||
|
})
|
|||
|
|
|||
|
function onScroll(e) {
|
|||
|
const currentTop = e.detail.scrollTop
|
|||
|
|
|||
|
const singleHeight = baseList.length * itemHeight
|
|||
|
const threshold = 20 // 触发回跳的阈值(rpx)
|
|||
|
|
|||
|
// 回到中间,形成无缝循环
|
|||
|
if (currentTop <= threshold) {
|
|||
|
scrollTop.value = singleHeight + currentTop
|
|||
|
} else if (currentTop >= singleHeight * 2 - threshold) {
|
|||
|
scrollTop.value = currentTop - singleHeight
|
|||
|
}
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style scoped>
|
|||
|
.container {
|
|||
|
height: 100vh;
|
|||
|
overflow: hidden;
|
|||
|
}
|
|||
|
.scroll {
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
.item {
|
|||
|
height: 100rpx;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
border-bottom: 1px solid #eee;
|
|||
|
background: #fff;
|
|||
|
}
|
|||
|
</style>
|