0.0.7 • Published 7 months ago
as_virtual_list
简介
虚拟列表,适用于长列表渲染,减少dom节点渲染,提升性能
安装
npm install as_virtual_list
使用
// 单文件引入
import { VirtualListVue, VirtualListJsx } from 'as_virtual_list'
import 'as_virtual_list/dist/style.css'
// 全局引入自动注册
import storyVirtualList from 'as_virtual_list'
import 'as_virtual_list/dist/style.css'
app.use(storyVirtualList)
// 或手动注册
import { VirtualListVue, VirtualListJsx } from 'as_virtual_list'
import 'as_virtual_list/dist/style.css'
app.component('VirtualListVue', VirtualListVue)
app.component('VirtualListJsx', VirtualListJsx)
// 使用
const listData = ref(Array.from({ length: 100000 }).map((_, i) => ({ id: i, value: i })))
// vue
<VirtualListVue style="height: 50vh" :data="listData" :itemSize="100"> </VirtualListVue>
// jsx
<>
<VirtualListJsx style='height: 50vh' data={listData.value} itemSize={100}>
{{
default: ({ item }) => <div>item:{JSON.stringify(item, null, 2)}</div>,
}}
</VirtualListJsx>
</>
API
属性名 | 说明 | 类型 | 默认值 |
---|
data | 数据 | Array | |
itemSize | 每项数据占据 | Number | 100 |
dynamicHeight | 是否开启动态高度 | Boolean | false |
Events
事件名 | 说明 | 参数 |
---|
scroll | 滚动事件 | Function(top:Number, left:Number ,e:event) |
Slots
插槽名 | 说明 | 参数 |
---|
default | 默认插槽 | Function(item) |
Exposes
事件名 | 说明 | 参数 |
---|
setScrollTop | 手动设置滚动条到顶部的距离 | Function(value:Number) |
setScrollLeft | 手动设置滚动条到左边的距离 | Function(value:Number) |
示例
<script setup lang="jsx">
import { ref, onMounted } from 'vue'
import { VirtualListVue, VirtualListJsx } from 'as_virtual_list'
import 'as_virtual_list/dist/style.css'
const listData = ref(Array.from({ length: 100000 }).map((_, i) => ({ id: i, value: i })))
const listProps = Object.keys(listData.value[0]).map((key) => ({ key, label: key }))
const VirtualListJsxRef = ref(null)
const tableHeaderRef = ref(null)
const tableFooterRef = ref(null)
const scrollVirtualList = (top, left, e) => {
tableHeaderRef.value.scrollLeft = left
tableFooterRef.value.scrollLeft = left
}
// 计算总和
const sum = (arr, key) => {
return arr.reduce((prev, curr) => {
return prev + curr[key]
}, 0)
}
const handleTop = (e) => {
VirtualListJsxRef.value.setScrollTop(e.target.value)
}
const handleLeft = (e) => {
VirtualListJsxRef.value.setScrollLeft(e.target.value)
}
</script>
<template>
<div class="home">home</div>
top <input type="range" :min="0" :max="listData.length * 100" :value="0" :step="1" @input="handleTop" />
<br />
left<input type="range" :min="0" :max="400" :value="0" :step="1" @input="handleLeft" />
<!-- tableFooter存在时 border-bottom-0 -->
<div class="border-ccc border-bottom-0">
<div ref="tableHeaderRef" class="table-header pr-6">
<div class="table-item" v-for="(item, index) in listProps" :key="item.key">{{ item.label }}</div>
</div>
<VirtualListVue style="height: 50vh" :data="listData" :itemSize="60" @scroll="scrollVirtualList" ref="VirtualListJsxRef">
<template #default="{ item }">
<div class="table-row">
<div class="table-item" v-for="i in listProps" :key="i.key">{{ i.key }} {{ item[i.key] }}</div>
</div>
</template>
</VirtualListVue>
<div ref="tableFooterRef" class="table-footer border-top-ccc">
<div class="table-item" v-for="item in listProps" :key="item.key">{{ item.key }} 总计: {{ sum(listData, item.key) }}</div>
</div>
</div>
</template>
<style lang="css" scoped>
.home {
}
.table-row {
/* 与itemSize保持一致 */
height: 60px;
display: flex;
line-height: 2.5;
}
.table-item {
flex-shrink: 0;
width: 800px;
padding: 10px;
box-sizing: border-box;
border: 1px solid #ccc;
margin-top: -1px;
margin-left: -1px;
}
.table-item:last-child {
border-right: none;
}
.table-header,
.table-footer {
height: 60px;
line-height: 2.5;
overflow: hidden;
display: flex;
/* 与滚动条保持一致 */
padding-right: 6px;
}
.border-ccc {
border: 1px solid #ccc;
}
.border-top-ccc {
border-top: 1px solid #ccc;
}
.border-bottom-0 {
border-bottom: none;
}
</style>