Administrator
发布于 2024-08-28 / 36 阅读
0
0

Vue3自定义无缝滚动组件(支持大量数据)

滚动组件:defaultSeamlessScroll.vue

<script setup>
import {ref, onMounted, toRef, defineProps, toRaw} from "vue"
import {unref} from "vue-demi";

const props = defineProps({
  list: {
    default: []
  },
  limitScrollNum:{
    default: 5
  }
})
const {list, limitScrollNum} = unref(props);
const data = toRaw(list);
const limit = toRaw(limitScrollNum);
const height = 42*limit + 'px';

let count = 0
let uu = []
let interval = null
const offset = ref(0)
const target = ref(null)
const little_Or_big = ref(null)
let testData = []


onMounted(() => {
  if (data.length > limit) {
    const size = target.value.clientHeight
    if (data.length > 0) {
      count = Math.ceil(size / 44)
      data.forEach((item, index) => {
        item._id = index
      })
      if (data.length / count > 2) {
        // 数据量大
        little_Or_big.value = true
        testData = data.slice(0, 2 * count + 1)
        if (!interval) {
          interval = setInterval(load1, 1000 / 50)
        }
      } else if (data.length / count <= 2) {
        // 数据量小
        little_Or_big.value = false
        testData = [...data]
        if (!interval) {
          interval = setInterval(load2, 1000 / 50)
        }
      }
    }
  }
})
const load1 = () => {
  offset.value = offset.value - 1
  if (offset.value === -count * 44) {
    offset.value = 0
    const temp = testData[count]._id
    const yy = []
    for (let i = temp; i < temp + 2 * count + 1; i++) {
      if (i < data.length) {
        yy.push({
          ...data[i]
        })
      } else {
        yy.push({
          ...data[i - data.length]
        })
      }
    }
    testData = yy
  }
}
const load2 = () => {
  offset.value = offset.value - 1
  if (offset.value === -data.length * 44) {
    offset.value = 0
    testData = [...data]
  } else {
    if (testData.length < 1.5 * data.length) {
      data.forEach((item, index) => {
        uu.push({
          ...item,
          // _id: item._id + chartData.value.length
        })
      })
      testData.push(...uu)
      uu = []
    }
  }
}

//鼠标悬停,停止滚动
function hoverHandler() {
    clearInterval(interval)
}
//鼠标离开,继续滚动
function leaveHandler() {
  if (little_Or_big.value) {
    interval = setInterval(load1, 1000 / 50)
  } else {
    interval = setInterval(load2, 1000 / 50)
  }
}
</script>

<template>
  <div class="scroll-container" ref="target" @mouseover="hoverHandler()" @mouseout="leaveHandler()">
    <div v-if="data.length > limit"
        class="scroll-list"
        :style="{transform: `translate3d(0,${offset}px,0)`}">
      <div
        v-for="(item, index) in testData"
        :key="index"
        class="item"
      >
        <slot name="itemSlot" :item="item"></slot>
      </div>
    </div>
    <div v-else class="scroll-list">
      <div
          v-for="(item, index) in data"
          :key="index"
          class="item"
      >
        <slot name="itemSlot" :item="item"></slot>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.scroll-container {
  margin: 0;
  padding: 0;
  height: v-bind(height);
  overflow: hidden;
}

</style>

使用

<template>
	<default-seamless-scroll v-if="isScrollShow" :list="list" :limitScrollNum="5" v-slot:itemSlot="{item}">
		<span>{{item.xxx}}</span>
	</default-seamless-scroll>
</template>
<script setup>
import {ref} from "vue";
import DefaultSeamlessScroll from '@view/defaultSeamlessScroll.vue'

const isScrollShow = ref(false);

const list = [];

//模拟请求
setTimeout(() => {
	for(let i=0; i < 100; i++) {
		var item={index: i, column1: "xxx",column2: "xxx"};
		list.push(item);
	}
	isScrollShow.value = true;
},3000)

</script>


评论