图片懒加载与预加载(超简版代码)

280 阅读2分钟

图片的懒加载与预加载

因为图片内容占用内存普遍比较大,所以对于图片加载过程的优化是改善用户非常重要的手段,懒加载与预加载就是最常用的方式。

所谓懒加载就是说,如果一个页面有多张照片需要展示,我们并不是在第一时间全部加载展示,而是,动态地只加载与视图窗口相关的一部分图片。好处是可以减少进入页面的等待时间,确保窗口的图片优先加载;
预加载是,通过预期用户接下来会进行什么样的操作来加载相应的页面、图片,好处是切换更顺畅,减少白屏和菊花的出现频率

懒加载(jQuery)

实现思路

1.因为在HTML5中,以data-开头的自定义属性都是合法的, 页面加载最初的时候,图片的 src 属性空着(因为在 ie 浏览器下会出现红色大叉叉,影响美观,最好设置成一个 1px * 1px 的透明小图片),我们用 data-url 属性来存图片的真实 url

2.监听容器(在这里假设是 window)的滚动事件,获取窗口位置与图片位置,如果图片出现在窗口内,把图片的 src 设置成 data-url 属性的值。

3.以上就完成了,不过,因为 scroll 事件挺频繁的,我们需要做一下节流。

代码

假设 html 中有这么一串图片(可略过)

<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/article1.jpg" alt="">
<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/article2.jpg" alt="">
<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/article3.jpg" alt="">
<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/ui.jpg" alt="">
<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/cnode.jpg" alt="">
<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/todo.jpg" alt="">
<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/eevee.jpg" alt="">
<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/bm.jpg" alt="">
<img src="./point.png" class="scrollLoading" data-url="https://ggg50.github.io/resume/img/mac.jpg" alt="">

js 代码:

let canScroll = true // 用于节流
let $imgDoms = $(".scrollLoading")

checkForImgShow()

//给 window 绑定 scroll 事件
$(window).scroll(function(){
  if(!canScroll) return
  scrollSwitch()
  checkForImgShow()
})

//检查、决定图片是否加载
function checkForImgShow(){
  $imgDoms.each(function(){
    let screenScroll = $(window).scrollTop()
    if (!this.preloaded) {
        if($(this).offset().top <= screenScroll +  $(window).height()  + 100) {
          $(this).attr("src", $(this).attr("data-url"))
          this.preloaded = true // 标记已加载
        }
    }
  })
}

//节流函数
function scrollSwitch(){
  canScroll = false
  setTimeout(()=>{canScroll = true}, 100)
}

预加载(jQuery)

预加载的关键在于“预测用户大概率会做什么事”,因为毫无预测的乱加载只会浪费资源。

比如在点击跳转的按钮上,当用户鼠标移动到这个按钮上的时候,大概率就要点击了,我们可以在 mouseenter 的时候就触发加载,争取 0.5 秒左右的时间,减少白屏的概率。
再比如,在搜索框中,当用户已经输入完了的时候,就可以触发搜索,当用户真正点击搜索按钮的时候,有可能我们已经完成了搜索。

下面这个预加载的思路来自于张鑫旭的基于用户行为的图片等资源预加载

准备一些 css 和 html (可略过)

.tab a {
    display: inline-block;
    padding: 5px 0;
    margin: 0 15px;
    border-bottom: 3px solid transparent;
    color: #343;
    font: menu;
    font-size: 14px;
}
.tab .active {
    border-bottom-color: #019EE4;
    color: #019EE4;
}
.panel {
    padding: 15px;
}
.panel img {
    display: none;
}
.panel .active {
    display: inline-block;
}
  <div id="tab" class="tab">
      <a href="javascript:" class="active">图1</a>
      <a href="javascript:" class="">图2</a>
      <a href="javascript:" class="">图3</a>
  </div>
  <div id="panel" class="panel">
      <img class="scrollLoading active" src="https://ggg50.github.io/resume/img/eevee.jpg" alt="">
      <img class="scrollLoading" data-url="https://ggg50.github.io/resume/img/bm.jpg" alt="">
      <img class="scrollLoading" data-url="https://ggg50.github.io/resume/img/mac.jpg" alt="">
  </div>

js 代码如下:

let $tabs = $("#tab a")
let $images = $("#panel img")

$tabs.each(function(index) {
  $(this).click(function() {
    statuSwitch($(this))
    statuSwitch($($images[index]))
  })
})

//预加载代码,在这个例子中,核心是 mouseenter 事件
$tabs.each(function(index){
  if(!this.preloaded)
  $(this).mouseenter(function() {
    $images.eq(index).attr("src", $images.eq(index).attr("data-url"))

    // 标记已加载
    this.preloaded = true
  })
})

function statuSwitch($dom){
  $dom.addClass("active").siblings().removeClass("active")
}