如何在React中实现音频组件的懒加载?
实现点击播放时才加载音频的改动方案
原代码的问题在于,useAudio hook初始化时就通过new Audio(url)创建了音频实例,组件挂载时就会开始加载音频,没法做到按需加载。要实现点击播放按钮才加载音频,咱们可以通过以下改动实现:
核心改动点
- 将音频实例的状态设为可空,初始值为
null,仅在首次点击播放时创建实例 - 修改
toggle函数逻辑,首次点击时完成音频实例创建、加载并播放,后续点击仅切换播放/暂停状态 - 调整
useEffect的依赖与触发条件,确保仅当音频实例存在时才处理播放状态和事件监听 - 增加音频实例的清理逻辑,避免内存泄漏
修改后的完整代码
import { IconButton } from "@chakra-ui/button"; import { useEffect, useState } from "react"; import { HiSpeakerWave } from "react-icons/hi2"; const useAudio = (url: string) => { // 音频实例初始为null,不提前创建 const [audio, setAudio] = useState<HTMLAudioElement | null>(null); const [playing, setPlaying] = useState(false); const toggle = () => { if (!audio) { // 首次点击:创建音频实例并加载 const newAudio = new Audio(url); setAudio(newAudio); // 实例创建后立即播放 newAudio.play(); setPlaying(true); } else { // 非首次点击:切换播放/暂停 if (playing) { audio.pause(); setPlaying(false); } else { audio.play(); setPlaying(true); } } }; useEffect(() => { if (!audio) return; // 监听音频结束事件,自动重置播放状态 const handleEnded = () => setPlaying(false); audio.addEventListener("ended", handleEnded); // 清理函数:移除监听并释放音频资源 return () => { audio.removeEventListener("ended", handleEnded); audio.pause(); audio.src = ""; // 清空src释放资源 }; }, [audio]); return [playing, toggle]; }; interface Prop { url: string; } const Player = ({ url }: Prop) => { const [playing, toggle] = useAudio(url); return ( <IconButton size={"sm"} colorScheme="teal" aria-label="Play Audio" borderRadius={"full"} icon={<HiSpeakerWave />} onClick={toggle} /> ); }; export default Player;
额外说明
- 首次点击按钮时才会触发
new Audio(url),此时浏览器才会开始请求并加载音频资源 - 音频播放结束后会自动重置播放状态,同时清理函数会在组件卸载时释放音频资源,避免内存占用
- 重复点击同一按钮时,不会重复创建音频实例,复用已加载的实例进行播放控制
内容的提问来源于stack exchange,提问作者Muhammad Mubashirullah Durrani
相关产品推荐
相关产品推荐

