– image –

First we should understand what is virtual scrolling 1. The concept of virtual scrolling is to render only the elements of the current parent box height and do not render other elements (to prevent the rendering of big data stuck) I implemented the method by intercepting from the source data method 2. Implementation Principle itemHeight Sets the scrollTop distance of all data. ItemHeihgt * data 4. ScrollTop/itemHeight 5 End index (last) first + el.clientheight/itemHeight 6 Slice (first,last) The following is the code I implemented


<template>
  <div class="scroll_wrap" ref="wrapEl" @scroll="handleScroll">
    <div class="scroll_view" :style="getViewStyle">
      <div
        style="height: 40px; background: red"
        v-for="(item, i) in newData"
        :key="i"
      >
        <slot name="default" :item="item"></slot>
      </div>
    </div>
  </div>
</template>

<script>
import {
  computed,
  defineComponent,
  onMounted,
  reactive,
  ref,
  unref,
} from "vue";
export default defineComponent({
  name: "VitrualScroll".props: {
    data: Array,},setup(props) {
    const state = reactive({
      first: 0.last: 0.scrollTop: 0});const wrapEl = ref(null);
    const newData = ref([]);

    const itemHeight = 40;
    const sumHeight = Math.ceil(props.data.length * itemHeight);

    const getViewStyle = computed(() = > {
      return {
        height: sumHeight + "px"."padding-top":
          Math.floor(state.scrollTop / itemHeight) * itemHeight + "px"}; });function handleScroll() {
      onScroll();
    }

    const getFirst = () = > {
      return Math.floor(state.scrollTop / itemHeight);
    };
    const getLast = () = > {
      return (
        state.first + Math.ceil(unref(wrapEl).clientHeight / itemHeight) + 1
      );
    };

    function onScroll() {
      state.scrollTop = unref(wrapEl).scrollTop;
      state.first = getFirst();
      state.last = getLast();
      newData.value = props.data.slice(state.first, state.last);
    }

    onMounted(() = > {
      onScroll();
    });

    return{ handleScroll, wrapEl, newData, getViewStyle, }; }});</script>
<style scoped>
.scroll_wrap {
  height: 300px;
  overflow-y: auto;
  width: 300px;
  margin: auto;
}

.scroll_view {
  box-sizing: border-box;
}
</style>


Copy the code