使用useRef实现视频悬停播放时仅最后一个缩略图生效的问题
问题概述
- 实现视频缩略图悬停播放功能:鼠标悬停缩略图时播放对应视频,移出时暂停
- 异常表现:仅最后一个缩略图的视频能正常响应悬停,其余无反应;先悬停无效缩略图再返回最后一个时,最后一个视频会持续播放进度
核心原因
使用单个useRef绑定循环渲染的所有<video>元素时,React会将最后一个渲染的视频DOM节点赋值给playerRef.current——因为每个循环项复用同一个ref,后续节点会覆盖之前的引用。因此所有悬停事件实际操作的都是最后一个视频,导致前序缩略图无响应。
修复方案
将每个视频项拆分为独立子组件,让每个组件拥有自己的useRef来管理对应的视频元素,确保每个悬停事件只操作当前视频。
父组件(Projects.jsx)
import React from 'react' import { projectlist } from '../../projectlist' import ProjectItem from './ProjectItem' import './Projects.css' export default function Projects() { return ( <div className='projects-container'> {projectlist.map((video) => ( <ProjectItem key={video.video_id} video={video} /> ))} </div> ) }
子组件(ProjectItem.jsx)
import React, { useRef } from 'react' export default function ProjectItem({ video }) { const playerRef = useRef(null) const handleMouseOver = () => { // 可选链避免null报错 playerRef.current?.play() } const handleMouseOut = () => { playerRef.current?.pause() // 可选:移出时重置视频到开头 // playerRef.current?.currentTime = 0 } return ( <div className='project-image' onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}> <video ref={playerRef} muted loop> <source src={video.test} type='video/mp4' /> </video> <img src={video.image} alt={`项目 ${video.video_id} 缩略图`} /> </div> ) }
原CSS可保留(无需修改)
.project-image{ position: relative; img{ position: relative; width: 100%; height: 100%; z-index: 1; } video{ position: absolute; opacity: 0; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; } &:hover{ video{ z-index: 2; opacity: 1; } } }
补充说明
- 子组件的独立ref确保每个视频元素拥有专属引用,悬停事件只会操作当前项的视频
- 使用可选链
?.避免组件挂载前或视频元素未加载时的null报错 - 可根据需求添加
currentTime = 0实现移出时重置视频到开头
内容的提问来源于stack exchange,提问作者LatePayment
相关产品推荐
相关产品推荐

