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

图片懒加载

简单的来讲:javascript

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

(如下但愿结合源码服用)前端

step 1:

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

https://github.com/ZWkang/jav...java

这个demo能够看得出,是实现了以前提到的几点。git

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

能够看出来上面这段代码其实是很糟糕的。

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

step 2:

前端迭代过程咱们能够发现。不少时候新的api的出现,是一部分是为了支持新的特性,一部分是为了弥补不够用github

前面说到很低效的offset类apiapi

并不够用。因此出现了缓存

此处通过一段时间的思考

https://github.com/ZWkang/jav...

进行迭代到这一版、

事实上这一版的代码写的也是很是的糟糕的。由于个人es6在那个时候并非很好。

能够在变量的声明上看出。不少时候我是没转变过来的。可是那不影响

简单的讲一下

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

而后能够发现,这一版本引入了Setting可配置。

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

在这一版咱们引入了getBoundingClientRect

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

能够说这一版解决了初版咱们发现的几个问题。

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

固然咱们能够看看这样写法的用处。

咱们能够很简单的侵入式的使用在vue上。

https://github.com/ZWkang/sim...

能够看看这个。核心代码基本是彻底一致的。

只是获取元素须要在渲染后获取。否则会致使获取不了元素。固然这个涉及到了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/jav...

在第三版咱们引入一个更新的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。固然该仓库还有一些宝藏~~


相关文章
相关标签/搜索