图片懒加载 触底加载 IntersectionObserver

优点:防止页面一次性向服务器发送大量请求,导致服务器响应面,页面卡顿崩溃等

 

懒加载函数

 

function lazyAll(options = { lazybox: [], showOffset: 150, throttleTime: 100, imgtruestr: 'lazyimg' }) {
    //lazybox //所有图片元素。必须有高度,可以用加载图,不给高度也可以,但是会有停顿
    // showOffset 图片底部距离底部多高就开始加载, 越大越早加载
    // throttleTime 节流时间
    //开始加载
    const { lazybox, showOffset, throttleTime, imgtruestr } = options
    const singlelazy = (lazyimg) => {
        let trueimg = lazyimg.getAttribute(imgtruestr)
        lazyimg.style.opacity = 0.5
        lazyimg.src = trueimg //替换真实图片
        lazyimg.onload = () => {
            lazyimg.style.opacity = 1
            lazyimg.style.transition = 'all 0.3s';
            //加载成功则不透明了
        }
        lazyimg.setAttribute('isload', true)
        //添加一个加载成功的标识
    }
    //节流函数
    function throttle(func, delay) {
        var prev = Date.now();
        return function () {
            var context = this;
            var args = arguments;
            var now = Date.now();
            if (now - prev >= delay) {
                func.apply(context, args);
                prev = Date.now();
            }
        }
    }
    const lazyBoot = (lazyimgArr) => {
        let B = document.documentElement.clientHeight
        lazyimgArr = Array.from(lazyimgArr)
        for (let index = 0; index < lazyimgArr.length; index++) {
            let lazyimg = lazyimgArr[index];
            if (lazyimg.getAttribute('isload') === 'true') continue //已经加载过了
            let A = lazyimg.getBoundingClientRect().bottom //元素距离底部的高度
            if (A <= (B + showOffset)) {
                // console.log(lazyimg.children)
                singlelazy(lazyimg)
            }
        }
    }
    //初始化执行一次
    setTimeout(() => {
        lazyBoot(lazybox)
    }, 500)
    window.onscroll = throttle(() => {
        lazyBoot(lazybox)
    }, throttleTime)
}
let lazybox = document.querySelectorAll('.lazybox > img')
lazyAll({ lazybox: lazybox, showOffset: 100, throttleTime: 100, imgtruestr: 'lazyimg' })
<div class="lazybox">
        <img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3286238346,2636386852&fm=26&gp=0.jpg" alt=""
        lazyimg='https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1359446852,3171321292&fm=26&gp=0.jpg'>
</div>

触底加载

 

html
   //将该元素至于列表底部,只要该元素出现在视口,即可触发回调
  <div id='more'>loading...<div>

js
let loadMore = () => {
    let oboptions = {
        threshold: [0] //可以给0 - 1 之间的数  0 元素刚进入窗口  1 完全进入窗口 
    }
    let ob = new IntersectionObserver(async changes => {
        let item = changes[0] //监听的所有对象。这里触底加载我们只监听了一个元素
        if (item.isIntersecting) {//元素刚好进入视口
            //加载更多
            let res = await Promise.resolve('xxx')
            //重新获取所有的图片元素
            if (res == 'xxx') { //满足一定条件,解除
                ob.unobserve(document.getElementById('more'))
            }
            console.log(res)
        }
    }, oboptions)
    ob.observe(document.getElementById('more'))
}
loadMore()

IntersectionObserver 监听某个元素和视口交叉的状态

//该api判断的以矩形条件为例的

有兼容性问题,请使用babel

new IntersectionObserver(
  entries.forEach(entry=>{
  }), 
  {
    threshold: [0, 0.25, 0.5, 0.75, 1] //0%、25%、50%、75%、100% 可见时,触发回调多次回调,传一个就好
    // [0, 0.5, 1],表示在两个矩形开始相交,相交一半,完全相交这三个时刻都要触发一次回调函数。如果你传了个空数组,它会给你自动插入 0,变成 [0],也等效于默认值 0
    //不仅当目标元素从视口外移动到视口内时会触发回调,从视口内移动到视口外也会:需要加载完毕后,立刻移除监听,免得再次触发渲染
    root:null,//不填则默认为浏览器窗口
    rootMargin:'100px 0px'//放大了根元素的区域 这里相当于加大了浏览器的上margin 和 下margin 图片加载会更提前,只能用px和百分比 em会报错
  }
).observe(监听的元素)

observer.disconnect(); //终止对所有可见元素的变化观察

 性能比较好,该api默认是异步的,并且监听元素是默认去重的

let lazybox = document.querySelectorAll('.lazybox > img')
const singlelazy = (lazyimg) => {
    let trueimg = lazyimg.getAttribute('lazyimg')
    lazyimg.style.opacity = 0.5
    lazyimg.src = trueimg //替换真实图片
    lazyimg.onload = () => {
        lazyimg.style.opacity = 1
        lazyimg.style.transition = 'all 0.3s';
        //加载成功则不透明了
    }
}

const lazyAllImage = () => {
    let oboptions = {
        threshold: [0.2]
    }
    //注意 如果异步加载数据,该对象只能存在一个,可以提出来单独用ob
    let ob = new IntersectionObserver(changes => {
        console.log(changes) //所有被监听到的盒子 并且默认是去重
        changes.forEach(item => {
            let { isIntersecting, target } = item
            if (isIntersecting) {
                singlelazy(target)
                ob.unobserve(target)
            }
        })
    }, oboptions);
    
    //每次异步数据。这里要重新添加监听的对象
    [].forEach.call(lazybox, box => {
        ob.observe(box)
    })
}
lazyAllImage()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值