专栏首页吴裕超实现图片懒加载

实现图片懒加载

Web 图片的懒加载就是通过读取img元素,然后获得img元素的data-src(也可以约定为其他属性名)属性的值,并赋予img的src,从而实现动态加载图片的机制。

这里需要注意的是: img在初始化的时候不要设置src属性,因为即使设置 src='' 浏览器也会尝试加载图片。

一个简单的图片懒加载共涉及两个方面,

1. HTML 约定

我们首先需要给准备实施懒加载的img元素添加指定的class 这里为m-lazyload ,同时将img src赋值给 data-src属性。 具体示例为:

  1. <img class="m-lazyload" data-src="imgUrl">

2. JavaScript 实现

动态加载总共分为以下几个步骤,这里每个步骤都将被拆分为独立的函数

1. 添加页面滚动监听事件
  1. window.addEventListener('scroll', _delay, false);
  2. function _delay() {
  3. clearTimeout(delay);
  4. delay = setTimeout(function () {
  5. _loadImage();
  6. }, time);
  7. }
2. 当触发监听事件时会执行 _loadImage 函数,该函数负责加载图片
  1. function _loadImage() {
  2. for (var i = imgList.length; i--;) {
  3. var el = imgList[i];
  4. if (_isShow(el)) {
  5. el.src = el.getAttribute('data-src');
  6. el.className = el.className.replace(new RegExp("(\\s|^)" + _selector.substring(1, _selector.length) + "(\\s|$)"), " ");
  7. imgList.splice(i, 1);
  8. }
  9. }
  10. }

虽然执行了_loadImage函数,但是我们得知道哪些图片需要被加载,这里的判断依据是什么呢?

依据就是判断该图片是否在当前窗口的可视区域内,在这里我们封装一个_isShow函数来实现

  1. function _isShow(el) {
  2. var coords = el.getBoundingClientRect();
  3. return ( (coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + parseInt(offset));
  4. }

自此一个图片加载的闭环就形成了

当网页滚动的事件被触发 -> 执行加载图片操作 -> 判断图片是否在可视区域内 -> 在,则动态将data-src的值赋予该图片。

太简单了?

事实就是如此!!!

如此简单,不妨扩展一下

  1. 添加一些自定义参数,谁都喜欢自定义,不是吗?
  2. 支持iScroll, iScroll是一个高性能,资源占用少,无依赖,多平台的javascript滚动插件。
这里我们做了些优化
  1. 图片加载后移除选择器,避免重复判断。
  2. 缓存img元素结合,减少dom元素查询性能损耗
  3. 扩展prototype添加getNode方法,支持分页数据懒加载(由于我们之前缓存了dom元素)

OK!说了这么多,show me the code 吧!

  1. (function () {
  2. var imgList = [], // 页面所有img元素集合
  3. delay, // setTimeout 对象
  4. offset, //偏移量,用于指定图片距离可视区域多少距离,进行加载
  5. time, // 延迟载入时间
  6. _selector; // 选择器 默认为 .m-lazyload
  7. function _isShow(el) {
  8. var coords = el.getBoundingClientRect();
  9. return ( (coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + parseInt(offset));
  10. }
  11. function _loadImage() {
  12. for (var i = imgList.length; i--;) {
  13. var el = imgList[i];
  14. if (_isShow(el)) {
  15. el.src = el.getAttribute('data-src');
  16. el.className = el.className.replace(new RegExp("(\\s|^)" + _selector.substring(1, _selector.length) + "(\\s|$)"), " ");
  17. imgList.splice(i, 1);
  18. }
  19. }
  20. }
  21. function _delay() {
  22. clearTimeout(delay);
  23. delay = setTimeout(function () {
  24. _loadImage();
  25. }, time);
  26. }
  27. function ImageLazyload(selector, options) {
  28. var defaults = options || {};
  29. offset = defaults.offset || 0;
  30. time = defaults.time || 250;
  31. _selector = selector || '.m-lazyload';
  32. this.getNode();
  33. _delay();//避免首次加载未触发touch事件,主动触发一次加载函数
  34. if (defaults.iScroll) {
  35. defaults.iScroll.on('scroll', _delay);
  36. defaults.iScroll.on('scrollEnd', _delay);
  37. } else {
  38. window.addEventListener('scroll', _delay, false);
  39. }
  40. }
  41. ImageLazyload.prototype.getNode = function () {
  42. imgList = [];
  43. var nodes = document.querySelectorAll(_selector);
  44. for (var i = 0, l = nodes.length; i < l; i++) {
  45. imgList.push(nodes[i]);
  46. }
  47. };
  48. })();

来源: 实现一个图片懒加载插件有多难? – 前端有多难? – SegmentFault

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • iOS 中, vue使用select option,第一个选项无法第一次进入无法选中问题

    参考: https://github.com/vuejs/vue/issues/6581

    吴裕超
  • vue 组件使用中的细节点

    有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>、<...

    吴裕超
  • 性能优化总结

    吴裕超
  • 动态加载router,用Vue+Element UI搭建后台管理系统界面

    今天教大家用 Vue + Element UI 搭建一个后台管理系统界面,首先讲一下需要用到的组件标签,重点是左侧菜单栏的创建,Element UI 左侧菜单的...

    南风
  • Element NavMenu 无限级菜单

    tianyawhl
  • WPF游戏开发——小鸡快跑

    同上一篇文章一样,游戏还是小鸡快跑,不同的是,这次的小鸡不在是跳大坑,而是躲子弹了。

    Kiba518
  • [javascript] vuejs的elementui配合iframe实现页面跳转

    一般后台界面都有三大部分 , 顶部导航 , 左侧导航,右侧的主界面 . 点击左侧和顶部的导航 , 可以在右侧的主界面展示不同的界面

    陶士涵
  • vue通过数据驱动实现表格行的增加与删除

    以前做明细表格的新增改查,都是需要操作dom的,但现在数据驱动,不需要了,只需要操作数据即可,相当简单

    星痕
  • 浅入深出Vue:文章列表

    这里我们选择 ElementUI 中的 Table 组件来进行展示,文章列表接口的数据定义如下:

    若羽
  • 自定义element UI的upload组件

    本文由腾讯云+社区自动同步,原文地址 https://stackoverflow.club/article/elementui_upload_custom/

    羽翰尘

扫码关注云+社区

领取腾讯云代金券