当前位置:首页 > VUE

vue实现视频下滑

2026-01-16 03:30:02VUE

Vue 实现视频下滑功能

实现视频下滑功能通常涉及监听滚动事件、动态加载视频内容以及优化性能。以下是具体实现方法:

监听滚动事件

在 Vue 中可以通过 @scroll 事件监听滚动行为,结合 scrollTopclientHeight 判断是否到达底部。

<template>
  <div class="video-container" @scroll="handleScroll">
    <div v-for="(video, index) in videos" :key="index">
      <video :src="video.src" controls></video>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      videos: [],
      currentPage: 1,
      isLoading: false
    };
  },
  methods: {
    handleScroll(event) {
      const container = event.target;
      const scrollBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
      if (scrollBottom < 100 && !this.isLoading) {
        this.loadMoreVideos();
      }
    },
    loadMoreVideos() {
      this.isLoading = true;
      // 模拟异步加载
      setTimeout(() => {
        const newVideos = [...Array(5)].map((_, i) => ({
          src: `https://example.com/video${this.currentPage + i}.mp4`
        }));
        this.videos = [...this.videos, ...newVideos];
        this.currentPage += 5;
        this.isLoading = false;
      }, 1000);
    }
  },
  mounted() {
    this.loadMoreVideos();
  }
};
</script>

<style>
.video-container {
  height: 100vh;
  overflow-y: auto;
}
video {
  width: 100%;
  margin-bottom: 20px;
}
</style>

使用 Intersection Observer API

Intersection Observer 更高效,适合监听元素是否进入视口。

<template>
  <div class="video-container">
    <div v-for="(video, index) in videos" :key="index" ref="videoItems">
      <video :src="video.src" controls></video>
    </div>
    <div ref="loader" v-if="isLoading">Loading...</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      videos: [],
      currentPage: 1,
      isLoading: false,
      observer: null
    };
  },
  methods: {
    initObserver() {
      this.observer = new IntersectionObserver((entries) => {
        if (entries[0].isIntersecting && !this.isLoading) {
          this.loadMoreVideos();
        }
      }, { threshold: 0.1 });
      this.observer.observe(this.$refs.loader);
    },
    loadMoreVideos() {
      this.isLoading = true;
      setTimeout(() => {
        const newVideos = [...Array(5)].map((_, i) => ({
          src: `https://example.com/video${this.currentPage + i}.mp4`
        }));
        this.videos = [...this.videos, ...newVideos];
        this.currentPage += 5;
        this.isLoading = false;
      }, 1000);
    }
  },
  mounted() {
    this.loadMoreVideos();
    this.$nextTick(() => {
      this.initObserver();
    });
  },
  beforeDestroy() {
    if (this.observer) {
      this.observer.disconnect();
    }
  }
};
</script>

优化性能

  • 懒加载视频:使用 loading="lazy" 属性或动态设置 src
  • 虚拟滚动:对于大量视频,使用 vue-virtual-scroller 等库减少 DOM 数量。
  • 节流滚动事件:避免频繁触发加载逻辑。
import { throttle } from 'lodash';

export default {
  methods: {
    handleScroll: throttle(function(event) {
      const container = event.target;
      const scrollBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
      if (scrollBottom < 100 && !this.isLoading) {
        this.loadMoreVideos();
      }
    }, 200)
  }
};

完整示例代码

结合上述方法,以下是一个完整的实现:

vue实现视频下滑

<template>
  <div class="video-container" @scroll="handleScroll">
    <div v-for="(video, index) in videos" :key="index">
      <video :src="video.src" controls :poster="video.poster"></video>
    </div>
    <div v-if="isLoading" class="loading">Loading more videos...</div>
  </div>
</template>

<script>
import { throttle } from 'lodash';

export default {
  data() {
    return {
      videos: [],
      currentPage: 1,
      isLoading: false,
      hasMore: true
    };
  },
  methods: {
    handleScroll: throttle(function(event) {
      const container = event.target;
      const scrollBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
      if (scrollBottom < 100 && !this.isLoading && this.hasMore) {
        this.loadMoreVideos();
      }
    }, 200),
    async loadMoreVideos() {
      this.isLoading = true;
      try {
        const newVideos = await this.fetchVideos(this.currentPage);
        if (newVideos.length === 0) {
          this.hasMore = false;
        } else {
          this.videos = [...this.videos, ...newVideos];
          this.currentPage += 1;
        }
      } catch (error) {
        console.error('Failed to load videos:', error);
      } finally {
        this.isLoading = false;
      }
    },
    fetchVideos(page) {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(
            [...Array(5)].map((_, i) => ({
              src: `https://example.com/video${page + i}.mp4`,
              poster: `https://example.com/thumbnail${page + i}.jpg`
            }))
          );
        }, 1000);
      });
    }
  },
  mounted() {
    this.loadMoreVideos();
  }
};
</script>

<style>
.video-container {
  height: 100vh;
  overflow-y: auto;
}
video {
  width: 100%;
  margin-bottom: 20px;
}
.loading {
  text-align: center;
  padding: 10px;
}
</style>

标签: 视频vue
分享给朋友:

相关文章

vue tag实现

vue tag实现

Vue 标签实现方法 在 Vue 中实现标签功能可以通过多种方式完成,常见场景包括动态标签生成、标签输入框、标签管理等。以下是几种典型实现方案: 动态标签列表渲染 使用 v-for 指令渲染标签数组…

vue实现 单选

vue实现 单选

实现 Vue 单选功能 在 Vue 中实现单选功能可以通过多种方式完成,以下是几种常见的方法: 使用 v-model 绑定单选按钮 通过 v-model 可以轻松实现单选功能,将单选按钮的值绑定到同…

vue实现注册

vue实现注册

Vue 实现注册功能 注册功能通常涉及前端表单、数据验证、与后端 API 的交互等步骤。以下是一个完整的 Vue 实现注册功能的方案。 创建注册表单 使用 Vue 的模板语法创建注册表单,包含用户名…

vue实现api

vue实现api

Vue 实现 API 调用 在 Vue 中调用 API 通常涉及使用 axios 或 fetch 发送 HTTP 请求,并结合 Vue 的响应式特性管理数据。以下是常见的实现方式: 安装 axios…

vue toast实现

vue toast实现

Vue Toast 实现方法 使用第三方库(推荐) 安装 vue-toastification 库,这是一个功能丰富且轻量级的 Vue Toast 插件。 npm install vue-toast…

vue实现书库

vue实现书库

Vue 实现书库功能 使用 Vue 构建书库功能需要结合前端框架和后端数据管理。以下是实现步骤和关键点: 项目初始化 使用 Vue CLI 或 Vite 初始化项目,安装 Vue Router 和状…