虚拟列表组件
<script>export default { name: "VirtualList", props: {
templateRender: Function,
list: {
type: Array,
default: () => [],
},
remainList: {
type: Array,
default: () => [],
},
itemHeight: {
type: Number,
default: 34,
},
wrapHeight: {
type: Number,
default: 262,
},
group: {
type: Number,
default: 1,
},
}, data() {
return {
pointer: 0,
translateY: 0,
};
}, watch: {
remainList: {
handler(v) {
this.translateY = v.length * this.itemHeight;
let scrollTop = this.$refs["virtual-list-wrapper"]?.scrollTop;
if (scrollTop !== undefined) {
this.handleScroll({
srcElement: {
scrollTop,
},
});
}
},
immediate: true,
},
}, computed: {
scrollHeight() {
return (
// (this.groupRemainList.length + this.groupList.length) * this.itemHeight
this.groupList.length * this.itemHeight
);
},
displayCount() {
return Math.ceil(this.wrapHeight / this.itemHeight);
},
groupRemainList() {
return this.convertByGroup(this.remainList);
},
groupList() {
return this.convertByGroup(this.list);
},
displayList() {
return this.groupList.slice(
this.pointer,
this.pointer + this.displayCount + 1
);
},
remainHeight() {
return 0; //this.remainList.length * this.itemHeight;
},
}, methods: {
convertByGroup(list) {
let result = [];
let temp = [];
list.forEach((data) => {
temp.push(data);
if (temp.length >= this.group) {
result.push(temp);
temp = [];
}
});
if (temp.length > 0) {
result.push(temp);
}
return result;
},
renderListItem(h, datas, index, startTranslateY, tag) {
return h(
"div",
{
class: "virtual-list-item",
style: {
height: this.itemHeight + "px",
transform: `translate3d(0, ${
startTranslateY + index * this.itemHeight
}px, 0)`,
display: tag === "remian" ? "none" : "block",
},
key: tag + index,
},
datas.map((data) => {
return this.templateRender(h, data, tag);
})
);
},
handleScroll(e) {
let scrollTop = e.srcElement.scrollTop;
// let remainHeight = this.remainList.length * this.itemHeight;
if (scrollTop <= this.remainHeight) {
this.pointer = 0;
this.translateY = this.remainHeight;
} else {
// this.translateY = scrollTop;
this.pointer = Math.floor(
(scrollTop - this.remainHeight) / this.itemHeight
);
this.translateY = this.pointer * this.itemHeight + this.remainHeight;
}
},
}, render(h) {
let children = [
// 要保留的数据
...this.groupRemainList.map((datas, index) => {
return this.renderListItem(h, datas, index, 0, "remian");
}),
// 全部数据
...this.displayList.map((datas, index) => {
return this.renderListItem(h, datas, index, this.translateY, "list");
}),
];
return h(
"div",
{
class: "virtual-list-wrapper",
style: {
height: this.wrapHeight + "px",
},
on: {
scroll: this.handleScroll,
},
ref: "virtual-list-wrapper",
},
[
h(
"div",
{
style: {
height: this.scrollHeight + "px",
position: "relative",
},
},
children
),
]
);
},};</script><style>.virtual-list-wrapper { overflow: auto;}.virtual-list-item { position: absolute; top: 0; left: 0; width: 100%;}</style>
转载自:https://segmentfault.com/a/1190000041788791