kangkangblog

Menu

图片懒加载的一些想法与实践

图片懒加载

简单的来说:

就是一些需要加载的图片,我们先使用占位的方式(用于判断是否存在视图内。),减少网络下载图片对首屏渲染的压力,从而使得首屏更快的load

(以下希望结合源码服用)

step 1:

第一步肯定是run一个简单的demo能实现替换占位符。并且进行判断是否在view视图内。

这个demo可以看得出,是实现了之前提到的几点。

它使用offset类的api进行获取位置,并进行遍历,再计算从而获得相对整个视图的位置。简单的替换图片进行这种获取转换src的方法

可以看出来上面这段代码实际上是很糟糕的。

  1. 它没有任何的封装
  2. 它没有可以让我输入的配置
  3. 它的获取性能太低效。(我们应该知道offset之类的api为了获得大小,总会触发一次Reflow,来进行位置的获取。)
  4. 它支持项太少了。只支持了我们特定的data-src

step 2:

前端迭代过程我们可以发现。很多时候新的api的出现,是一部分是为了支持新的特性,一部分是为了弥补不够用

前面说到很低效的offset类api

并不够用。所以出现了

此处经过一段时间的思考

进行迭代到这一版、

事实上这一版的代码写的也是非常的糟糕的。因为我的es6在那个时候并不是很好。

可以在变量的声明上看出。很多时候我是没转变过来的。但是那不影响

简单的讲一下

首先当然是声明一些将被缓存的变量

然后可以发现,这一版本引入了Setting可配置。

lazyload是一个对象,一些实例方法挂载在上面。这里没有用class之类的,也就是使用,下面会说一下这种写法。页面共享一个实例。

在这一版我们引入了getBoundingClientRect

使用getBoundingClientRect来判断。明显是比较高效的。而且性能损耗并不会比offset类的高。

可以说这一版解决了第一版我们发现的几个问题。

引入了配置。UMD的模块写法。获取的api判断是否在视图内优雅降级。支持了更多项,srcset backgroundImage(当然对于srcset的处理其实并没有很好的方法。它还是有一些坑的。)

当然我们可以看看这样写法的用处。

我们可以很简单的侵入式的使用在vue上。

可以看看这个。核心代码基本是完全一致的。

只是获取元素需要在渲染后获取。不然会导致获取不了元素。当然这个涉及到了vue的执行时机。

Vue.use(lazy, {
background: true,
backgroundTag: 'data-background',
imgSrc: true,
imgTag: 'data-src',
parent: null,
srcset: false,
srcsetTag: 'data-srcset',
delayTime: 200,
rendered: function () { },
deleleData: true,
firstLoad: true
})

在use 安装的时候设置配置文件,注入在vue组件的实例实际上在这个时候就已经有了对应的配置

updated: function () {
this.lazyload.init({})
},
destroyed: function () {
this.lazyload.cache = []
}

然后只需要简单的配置就可以使用我们的lazyload组件了。

实际上这种方法。是完全的将vue当成普通的html dom来处理了。

很多vue的高级东西并没有用到。但是这样确实是很简单不是么。

而这样子的做法很便捷,但是也有缺陷。那就是,多个子组件的时候。

你的组件init初始需要放在相对的父级组件使用,而不是多个子组件使用。。

更好的方式是应该使用一个component的组件来承载整个lazyload的流程


step 3:

其实上面步骤的lazyload组件已经是可用了。

那么第三版我们还可以对它进行什么改造。

https://github.com/ZWkang/javascript-demo/blob/master/%E6%87%92%E5%8A%A0%E8%BD%BD(over)/kanglazyload.1.js

在第三版我们引入一个更新的api

IntersectionObserver

这个observer也是更为强劲。它可以直接进行判断是否在视图内,有一个boolean的处理值。并且还携带一些属性。

使用也很简单。

只需要new初始化时候传入对应的回调函数。然后observe element节点即可

第三版我们还可以进行更好的优化

例如加入loading图片 error图片 之类的配置文件

并且将我们的逻辑代码更抽象,例如一些判断的if else 可以用iife直接判断返回一个函数

减少一些if else的判断。而是在第一次解析的时候就确定了。

这里。我们可以看一下代码职责分离 耦合度低的好处

我在第二版写的srcChange 是独立的函数,传入对应的节点处理对应的事情。

而在第三版即使我们添加新的处理api

这个srcChange也是完全复用的。是完全。

图片增加loading error的处理。

就是new Image代理我们获取图片。onload成功之后就再替换。预加载的原理跟这个差不多,预加载就是将所有图片获取再进行Image获取


唔。大概这个时候这个lazyload插件就到达可用的程度了(当然可不可用我也不知道,因为我没有在实际情况下生产情况使用(欢迎使用后的反馈),从简单测试来看,它是可行的)

我很喜欢写小demo,因为它不大。我可以任意重构,想怎么搞就怎么搞。

唔。很欢迎很欢迎交流啊!!!!!!

但是不要喷我。我读书少,你喷不赢我的。

最后是祝福语。

希望阅读这篇文章能有一点点帮助到你。

也厚脸皮求一下下star。当然该仓库还有一些宝藏~~


— 于 共写了2368个字
— 文内使用到的标签:

发表评论

电子邮件地址不会被公开。 必填项已用*标注