在同构呈现的页面图像中,可以在主script.js
文件之前下载。因此,可以在react
注册onLoad
事件之前加载图像 - 从不触发此事件。
script.js
constructor(props) {
super(props);
this.handleImageLoaded = this.handleImageLoaded.bind(this);
}
handleImageLoaded() {
console.log('image loaded');
}
render() {
return (
<img src='image.jpg' onLoad={this.handleImageLoaded} />
);
}
image.jpg
大于script.js
在这种情况下一切正常。事件在最终加载图像之前注册,因此在控制台中是image loaded
消息。
image.jpg
小于script.js
此方案您可以看到帖子开头描述的问题。 onLoad
事件未被触发。
如何在方案2 中触发onLoad
事件,我该怎么办?
要检测渲染时图像是否准备好,您应该检查纯javascript complete
对象上的img
属性:
constructor(props) {
super(props);
this.state = { loaded: false };
this.handleImageLoaded = this.handleImageLoaded.bind(this);
this.image = React.createRef();
}
componentDidMount() {
const img = this.image.current;
if (img && img.complete) {
this.handleImageLoaded();
}
}
handleImageLoaded() {
if (!this.state.loaded) {
console.log('image loaded');
this.setState({ loaded: true });
}
}
render() {
return (
<img src='image.jpg' ref={this.image} onLoad={this.handleImageLoaded} />
);
}
答案 0 :(得分:13)
在应用complete
事件之前,您可以检查图片上的onload
属性。
if (!img.complete) {
// add onload listener here
}
答案 1 :(得分:4)
与Hooks相比,这有点整洁:
const useImageLoaded = () => {
const [loaded, setLoaded] = useState(false)
const ref = useRef()
const onLoad = () => {
setLoaded(true)
}
useEffect(() => {
if (ref.current && ref.current.complete) {
onLoad()
}
})
return [ref, loaded, onLoad]
}
const SomeComponent = ({ src }) => {
const [ref, loaded, onLoad] = useImageLoaded()
return (
<div>
<img ref={ref} onLoad={onLoad} src={src} alt="" />
{loaded && <h1>Loaded!</h1>}
</div>
)
}
答案 2 :(得分:2)
另一种方法是使用ref并涵盖这两种情况:
<img
ref={(input) => {
// onLoad replacement for SSR
if (!input) { return; }
const img = input;
const updateFunc = () => {
this.setState({ loaded: true });
};
img.onload = updateFunc;
if (img.complete) {
updateFunc();
}
}}
src={imgSrc}
alt={imgAlt}
/>
答案 3 :(得分:1)
img.complete为true,即使src加载失败。
complete-返回布尔值,如果浏览器已完成图像获取,则返回true,是否成功。如果图像没有src值,它也会显示true。
使用naturalWidth作为img加载是否成功的决定因素
state = { isLoading:是的, hasError:假, }
myRef = React.createRef();
componentDidMount(){ const img = this.myRef.current;
if (img && img.complete) {
if (img.naturalWidth === 0) {
this.handleOnError();
} else {
this.handleImageLoaded();
}
}
}
handleImageLoaded =()=> { 如果(this.state.isLoading){ this.setState({isLoading:false}); } }
handleOnError =()=> { this.setState({hasError:true}); }
render(){ 返回( ); }
另一种方法是在componentDidMount中添加一个“检查”图像,并将其设置为一个eventHandler,然后使该检查图像成为处理eventListener的图像。
componentDidMount() {
const testImg = new Image();
testImg.onerror = this.handleOnError;
testImg.onload = this.handleImageLoaded;
testImg.src = this.props.src; // important to set eventlisteners before src
}