14

特点

  • 轻量、强大、易用
  • 支持所有图片
  • 支持添加加载时样式
  • 支持 vue1 和 vue2

使用方法

main.js

import Vue from 'vue'
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload)

new Vue({
  el: '#app',
  data: {
    imgs: [
      'http://covteam.u.qiniudn.com/test16.jpg?imageView2/2/format/webp',
      'http://covteam.u.qiniudn.com/test16.jpg?imageView2/2/format/webp',
      'http://covteam.u.qiniudn.com/test16.jpg?imageView2/2/format/webp',
    ]
  }
})

template:

<div id="app">
    <img v-for="img in imgs" v-lazy="img">
    <img v-for="img in imgs" v-lazy:background-image="img">
</div>

可配置项

key description default
preLoad 提前加载高度(数字 1 表示 1 屏的高度) 1.3
error 图片加载失败时显示的图片 'data-src'
loading 图片加载状态下显示的图片 'data-src'
attempt 加载错误后最大尝试次数 3
listenEvents 监听事件 ['scroll', 'wheel', 'mousewheel',
'resize', 'animationend', 'transitionend',
'touchmove']`
adapter 动态修改元素属性 { }
filter 图片监听过滤 { }
lazyComponent 组件懒加载 false
dispatchEvent 触发元素状态监听事件(error, loaded, rendered) false

重点

loading & error

这两个参数用于配置图片相应加载状态下的图片

因为也是以图片 src 的形式加载,因此应使用比原图小的图片,当然也可以使用 base64 图片

如果我只是想用纯颜色怎么办?

除了以上 src 两种形式外,我们还可以借用 css 来实现加载状态

该插件会在图片元素上加上当前的加载状态:分别是 loading、loaded、error

<img src="imgUrl" lazy="loading">
<img src="imgUrl" lazy="loaded">
<img src="imgUrl" lazy="error">

此时使用元素选择器,来给每一个状态添加相应的样式

<style>
  img[lazy=loading] { }
  img[lazy=error] { }
  img[lazy=loaded] { }
</style>

listenEvents

默认配置的监听事件:['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']

为了提高页面性能,我们可以指定当前页面懒加载监听的事件,如['scroll']

但因为 vua-lazyload 是全局配置的,我们应该怎么对指定页面采用指定配置呢?

为了解决这个问题,我们需要使用另外一个配置项:filter

filter(listener, options)

图片监听过滤,每张图片加载时都会执行一次。

会得到以下关键数据:

listener

key description value
el 当前元素 -
naturalHeight 图片原始高度 180
naturalWidth 图片原始宽度 236
performanceData 加载性能 {
init: 1526632128700,
loadStart: 1526632128708,
loadEnd: 1526632128829
}
rect 图片元素 getBoundingClientRect 值 {
bottom: 25, <br/> height: 0,
left: 8,
right: 312,
top: 25,
width: 304,
x: 8,
y: 25
}
state 加载状态 {
error: false, 
loaded: true, 
rendered: false
}

options

key description value
ListenEvents 与配置项 listenEvents 相同(但注意是大写开头,怀疑是 bug,已提 issue) ['scroll']
supportWebp 判断当前浏览器是否支持 webp Boolean

supportWebp 实现代码

function supportWebp() {
  if (!inBrowser) return false;
  var support = true;
  var d = document;
  try {
    var el = d.createElement('object');
    el.type = 'image/webp';
    el.style.visibility = 'hidden';
    el.innerHTML = '!';
    d.body.appendChild(el);
    support = !el.offsetWidth;
    d.body.removeChild(el);
  } catch (err) {
    support = false;
  }
  return support;
}

之前留了一个问题:如何根据当前页面需要配置懒加载监听方式?

这里便采用了 filter 来解决这个问题

filter: {
  index(listener, opts) {
    if (location.href.indexOf('index')>-1) {
      opts.ListenEvents = ['animationend']        
    }
  }
}

除此之外,filter 还能做什么呢?

这里再举一个官方的例子:

filter: {
  progressive (listener, options) { // 实现渐近式加载图片(先加载模糊的图)
    const isCDN = /qiniudn.com/
    if (isCDN.test(listener.src)) {
        listener.el.setAttribute('lazy-progressive', 'true')
        listener.loading = listener.src + '?imageView2/1/w/10/h/10'
    }
  },
  webp (listener, options) { // 加载 webp 图
    if (!options.supportWebp) return
      const isCDN = /qiniudn.com/
      if (isCDN.test(listener.src)) {
        listener.src += '?imageView2/2/format/webp'
      }
  }
}

讲到这里,我们了解 filter 是在加载图片之前遍历调用的。

但!为什么 listener 参数里会有图片的加载时长和大小呢??

图片的加载时长和大小参数是在图片 loaded 状态后,再写到对象里的。所以,如果你在 filter 里直接读取图片的 “加载后属性”,会报错(万能的 setTimeout 了解下)。此时,你就应该使用下面的配置了:adapter

adapter

用于定义图片的三个加载状态下分别触发的函数:

adapter: {
  loaded(listender, options) {
    console.log('loaded')
  },
  loading(listender, options) {
    console.log('loading')
  },
  error(listender, options) {
    console.log('error')
  }
}

所以,为解决上题,要准确拿到图片的大小,应该写在 loaded 状态触发函数下

lazyComponent

实现被 lazy-component 标签包含的元素延迟渲染

<lazy-component @show="handler">
  <img class="mini-cover" :src="img.src" width="100%" height="400">
</lazy-component>

<script>
  {
    ...
    methods: {
      handler (component) {
        console.log('this component is showing')
      }
    }

  }
</script>

dispatchEvent

lazyload 插件默认会阻塞图片元素的 onload 等事件,若要打开,只需在配置中将当前项设为 true

observer

这里指的是浏览器的一个 API:Intersection Observer :当指定元素进入页面时,自动触发函数

use Intersection Observer to to improve performance of a large number of nodes.

lazyload 默认的触发方式是当页面滚动时,遍历全部元素,查看元素是否在视图内,从而加载图片。因此,当元素特别多时,非常消耗性能。

采用 observer 则能避免这个问题,很好地提高性能。(但有兼容性问题,当浏览器不支持时,即使你设了 true,还是以 false 去操作)

observerOptions

这个是 observer 的配置参数:

{ rootMargin: '0px', threshold: 0.1 } 

rootMargin

表示元素的扩展范围,其值的书写方式与 margin 的书写方式一致。

当值为 10px 时,表示元素的显示范围向外扩展 10px(但不影响布局)

threshold

表示元素触发显示的高度比例。

0.1 表示元素显示 10% 的高度时,触发当前元素显示函数。


henry_chen
322 声望44 粉丝