You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SvelteKit中onloadeddata行为异常问题排查

问题原因分析

你的代码核心问题出在事件绑定时机滞后和未覆盖缓存/快速加载场景:

  1. 开发模式下本地视频加载极快,onMount执行时loadeddata事件已经触发完毕,此时再绑定事件自然捕获不到。
  2. 生产模式下,视频可能从浏览器缓存加载(事件触发更快)或网络加载(触发较慢),导致事件有时能捕获有时不能。
  3. 直接赋值onloadeddata的方式无法处理事件已提前触发的情况,且未在组件销毁时解绑事件,存在内存泄漏风险。
修复方案

1. 提前检查视频加载状态,兼容已完成加载的场景

视频元素的readyState属性可判断当前加载进度:

  • readyState >= 2对应HAVE_CURRENT_DATA状态,即已触发loadeddata事件。
    绑定事件前先检查该状态,若已满足则直接执行回调,无需等待事件触发。

2. 使用addEventListener绑定事件并在组件销毁时解绑

相比直接赋值onloadeddata,addEventListener更灵活,且能避免覆盖其他可能的事件监听;同时在组件销毁时移除监听,防止内存泄漏。

3. 补充视频初始样式

给视频添加初始透明样式,保证加载完成后显示的过渡效果正常。

修改后的完整代码
<script>
  import { onMount, onDestroy } from 'svelte'

  export let
    hdSrcArr = [],
    nonHdSrcArr = []

  let
    refHd = null,
    refSmall = null,
    showLowQualityVideo = true

  // 低清视频加载完成回调
  function handleSmallLoaded() {
    if (!refSmall) return
    refSmall.style.opacity = 1
    refSmall.disablePictureInPicture = true
  }

  // 高清视频加载完成回调
  function handleHdLoaded() {
    if (!refHd || !refSmall) return
    refHd.currentTime = refSmall.currentTime
    refHd.style.opacity = 1
    refHd.disablePictureInPicture = true
    showLowQualityVideo = false
  }

  onMount(() => {
    // 处理低清视频
    if (refSmall) {
      // 检查是否已加载完成
      if (refSmall.readyState >= 2) {
        handleSmallLoaded()
      } else {
        refSmall.addEventListener('loadeddata', handleSmallLoaded)
      }
    }

    // 处理高清视频
    if (refHd) {
      if (refHd.readyState >= 2) {
        handleHdLoaded()
      } else {
        refHd.addEventListener('loadeddata', handleHdLoaded)
      }
    }
  })

  // 组件销毁时移除事件监听
  onDestroy(() => {
    if (refSmall) {
      refSmall.removeEventListener('loadeddata', handleSmallLoaded)
    }
    if (refHd) {
      refHd.removeEventListener('loadeddata', handleHdLoaded)
    }
  })
</script>

<style>
  video {
    opacity: 0;
    transition: opacity 0.3s ease;
    /* 让两个视频重叠显示,按需调整定位 */
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
</style>

{#if showLowQualityVideo}
  <video
      bind:this={refSmall}
      playsinline
      autoplay
      muted
      loop
      preload="auto"
  >
    {#each nonHdSrcArr as video}
      <source src={video.video} type={video.type} />
    {/each}
  </video>
{/if}

<video
    bind:this={refHd}
    playsinline
    autoplay
    muted
    loop
    preload="auto"
>
  {#each hdSrcArr as video}
    <source src={video.video} type={video.type} />
  {/each}
</video>
额外注意事项
  • 两个视频需通过定位重叠,否则会同时显示;样式中已添加基础定位,可根据布局调整。
  • 必须同时保留autoplay和muted属性,符合浏览器自动播放策略,否则视频可能无法自动加载播放。
  • 若视频资源较大,可监听progress事件优化加载中的过渡体验。

内容的提问来源于stack exchange,提问作者Evgeny Alekseev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:25:30