main.jscss
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:html
<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 |
这两个参数用于配置图片相应加载状态下的图片vue
由于也是以图片 src 的形式加载,所以应使用比原图小的图片,固然也可使用 base64 图片node
若是我只是想用纯颜色怎么办?web
除了以上 src 两种形式外,咱们还能够借用 css 来实现加载状态浏览器
该插件会在图片元素上加上当前的加载状态:分别是 loading、loaded、errorapp
<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>
默认配置的监听事件:['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']
布局
为了提升页面性能,咱们能够指定当前页面懒加载监听的事件,如['scroll']性能
但由于 vua-lazyload 是全局配置的,咱们应该怎么对指定页面采用指定配置呢?
为了解决这个问题,咱们须要使用另一个配置项:filter
图片监听过滤,每张图片加载时都会执行一次。
会获得如下关键数据:
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 } |
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: { loaded(listender, options) { console.log('loaded') }, loading(listender, options) { console.log('loading') }, error(listender, options) { console.log('error') } }
因此,为解决上题,要准确拿到图片的大小,应该写在 loaded 状态触发函数下
实现被 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>
lazyload 插件默认会阻塞图片元素的 onload 等事件,若要打开,只需在配置中将当前项设为 true
这里指的是浏览器的一个 API:Intersection Observer :当指定元素进入页面时,自动触发函数
use Intersection Observer to to improve performance of a large number of nodes.
lazyload 默认的触发方式是当页面滚动时,遍历所有元素,查看元素是否在视图内,从而加载图片。所以,当元素特别多时,很是消耗性能。
采用 observer 则能避免这个问题,很好地提升性能。(但有兼容性问题,当浏览器不支持时,即便你设了 true,仍是以 false 去操做)
这个是 observer 的配置参数:
{ rootMargin: '0px', threshold: 0.1 }
表示元素的扩展范围,其值的书写方式与 margin 的书写方式一致。
当值为 10px 时,表示元素的显示范围向外扩展 10px(但不影响布局)
表示元素触发显示的高度比例。
0.1 表示元素显示 10% 的高度时,触发当前元素显示函数。