如何在React中仅通过图片URL获取图片的宽度和高度?
问题原因
你遇到的是异步执行顺序的问题:图片加载属于异步IO操作,给Image实例设置src后,浏览器会在后台发起资源请求、加载、解码,这个过程不会阻塞后续同步代码的执行。所以你的第2、3条log运行时图片还没加载完成,自然拿不到有效宽高,只有load回调触发时图片才加载完成,才能输出正确值。这个和你把src放在onload前后的顺序没有关系,核心是不能用同步逻辑拿异步操作的结果。
解决方案
React场景下推荐用Promise封装异步逻辑,结合async/await或者state存储结果来使用:
1. 封装通用获取图片宽高的工具函数
基于onload实现:
const getImageSize = (imgUrl) => { return new Promise((resolve, reject) => { const img = new Image(); // 跨域场景需要加下面这行,放在src设置之前 // img.crossOrigin = 'anonymous' img.onload = () => { resolve({ width: img.width, height: img.height }) } img.onerror = (err) => reject('图片加载失败', err) img.src = imgUrl }) }
基于decode方法实现(更稳定,避免解码阻塞主线程):
const getImageSize = async (imgUrl) => { const img = new Image() // img.crossOrigin = 'anonymous' img.src = imgUrl await img.decode() return { width: img.width, height: img.height } }
2. 在React组件中使用
结合useEffect和state存储结果,所有需要用到图片宽高的逻辑都要等异步操作完成后执行:
import { useState, useEffect } from 'react' const DemoComponent = () => { // 存储图片宽高 const [imgSize, setImgSize] = useState(null) const thumbUrl = '你的图片URL' useEffect(() => { const loadImgSize = async () => { try { const size = await getImageSize(thumbUrl) // 这里拿到宽高后可以随意使用,存state/做计算都可以 setImgSize(size) console.log('图片宽高', size.width, size.height) } catch (err) { console.error(err) } } loadImgSize() }, [thumbUrl]) return ( <div> {/* 渲染时判断是否拿到宽高再处理 */} {imgSize ? ( <p>图片宽:{imgSize.width}px,高:{imgSize.height}px</p> ) : ( <p>加载中...</p> )} </div> ) }
注意事项
- 不要尝试用同步方式获取异步加载的结果,所有依赖宽高的逻辑必须放在异步回调/await后面/state更新后的渲染逻辑中
- 跨域场景需要给Image实例设置
crossOrigin: 'anonymous',且图片服务端需要配置跨域允许 - 高频调用场景可以增加URL缓存,避免同一个地址重复加载图片浪费资源
内容的提问来源于stack exchange,提问作者lufesome
相关产品推荐
相关产品推荐

