今天的这个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}
/>
);
}
}