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

Chromium浏览器中,空格/回车触发后File Input onChange未触发问题

问题

开发了一个React组件,用于展示图片并允许用户选择本地图片替换展示。该组件在Firefox、Epiphany等浏览器中运行正常,但在Chromium系浏览器(Chrome、Chromium、Brave)中存在异常:

  • 用鼠标点击img标签选择图片,所有浏览器均能正常切换;
  • 用空格或回车(无障碍操作)触发img标签的选择后,img标签未更新,File Input的onChange事件也没触发,且控制台无报错。

组件代码如下:

function Avatar() {
  const inputRef = useRef(null)
  const [imageSrc, setImageSrc] = useState('https://fastly.picsum.photos/id/605/200/200.jpg?hmac=aAxC3x4fmu7RXhLH-1idijrAUvlZVEwlUqjzKR80YWo')

  const handleImageChange = (event) => {
    console.log('HANDLE IMAGE CHANGE')
    const file = event.target.files[0]
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => {
      setImageSrc(reader.result)
    }
  }

  const handleImageClick = () => {
    inputRef.current.click()
  }

  return (
    <div>
      <img
        tabIndex="0"
        src={imageSrc}
        alt="avatar"
        onClick={handleImageClick}
        onKeyDown={(e) => {
          if (e.code === 'Tab') return

          e.preventDefault()

          if (['Enter', 'Space'].includes(e.code)) handleImageClick()
        }}
      />
      <input type="file" ref={inputRef} style={{ display: 'none' }} onChange={handleImageChange} />
    </div>
  )
}

原因及解决方案

问题根源

Chromium系浏览器中,通过onKeyDown触发文件选择框的click()时,会存在焦点上下文冲突:按下回车/空格时,img元素的焦点尚未释放,导致文件选择框的操作被浏览器默认行为干扰,最终onChange事件无法正常触发。

同时,全局的e.preventDefault()在处理Space键时,虽阻止了页面滚动,但也干扰了浏览器对“激活元素”的上下文判定,进一步加剧了问题。

修复方案

  1. 改用onKeyUp事件处理回车/空格触发,避免焦点未释放时的冲突;
  2. 仅针对Space键阻止默认滚动行为,保留其他按键的正常上下文;
  3. 确保文件选择框的触发逻辑在焦点稳定后执行。

修正后的代码:

function Avatar() {
  const inputRef = useRef(null)
  const [imageSrc, setImageSrc] = useState('https://fastly.picsum.photos/id/605/200/200.jpg?hmac=aAxC3x4fmu7RXhLH-1idijrAUvlZVEwlUqjzKR80YWo')

  const handleImageChange = (event) => {
    console.log('HANDLE IMAGE CHANGE')
    const file = event.target.files[0]
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => {
      setImageSrc(reader.result)
    }
  }

  const handleImageClick = () => {
    inputRef.current.click()
  }

  return (
    <div>
      <img
        tabIndex="0"
        src={imageSrc}
        alt="avatar"
        onClick={handleImageClick}
        onKeyUp={(e) => {
          if (e.code === 'Tab') return;
          
          // 仅阻止Space键的默认滚动行为
          if (e.code === 'Space') {
            e.preventDefault();
          }
          
          if (['Enter', 'Space'].includes(e.code)) {
            handleImageClick();
          }
        }}
      />
      <input type="file" ref={inputRef} style={{ display: 'none' }} onChange={handleImageChange} />
    </div>
  )
}

无障碍体验优化

为让屏幕阅读器更清晰识别元素交互属性,建议给img标签添加role="button":

<img
  role="button"
  tabIndex="0"
  src={imageSrc}
  alt="avatar"
  onClick={handleImageClick}
  onKeyUp={(e) => {
    // 原有逻辑
  }}
/>

内容的提问来源于Stack Exchange,提问作者Jozef Hudec

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 02:57:42