Ответ 1
Вы можете проверить свойство complete
на изображении перед применением события onload
.
if (!img.complete) {
// add onload listener here
}
В изоморфной отрисовке страницы изображение можно скачать перед основным файлом 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 loaded
.
image.jpg
меньше, чем script.js
В этом сценарии вы можете увидеть проблему, описанную в начале поста. Событие onLoad
не вызывается.
Что я могу сделать, чтобы вызвать событие onLoad
в сценарии 2?
Чтобы определить, готово ли изображение при рендеринге, вы должны проверить свойство complete
на чистом объекте img
javascript:
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} />
);
}
Вы можете проверить свойство complete
на изображении перед применением события onload
.
if (!img.complete) {
// add onload listener here
}
Другой способ - использовать 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}
/>
img.complete верно даже в случае сбоя загрузки src.
complete - возвращает логическое значение, которое имеет значение true, если браузер завершил выборку изображения, независимо от того, успешно оно или нет. Это также показывает true, если изображение не имеет значения src.
Используйте naturalWidth в качестве определяющего, была ли загрузка IMG успешной или нет
state = {isLoading: true, hasError: false,}
myRef = React.createRef();
componentDidMount() {const img = this.myRef.current;
if (img && img.complete) {
if (img.naturalWidth === 0) {
this.handleOnError();
} else {
this.handleImageLoaded();
}
}
if (img && img.complete) {
if (img.naturalWidth === 0) {
this.handleOnError();
} else {
this.handleImageLoaded();
}
}
handleImageLoaded =() => {if (this.state.isLoading) {this.setState({isLoading: false}); }}
handleOnError =() => {this.setState({hasError: true}); }
render() {return(); }
<img
src={this.props.imageUrl}
onLoad={this.handleImageLoaded.bind(this)}
onError={this.handleImageErrored.bind(this)}
/>