当前位置:首页 > VUE

vue实现视频下滑

2026-01-16 03:30:02VUE

Vue 实现视频下滑功能

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

vue实现视频下滑

监听滚动事件

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

vue实现视频下滑

<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)
  }
};

完整示例代码

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

<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实现tab换行

vue实现tab换行

Vue实现Tab切换的常见方法 使用Vue实现Tab切换功能可以通过多种方式完成,以下是几种常见的方法: 动态组件结合v-if或v-show 通过v-if或v-show控制不同Tab内容的显示…

vue实现页面截屏

vue实现页面截屏

使用html2canvas库实现截屏 html2canvas是一个流行的JavaScript库,可以将DOM元素转换为Canvas图像。在Vue项目中安装html2canvas: npm inst…

vue怎么实现文件树

vue怎么实现文件树

Vue 实现文件树的方法 使用递归组件 递归组件是处理嵌套数据结构的理想方式。文件树通常包含文件夹和文件的嵌套结构,适合用递归组件实现。 <template> <ul>…

vue实现继承语法糖

vue实现继承语法糖

在Vue中实现继承可以通过多种方式模拟类继承的效果,以下是常见的几种方法: 使用mixins实现逻辑复用 通过Vue的mixins机制共享组件选项,达到类似继承的效果: const BaseC…

vue实现多选题

vue实现多选题

Vue实现多选题的方法 使用Vue实现多选题功能,可以通过v-model绑定数组、动态渲染选项、以及处理选中状态来实现。以下是一个完整的实现示例: 基础实现代码 <template>…

vue实现点击旋转轮盘

vue实现点击旋转轮盘

实现点击旋转轮盘效果 在Vue中实现点击旋转轮盘效果,可以通过CSS动画和Vue的数据绑定结合完成。以下是一个完整的实现方案: 准备工作 需要安装Vue.js环境,可以通过CDN引入或使用Vue…