uniapp vue3 虚拟下拉滚动 初始版
下面是vue3的写法 如果想查看vue2的写法 请移步至github链接 https://github.com/Arvin-Cui/vue-virtual-scroll/blob/master/pages/index/index.vue
1.index.vue index.vue页面中加一个共用组件VirtualList.vue
最终效果图
1.index.vue index.vue页面中加一个共用组件VirtualList.vue
<template>
<view>
<VirtualList :listData="state.dateList" :itemSize="100"></VirtualList>
</view>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { onShow } from '@dcloudio/uni-app'
const state = reactive({
dateList: []
})
onShow(() => {
inits()
})
const inits = () => {
state.dateList = [
{ name: 1 },{ name: 2 }, { name: 3 }, { name: 4 },{ name: 5 }, { name: 6 }, { name: 7 },{ name: 8 },{ name: 9 }, { name: 10 },
{ name: 11 },{ name: 12 },{ name: 13 },{ name: 14 },{ name: 15 },{ name: 16 },{ name: 17 },{ name: 18 },{ name: 19 },{ name: 20 },
{ name: 21 },{ name: 22 },{ name: 23 },{ name: 24 },{ name: 25 },{ name: 26 },{ name: 27 },{ name: 28 },{ name: 29 },{ name: 30 },
{ name: 31 },{ name: 32 },{ name: 33 },{ name: 34 },{ name: 35 },{ name: 36 },{ name: 37 },{ name: 38 },{ name: 39 },{ name: 40 },
{ name: 41 },{ name: 42 },{ name: 43 },{ name: 44 },{ name: 45 },{ name: 46 },{ name: 47 },{ name: 48 },{ name: 49 },{ name: 50 },
{ name: 51 },{ name: 52 },{ name: 53 },{ name: 54 },{ name: 55 },{ name: 56 },{ name: 57 },{ name: 58 },{ name: 59 },{ name: 60 },
{ name: 61 },{ name: 62 },{ name: 63 },{ name: 64 },{ name: 65 },{ name: 66 },{ name: 67 },{ name: 68 },{ name: 69 },{ name: 70 },
{ name: 71 },{ name: 72 },{ name: 73 },{ name: 74 },{ name: 75 },{ name: 76 },{ name: 77 },{ name: 78 },{ name: 79 },{ name: 80 },
{ name: 81 },{ name: 82 },{ name: 83 },{ name: 84 },{ name: 85 },{ name: 86 },{ name: 87 },{ name: 88 },{ name: 89 },{ name: 90 },
{ name: 91 },{ name: 92 },{ name: 93 },{ name: 94 },{ name: 95 },{ name: 96 },{ name: 97 },{ name: 98 }, { name: 99 },{ name: 100 },
{ name: 101 },{ name: 102 }, { name: 103 }, { name: 104 },{ name: 105 }, { name: 106 }, { name: 107 },{ name: 108 },{ name: 109 }, { name: 110 },
{ name: 111 },{ name: 112 },{ name: 113 },{ name: 114 },{ name: 115 },{ name: 116 },{ name: 117 },{ name: 118 },{ name: 119 },{ name: 120 },
{ name: 121 },{ name: 122 },{ name: 123 },{ name: 124 },{ name: 125 },{ name: 126 },{ name: 127 },{ name: 128 },{ name: 129 },{ name: 130 },
{ name: 131 },{ name: 132 },{ name: 133 },{ name: 134 },{ name: 135 },{ name: 136 },{ name: 137 },{ name: 138 },{ name: 139 },{ name: 140 },
{ name: 141 },{ name: 142 },{ name: 143 },{ name: 144 },{ name: 145 },{ name: 146 },{ name: 147 },{ name: 148 },{ name: 149 },{ name: 150 },
{ name: 151 },{ name: 152 },{ name: 153 },{ name: 154 },{ name: 155 },{ name: 156 },{ name: 157 },{ name: 158 },{ name: 159 },{ name: 160 },
{ name: 161 },{ name: 162 },{ name: 163 },{ name: 164 },{ name: 165 },{ name: 166 },{ name: 167 },{ name: 168 },{ name: 169 },{ name: 170 },
{ name: 171 },{ name: 172 },{ name: 173 },{ name: 174 },{ name: 175 },{ name: 176 },{ name: 177 },{ name: 178 },{ name: 179 },{ name: 180 },
{ name: 181 },{ name: 182 },{ name: 183 },{ name: 184 },{ name: 185 },{ name: 186 },{ name: 187 },{ name: 188 },{ name: 189 },{ name: 190 },
{ name: 191 },{ name: 192 },{ name: 193 },{ name: 194 },{ name: 195 },{ name: 196 },{ name: 197 },{ name: 198 }, { name: 199 },{ name: 200 },
]
}
</script>
<style lang="scss" scoped>
</style>
2.VirtualList.vue 页面 逻辑都在这个页面
<template>
<template>
<view class="content">
<!-- 使用 scroll-view 组件来实现滚动 -->
<scroll-view
ref="list"
scroll-y="true"
class="list-container"
@scroll="handleScroll"
style="height: 100vh"
:scroll-top="state.startOffset"
>
<view class="list-phantom" :style="{ height: listHeight + 'px' }"></view>
<view class="list" :style="{ transform: getTransform }">
<view
v-for="(item, index) in visibleData"
class="list-item"
:key="index"
:style="{ height: props.itemSize + 'px', lineHeight: props.itemSize + 'px' }"
>
{{ item.name }}
</view>
</view>
</scroll-view>
</view>
</template>
<script setup lang="ts">
import { reactive, onMounted, computed } from 'vue'
import { debounce } from '@/utils/tools'
const state = reactive({
listHeight: 0,
screenHeight: 0, // 屏幕高度即可视区域高度
startOffset: 0, // 顶部偏移量
startIndex: 0, // 可视化区域的数据开始下标
endIndex: 0 // 可视化区域的数据结束下标
})
const props = defineProps({
listData: {
type: Array,
default: () => []
},
//每项高度
itemSize: {
type: Number,
default: 200
}
})
const listHeight = computed(() => {
return props.listData.length * props.itemSize
})
const visibleCount = computed(() => {
return Math.ceil(state.screenHeight / props.itemSize) || 0
})
const getTransform = computed(() => {
return 'translate3d(0,' + state.startOffset + 'px,0)'
})
const visibleData = computed(() => {
return props.listData.slice(state.startIndex, Math.min(state.endIndex, props.listData.length))
})
onMounted(() => {
console.log(props.listData)
init()
})
const init = () => {
getScreenHeight()
// 设置初始滚动距离 state.startIndex = 0 如果不是从第一个开始滚动 num为第几个开始 state.startIndex = num state.startOffset = num * props.itemSize
// state.startIndex = 0
state.startIndex = 20
state.startOffset = 20 * props.itemSize
state.endIndex = state.startIndex + visibleCount.value
}
// 获取屏幕高度即可视化区域高度
const getScreenHeight = () => {
uni.getSystemInfo({
success: function (res) {
state.screenHeight = res.screenHeight
}
})
}
// 防抖 节流方法 debounce第三个参数没用 可以删除
const debounce= (fn, delay,_this) => {
vardelay = delay || 200
var timer = null
return function () {
let self = _this || this
let args = arguments
timer && clearTimeout(timer)
timer = setTimeout(function () {
timer = null
fn.apply(self, args)
}, delay)
}
}
const handleScroll = debounce(
(e) => {
//当前滚动位置
let scrollTop = e.detail.scrollTop
//开始索引
state.startIndex = Math.floor(scrollTop / props.itemSize)
//结束索引
state.endIndex = state.startIndex + visibleCount.value
//顶部偏移量
state.startOffset = scrollTop - (scrollTop % props.itemSize)
},
10,
''
)
</script>
<style lang="scss" scoped>
.list-container {
height: 100%;
overflow: auto;
position: relative;
.list-phantom {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
}
.list {
left: 0;
right: 0;
top: 0;
position: absolute;
.list-item {
text-align: center;
border-bottom: 1px solid #ccc;
}
}
}
</style>