Vue3滚动轮播组件实现超标信息自动滚动

创建滚动轮播组件实现超标信息自动滚动

为了实现超出父容器高度时的自动轮播滚动效果,我们可以创建一个通用的滚动组件,通过插槽来包裹内容。

1. 组件代码如下

vue:/Users/dylan/Documents/GitHub/Supervision-of-cooking-fume/src/components/ScrollList.vue 复制代码
<template>
  <div 
    ref="container" 
    class="scroll-container" 
    :style="{ height: height }"
    @mouseenter="pauseScroll" 
    @mouseleave="resumeScroll"
  >
    <div 
      ref="wrapper"
      class="scroll-wrapper"
      :class="{ 'scrolling': isScrolling }"
      :style="{ animationDuration: `${duration}s`, animationPlayState: isPaused ? 'paused' : 'running' }"
    >
      <slot></slot>
      <!-- 当内容超出时,复制一份内容用于无缝滚动 -->
      <div v-if="needScroll" class="scroll-duplicate">
        <slot></slot>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue';

const props = defineProps({
  // 容器高度
  height: {
    type: String,
    default: '100%'
  },
  // 滚动速度,单位秒
  duration: {
    type: Number,
    default: 20
  },
  // 是否自动开始滚动
  autoScroll: {
    type: Boolean,
    default: true
  },
  // 滚动延迟,单位毫秒
  delay: {
    type: Number,
    default: 500
  }
});

const container = ref(null);
const wrapper = ref(null);
const isScrolling = ref(false);
const isPaused = ref(!props.autoScroll);
const needScroll = ref(false);

// 检查是否需要滚动
const checkNeedScroll = async () => {
  await nextTick();
  if (!container.value || !wrapper.value) return;
  
  const containerHeight = container.value.clientHeight;
  const contentHeight = wrapper.value.scrollHeight / (needScroll.value ? 2 : 1);
  
  needScroll.value = contentHeight > containerHeight;
  
  if (needScroll.value && props.autoScroll) {
    startScroll();
  } else {
    stopScroll();
  }
};

// 开始滚动
const startScroll = () => {
  isScrolling.value = true;
  isPaused.value = false;
};

// 停止滚动
const stopScroll = () => {
  isScrolling.value = false;
};

// 暂停滚动
const pauseScroll = () => {
  isPaused.value = true;
};

// 恢复滚动
const resumeScroll = () => {
  if (needScroll.value) {
    isPaused.value = false;
  }
};

// 监听内容变化
const observer = ref(null);

onMounted(() => {
  // 初始检查
  setTimeout(checkNeedScroll, props.delay);
  
  // 监听内容变化
  if (window.MutationObserver) {
    observer.value = new MutationObserver(checkNeedScroll);
    if (wrapper.value) {
      observer.value.observe(wrapper.value, {
        childList: true,
        subtree: true,
        characterData: true
      });
    }
  }
  
  // 监听窗口大小变化
  window.addEventListener('resize', checkNeedScroll);
});

onUnmounted(() => {
  if (observer.value) {
    observer.value.disconnect();
  }
  window.removeEventListener('resize', checkNeedScroll);
});

// 监听props变化
watch(() => props.autoScroll, (newVal) => {
  isPaused.value = !newVal;
});

// 暴露方法给父组件
defineExpose({
  checkNeedScroll,
  startScroll,
  stopScroll,
  pauseScroll,
  resumeScroll
});
</script>

<style scoped>
.scroll-container {
  overflow: hidden;
  position: relative;
  width: 100%;
}

.scroll-wrapper {
  position: relative;
  width: 100%;
}

.scrolling {
  animation: scrollAnimation linear infinite;
}

@keyframes scrollAnimation {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-50%);
  }
}

.scroll-duplicate {
  /* 确保复制的内容样式与原内容一致 */
}
</style>

2. 使用示例

vue:/Users/dylan/Documents/GitHub/Supervision-of-cooking-fume/src/views/IndexView.vue 复制代码
<script setup>
import { ref, onMounted, onUnmounted, inject } from "vue";
// 导入依赖...
import ScrollList from "@/components/ScrollList.vue"; // 导入滚动组件

// 其他代码...
</script>

<template>
    <div>
        <ScrollList
            class="flex-1 w-full hide-scrollbar"
            :duration="30"
          >
            <div
              v-for="(item, index) in 100"
              :key="index"
            >
              {{item}}
            </div>
          </ScrollList>
    </div>
</template>

组件功能说明

  1. 自动检测:组件会自动检测内容是否超出容器高度,只有超出时才会启动滚动

  2. 无缝滚动:通过复制一份内容实现无缝循环滚动效果

  3. 交互控制:鼠标悬停时暂停滚动,移出时恢复滚动

  4. 可配置性

    • height:设置容器高度
    • duration:控制滚动速度
    • autoScroll:是否自动开始滚动
    • delay:初始检测延迟时间
  5. 响应式

    • 监听内容变化自动更新滚动状态
    • 监听窗口大小变化重新计算是否需要滚动

这个组件设计为通用组件,可以在项目中的其他需要滚动展示的地方复用,提高代码的可维护性和一致性。

相关推荐
艾小逗40 分钟前
vue3中的effectScope有什么作用,如何使用?如何自动清理
前端·javascript·vue.js
小小小小宇3 小时前
手写 zustand
前端
Hamm4 小时前
用装饰器和ElementPlus,我们在NPM发布了这个好用的表格组件包
前端·vue.js·typescript
小小小小宇5 小时前
前端国际化看这一篇就够了
前端
大G哥5 小时前
PHP标签+注释+html混写+变量
android·开发语言·前端·html·php
whoarethenext5 小时前
html初识
前端·html
小小小小宇5 小时前
一个功能相对完善的前端 Emoji
前端
m0_627827525 小时前
vue中 vue.config.js反向代理
前端
Java&Develop5 小时前
onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2
前端·spring boot·编辑器
白泽talk5 小时前
2个小时1w字| React & Golang 全栈微服务实战
前端·后端·微服务