react imageLoad

原创
2018/02/05 11:15
阅读数 264

今天的这个imageload 的react组件可能和大众的不一样,为什么呢?大众化的可能需要你接口拉取,无限加载,而这个组件并非这样的需求,而是项目中使用的图片都可以,包括单个图片,因此大众的不太符合这样的需求,因此单独写了一个。

import React from 'react';
export default class ImgLazy extends React.PureComponent {
    constructor(props) {
        super(props);
        this.state = {
           height:props.placeholder || 50, 
           image:'http://via.placeholder.com/350x150'
         };
    }
    componentDidMount() {
        let self = this;
        window.addEventListener('scroll', self.checkViewport,false);
        //延迟调用,浏览器渲染需要时间
        setTimeout(function () {
            self.checkViewport();
        },100);
    }
    componentWillUnmount() {
        window.removeEventListener('scroll', this.checkViewport,false);
    }
    checkViewport =() => {
       if(this.inViewport()){
           this.setState({
               height:'',
               image:this.props.url
           }, function () {
               window.removeEventListener('scroll', this.checkViewport,false);
           })
       }
    }
    setRef =(e)=>{
        this.element = e;
    }
    inViewport() {
        const rect = this.element.getBoundingClientRect();
        return rect.top > 0
            && rect.bottom < window.innerHeight
            && rect.left > 0
            && rect.right < window.innerWidth
    }
    render(){
        return(
            <img
                ref={this.setRef}
                height={this.state.height}
                src={this.state.image}
            />
        )
    }
};

使用的是要很简单,引入插件然后把原来的image标签直接换成ImgLazy 传入图片对应的url,你也可以设置placeholder占位符的高度,具体的数值自己调整。

上面的插件是要求图片完全进入可视区才会处理,但是有时候我们需要的可能是看到部分就加载。这个时候上面的代码可能就不满足需求了,还有就是如果是现在比较流行的横向滚动的模块你发现也不好使了,为什么呢?我们把滚动事件绑定到了window上了,针对以上的问题有了下一版本的代码。

import React from 'react';
/*
* @height 默认初始化设置图片的高度
* @placeholder  图片的占位符
* @url 图片的url
* @el  监控滚动的容器,如果是浏览器的可以不设置
* @className 样式控制
* */
export default class ImgLazy extends React.PureComponent {
    constructor(props) {
        super(props);
        this.state = {
            height: props.height || 50,
            image: props.placeholder || 'http://via.placeholder.com/350x150'
        };
    }

    componentDidMount() {
        let self = this;
        self.props.el ?
            document.querySelector(self.props.el).addEventListener('scroll', self.checkViewport, false) :
            window.addEventListener('scroll', self.checkViewport, false);
        //延迟调用,浏览器渲染需要时间
        setTimeout(function() {
            self.checkViewport();
        }, 100);
    }

    componentWillUnmount() {
        let self = this;
        self.props.el ?
            document.querySelector(self.props.el).removeEventListener('scroll', this.checkViewport, false) :
            window.removeEventListener('scroll', this.checkViewport, false);

    }

    checkViewport = () => {
        if (this.inViewport()) {
            this.setState(
                {
                    height: '',
                    image: this.props.url
                },
                function() {
                    window.removeEventListener(
                        'scroll',
                        this.checkViewport,
                        false
                    );
                }
            );
        }
    };
    setRef = e => {
        this.element = e;
    };
    inViewport() {
        const rect = this.element.getBoundingClientRect();
        return (
            rect.top > 0 &&
            rect.bottom < (window.innerHeight + rect.height) &&
            rect.left > 0 &&
            rect.right < (window.innerWidth + rect.width)
        );
    }
    render() {
        return (
            <img
                clasName={this.props.className}
                ref={this.setRef}
                height={this.state.height}
                src={this.state.image}
            />
        );
    }
}

 

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部