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. 响应式

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

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

相关推荐
lee5764 小时前
老是忘记package.json,备忘一下 webpack 环境下 Vue Cli 和 Vite 命令行工具对比
vue.js
喝拿铁写前端5 小时前
前端与 AI 结合的 10 个可能路径图谱
前端·人工智能
codingandsleeping5 小时前
浏览器的缓存机制
前端·后端
灵感__idea7 小时前
JavaScript高级程序设计(第5版):扎实的基本功是唯一捷径
前端·javascript·程序员
摇滚侠7 小时前
Vue3 其它API toRow和markRow
前端·javascript
難釋懷7 小时前
JavaScript基础-history 对象
开发语言·前端·javascript
beibeibeiooo7 小时前
【CSS3】04-标准流 + 浮动 + flex布局
前端·html·css3
拉不动的猪7 小时前
刷刷题47(react常规面试题2)
前端·javascript·面试
浪遏7 小时前
场景题:大文件上传 ?| 过总字节一面😱
前端·javascript·面试
Bigger7 小时前
Tauri(十八)——如何开发 Tauri 插件
前端·rust·app