4

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

 3 years ago
source link: https://zwkang.com/?p=395
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

图片懒加载

简单的来说:
就是一些需要加载的图片,我们先使用占位的方式(用于判断是否存在视图内。),减少网络下载图片对首屏渲染的压力,从而使得首屏更快的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。当然该仓库还有一些宝藏~~


Comments

发表评论 取消回复

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

评论

姓名 *

电子邮件 *

站点

在此浏览器中保存我的名字、电邮和网站。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK