同构/通用反应中的图像onLoad事件 - 加载图像后注册事件

时间:2016-09-29 18:46:31

标签: javascript reactjs isomorphic-javascript

在同构呈现的页面图像中,可以在主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} />
    );
}

场景1 - image.jpg大于script.js

image.jpg is bigger than script.js

在这种情况下一切正常。事件在最终加载图像之前注册,因此在控制台中是image loaded消息。

情景2 - image.jpg小于script.js

image.jpg is smaller than 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} />
    );
}

4 个答案:

答案 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。

  1. 使用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(){     返回(              ); }

  2. 另一种方法是在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
}
相关问题