虚拟滚动平级数据结构
import { onMounted, defineComponent, ref, computed, watch, toRefs } from 'vue'
const Index = defineComponent({
props: {
/**
* 可见区域内显示多少条--区域高度/每一条记录的样式高度
*/
pageSize: {
type: Number,
default: 20
},
/**
* 数组数据
*/
list: {
type: Array,
default: []
},
/**
* 容器高度
*/
height: {
type: Number,
default: 400
},
/**
* 获取接口函数
*/
getData: {
type: Function
},
/**
* 获取接口的参数
*/
params: {
type: Object,
default: {}
}
},
name: 'virtualScroll',
setup(props, ctx) {
const { pageSize, height, params } = toRefs(props)
const getData = props.getData
const list = ref([])
const startIndex = ref(0) // 当前区域显示的数据起始index
const endIndex = ref(pageSize.value) // 数据结束index
const paddingTop = ref(0) // 当前区域下scrollList区域的paddingtop值
const paddingBottom = ref(0) // 当前区域下scrollList区域的paddingbottom值
const allHeight = ref(0) // 大量无数条数据的高度
const itemHeight = ref(22)
const myRef = ref(null)
const scrollList = computed(() => list.value.slice(startIndex.value, endIndex.value)) //滚动区域的数据集合
const defaultStyle = {'overflow-y': 'auto', 'height': height.value + 'px'}
/**
* 滚动区域的样式
*/
const style = computed(() => {
return {
paddingTop: paddingTop.value + 'px',
paddingBottom: paddingBottom.value + 'px'
}
})
/**
* 监听滚动条的滚动事件
*/
const scroll = (e) => {
const container = document.getElementById('container')
const top = container.scrollTop
startIndex.value = Math.floor(top / itemHeight.value) // 已经滚走了多少条数据 (当前区域的list start下标)
endIndex.value = startIndex.value + pageSize.value // 当前区域的list end下标
paddingTop.value = top
if (endIndex.value >= list.value.length - 1) { // 最后一条 直接return
paddingBottom.value = 0
return
}
paddingBottom.value = allHeight.value - height - top // 否则就拿所有数据的高度 - 当前可视区域的高度 - paddingtop值 = paddingbottom值
}
/**
* 获取总高度,padding值
*/
const getHeightPadding = (val) => {
list.value = val
const valLen = val.length
allHeight.value = valLen * itemHeight.value
paddingBottom.value = allHeight.value - scrollList.value.length * itemHeight.value
}
/**
* 监听数据的变化,padding值和高度相应变化
*/
watch(() => list.value, (val) => {
getHeightPadding(val)
})
onMounted(() => {
getData(params.value).then((res) => {
getHeightPadding(res)
})
})
return () => (
<div ref={myRef} id="container" style={defaultStyle} onscroll={(e) => {
scroll(e)
}}>
<div style={style.value}>
{scrollList.value.map((item) => {
return <div>{ctx.slots.content?ctx.slots.content(item) : item.name}</div>
})}
</div>
</div>
)
},
// render() {
// }
})
export default Index
网友评论