You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.5 KiB
87 lines
2.5 KiB
1 year ago
|
<template>
|
||
|
<!-- @scrolltolower触底事件,@scroll滚动事件 -->
|
||
|
<scroll-view scroll-y="true" :style="{height: containerHeight+'px'}" @scroll="scrollTop = $event.detail.scrollTop"
|
||
|
@scrolltolower="$emit('@scrolltolower')">
|
||
|
<!-- 监听滚动事件使用passive修饰符 -->
|
||
|
<view :style="paddingStyle">
|
||
|
<!-- key使用index,可避免多次渲染该dom -->
|
||
|
<view id="box" v-for="(item, index) in showList" :key="index">
|
||
|
<!-- 使用作用域插槽,将遍历后的数据item和index传递出去 -->
|
||
|
<slot :item="item" :$index="index"></slot>
|
||
|
</view>
|
||
|
</view>
|
||
|
</scroll-view>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
export default {
|
||
|
name: "App",
|
||
|
props: {
|
||
|
// 所有数据
|
||
|
allList: {
|
||
|
type: Array,
|
||
|
default () {
|
||
|
return []
|
||
|
}
|
||
|
},
|
||
|
// 容器高度
|
||
|
containerHeight: {
|
||
|
type: Number,
|
||
|
default: 0
|
||
|
},
|
||
|
},
|
||
|
data() {
|
||
|
return {
|
||
|
oneHeight: 200, // 单个元素的高度,默认200.在mounted中会再次回去单个元素高度
|
||
|
scrollTop: 0 // 滚动距离
|
||
|
};
|
||
|
},
|
||
|
async mounted() {
|
||
|
// 计算单个元素的高度
|
||
|
await this.$nextTick(() => {
|
||
|
|
||
|
})
|
||
|
|
||
|
// uniapp中获取高度的兼容写法
|
||
|
const query = uni.createSelectorQuery();
|
||
|
console.log('query.select :>> ', query.select('#box').boundingClientRect);
|
||
|
query.select('#box').boundingClientRect(data => {
|
||
|
console.log('data :>> ', data);
|
||
|
this.oneHeight = data.height
|
||
|
}).exec();
|
||
|
},
|
||
|
computed: {
|
||
|
// 一屏多少条数据
|
||
|
showNum() {
|
||
|
return ~~(this.containerHeight / this.oneHeight) + 2;
|
||
|
},
|
||
|
// 开始索引
|
||
|
startIndex() {
|
||
|
// 可见区域,第一个元素的index
|
||
|
const curIndex = ~~(this.scrollTop / this.oneHeight)
|
||
|
// console.log(this.showNum, this.oneHeight)
|
||
|
// 渲染区域第一个元素的index,这里缓冲区域的列表条数使用的是this.showNum
|
||
|
return curIndex < this.showNum ? 0 : curIndex - this.showNum
|
||
|
},
|
||
|
// 渲染元素最后的index
|
||
|
endIndex() {
|
||
|
// 可见区域,第一个index
|
||
|
const curIndex = ~~(this.scrollTop / this.oneHeight)
|
||
|
let end = curIndex + this.showNum * 3; // 2倍是需要预留缓冲区域
|
||
|
let len = this.allList.length
|
||
|
return end >= len ? len : end; // 结束元素大于所有元素的长度时,就取元素长度
|
||
|
},
|
||
|
// 需要渲染的数据
|
||
|
showList() {
|
||
|
return this.allList.slice(this.startIndex, this.endIndex)
|
||
|
},
|
||
|
// 空白占位的高度
|
||
|
paddingStyle() {
|
||
|
return {
|
||
|
paddingTop: this.startIndex * this.oneHeight + 'px',
|
||
|
paddingBottom: (this.allList.length - this.endIndex) * this.oneHeight + 'px'
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
};
|
||
|
</script>
|