<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>