父组件
import React from 'react'
import ImgList from './imgList'
class LazyLoadImg extends React.Component {
constructor() {
super()
}
getImg = ()=>[ //模拟获取图片信息
{ src: 'http://localhost:8080/imgs/chaomifen.jpg', title: '1' },
{ src: 'http://localhost:8080/imgs/dapanji.jpg', title: '2' },
{ src: 'http://localhost:8080/imgs/hulayangti.jpg', title: '3' },
{ src: 'http://localhost:8080/imgs/jiaomaji.jpg', title: '4' },
{ src: 'http://localhost:8080/imgs/kaoyu.jpg', title: '5' },
{ src: 'http://localhost:8080/imgs/laziji.jpg', title: '6' },
]
render() {
return (
<>
<ImgList imgArray={this.getImg()}/>
</>
)
}
}
子组件
import React from 'react'
class ImgList extends React.Component {
constructor() {
super()
this.imgRefs = []
}
renderImgList = () =>{
return <>
{
this.props.imgArray.map((item, index) => {
const imgref = React.createRef()
this.imgRefs.push(imgref)
return <div key={index} style={{width:'500px',height:'500px'}}>
<img ref={imgref} src='' data-src={item.src} title={item.title} />
</div>
})
}
<img src='' onError={this.onload}/>
</>
}
imgObserver = new IntersectionObserver(
entries => {
entries.forEach(item => {
// entries 是被监听的元素集合它是一个数组
if (item.intersectionRatio <= 0) return // intersectionRatio 是可见度 如果当前元素不可见就结束该函数。
const {target} = item
target.src = target.dataset.src // 将 h5 自定义属性赋值给 src (进入可见区则加载图片)
this.imgObserver.unobserve(item.target) //加载过的不用加载了
})
},
{
threshold: [0.01]
}
)
onload = () => {
this.imgRefs.forEach(item => {
this.imgObserver.observe(item.current) // 添加需要被观察的元素。
})
}
render() {
return (
<>
{this.renderImgList()}
</>
)
}
}
export default ImgList
在子组件里也可以在componentDidUpdate
调用onload
方法
在renderImgList
此方法中使用<img src='' onError={this.onload}/>
是为了在上面的图片都加载完后,再调用onload
方法
本文中的图片是在本地的tomcat中。
首次打开
此次可以看到只加载了两张图片
滚动条滚动
此次可以看到又加载了两张图片
注意
1.加载过的要设置不用加载,不然即使加载过,再次出现在可视范围内还会再加载
2.如果涉及到分页,用<img src='' onError={this.onload}/>
可能会在第二页不会执行onload
方法,这是可以考虑用componentDidUpdate
来实现
componentDidUpdate(prevProps, prevState) {
if(!isEqual(this.props.imgArray,prevProps.imgArray)){
this.onload()
}
}
利用 componentDidUpdate
实现添加被观察的元素
父组件
import React from 'react'
import ImgList from './imgList'
class LazyLoadImg extends React.Component {
constructor() {
super()
this.state={
imgArray:[]
}
}
componentDidMount(){
this.setState({
imgArray:this.getImg()
})
}
getImg = ()=>[
{ src: 'http://localhost:8080/imgs/chaomifen.jpg', title: '1' },
{ src: 'http://localhost:8080/imgs/dapanji.jpg', title: '2' },
{ src: 'http://localhost:8080/imgs/hulayangti.jpg', title: '3' },
{ src: 'http://localhost:8080/imgs/jiaomaji.jpg', title: '4' },
{ src: 'http://localhost:8080/imgs/kaoyu.jpg', title: '5' },
{ src: 'http://localhost:8080/imgs/laziji.jpg', title: '6' },
]
render() {
return (
<>
<ImgList imgArray={this.state.imgArray}/>
</>
)
}
}
export default LazyLoadImg
子组件
import React from 'react'
import isEqual from 'lodash/isEqual'
class ImgList extends React.Component {
constructor() {
super()
this.imgRefs = []
}
componentDidUpdate(prevProps, prevState) {
if(!isEqual(this.props.imgArray,prevProps.imgArray)){
this.onload()
}
}
renderImgList = () =>{
return <>
{
this.props.imgArray.map((item, index) => {
const imgref = React.createRef()
this.imgRefs.push(imgref)
return <div key={index} style={{width:'500px',height:'500px'}}>
<img ref={imgref} src='' data-src={item.src} title={item.title} />
</div>
})
}
{/* <img src='' onError={this.onload}/> */}
</>
}
imgObserver = new IntersectionObserver(
entries => {
entries.forEach(item => {
// entries 是被监听的元素集合它是一个数组
if (item.intersectionRatio <= 0) return // intersectionRatio 是可见度 如果当前元素不可见就结束该函数。
const {target} = item
target.src = target.dataset.src // 将 h5 自定义属性赋值给 src (进入可见区则加载图片)
this.imgObserver.unobserve(item.target) //加载过的不用加载了
})
},
{
threshold: [0.01]
}
)
onload = () => {
this.imgRefs.forEach(item => {
this.imgObserver.observe(item.current) // 添加需要被观察的元素。
})
}
render() {
return (
<>
{this.renderImgList()}
</>
)
}
}
export default ImgList
意思就是这么个意思,当图片出现在可视范围内,再把真正的图片地址给src
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。