Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

图片滚动懒加载 #40

Open
MikeMiller3 opened this issue Mar 1, 2018 · 0 comments
Open

图片滚动懒加载 #40

MikeMiller3 opened this issue Mar 1, 2018 · 0 comments

Comments

@MikeMiller3
Copy link
Owner

MikeMiller3 commented Mar 1, 2018

@see
节流与防抖
饿了么图片优化

背景

页面图片太多,一次性请求,带宽不高用户体验不流畅,服务器压力也大

原理

1.异步加载:通过获取页面滚动位置和图片位置,判断图片是否在用户可视范围内,若在则调用加载方法
2.函数节流:滚动事件可能连续触发,需要保证事件被调用一次。(类似进电梯,电梯5s后关门,只有最后一个人进来是才会触发关门。)
3.函数去抖:如果一直下拉菜单,图片不会被加载直到停止下拉,这并不是我们想要的。去抖就是给函数设定一个执行周期,每个周期只有一个函数在执行,超过这个时间则执行这个函数,并开始新的周期。(自动售货机,每次只操作一个商品)

实际效果

设置节流为0.5秒触发,去抖设置为0.8秒触发。则用户下拉时,第一次触发滚动事件后的0.5-0.8秒之间会触发加载事件。(下拉第一次触发事件即停止,0.5秒后触发,一直下拉不停,0.8秒后触发)

核心代码

//判断是否进入可视范围
function loadImg(){
  var imgs = document.getElementsByTagName('img')
  var clientHeight = document.documentElement.clientHeight;//浏览器窗口高度,innerHeight也可
  imgs = Array.prototype.slice.call(imgs)
  var len = imgs.length;
  var n = 0;
  for(var i=n; i< len;i++){
    var scrollTop = document.documentElement.scrollTop;//滚动条上沿到顶部举例
//var rect = imgs[i].getBoundingClientRect(), imgTop = rect.top
    if(clientHeight + scrollTop > imgTop) {//offsetTop图片上沿到顶部距离
      ++n;
      imgs[m].src = imgs[m].getAttribute('data-url');
      })(i)
    }
  }
}
//节流
debounce(fn, delay){
    var timeout = null, ctx = this
    clearTimeout(timeout);
    (function(){
        timeout = setTimeout(fn.apply(_this, args), delay)
    })(fn, delay, _this, arguments)
}
//去抖
throttle(delay, fn){
    var start = Date.now()
    (function(_this, args){
        var now = Date.now();
        if(now - start >= delay) {
            fn.apply(_this, args)
            start = now
        }
    })(this, arguments)
}

//节流+去抖
lazyLoad(debounce, throttle, fn){
    var timeout = null, start = Date.now();
    clearTimeout(timeout)
    (function(_this, args){
        var now = Date.now();
        if(now - start > throttle) {
            fn.apply(_this, args)
            start = now
        } else {
            timeout = setTimeout(fn.apply(_this, args), debounce)
        }
    })(this, arguments)
}

//监听事件
window.addEventListener('scroll', lazyLoad(loadImg, 5000, 8000), false)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant