UNPKG

mem-lazyload

Version:

#### 项目介绍 图片懒加载html5原生组件

180 lines (174 loc) 6.01 kB
/** * 使用方法: * let lazy = new LazyLoad(window); * // 当页面lazyload图片dom新增时调用update方法刷新lazy数据 * lazy.update(); */ ((global, factory) => { typeof module !== 'undefined' && typeof module.exports === 'object' ? module.exports = factory() : (global.LazyLoad = factory()); })(window, function () { // 自定义标签名 const CUSTOM_ELEMENT_NAME = 'lazy-image'; const ANIMATION_CLASS = 'lazy-image-load'; // 样式常量 const DISPLAY_DEFAULT = 'inline-block'; const DISPLAY_INLINE = 'inline'; const POSITION_DEFAULT = 'relative'; const POSITION_STATIC = 'static'; const IMAGE_CLASS = 'lazy-image-real-dom'; const INITIAL_IMAGE = 'http://qn.zhangyy.xyz/5c9206d469.jpeg'; // 自定义类 class LazyImage extends HTMLElement { constructor() { super(); } // 初始化元素 init() { if (!LazyImage.$id) { LazyImage.$id = 0; } LazyImage.$id += 1; this.$id = LazyImage.$id; // 是否已经加载图片 this.loaded = false; let styleSheets = window.getComputedStyle(this, null); let display = styleSheets.display; let position = styleSheets.position; this.setStyle(this, { display: display === DISPLAY_INLINE ? DISPLAY_DEFAULT : display, position: position === POSITION_STATIC ? POSITION_DEFAULT : position, }); this.activeClass = this.getAttribute('active-class') || ANIMATION_CLASS; this.initSrc = this.getAttribute('init-src') || INITIAL_IMAGE; // 插入图片dom this.img = this.insertImage(); // 注册过的自定义组件在dom更新时会重新注册,但是插入的dmo不会被注销,所以只更换自定义dom的外壳, // 插入的dom状态保持原样 if (this.loaded) { this.loadEnd(); } this.setStyle(this.img, { position: 'absolute', left: '0', top: '0', width: '100%', height: '100%', }); } // 插入图片dom insertImage() { let oImg = this.querySelector(`.${IMAGE_CLASS}`); if (!oImg) { oImg = document.createElement('img'); oImg.src = this.initSrc; oImg.className = IMAGE_CLASS; this.insertBefore(oImg, this.firstChild); } else if (this.getAttribute('src') === oImg.src) { this.loaded = true; } return oImg; } // 给dom设置样式 setStyle(dom, styles) { Object.keys(styles).forEach((prop) => { dom.style[prop] = styles[prop]; }); } // 加载图片 load() { if (this.loaded) { return; } this.img.src = this.getAttribute('src'); this.img.className += ` ${this.activeClass}`; this.loaded = true; this.addEventListener('webkitAnimationEnd', this.loadEnd, false) } loadEnd(e) { this.img.className = this.img.className.replace(this.activeClass, ''); this.removeEventListener('webkitAnimationEnd', this.loadEnd); } // dom首次被插入文档DOM时调用 connectedCallback() { this.init(); } // dom移除时调用 disconnectedCallback() { this.loadEnd(); } } // 注册自定义组件 customElements.define(CUSTOM_ELEMENT_NAME, LazyImage); class LazyLoad { constructor(container = window) { // wrap为滑动容器的对象 // container为dom容器,做查询dom的容器 this.wrap = container; if (container === window) { container = document; } this.container = container; this.lazyImages = []; this.init(); } init() { this.insertStyle(); this.update(); this.registerScroll(); } // 插入样式 insertStyle() { let oStyle = document.createElement('style'); oStyle.innerHTML = ` .${ANIMATION_CLASS} { animation: lazyImageLoad 1s; } @keyframes lazyImageLoad { from { opacity: 0; } to { opacity: 1; } } `; document.head.appendChild(oStyle); } // 类数组转换 makeArray(arrayLike) { return Array.prototype.slice.call(arrayLike); } // 更新需要懒加载的dom update() { setTimeout(() => { this.lazyImages = this.makeArray(this.container.querySelectorAll('lazy-image')) .filter((oItem) => { return !oItem.loaded; }); this.loadImage(); }, 0); } // 加载更多图片 loadImage() { this.lazyImages = this.lazyImages.filter((oItem) => { let rect = oItem.getBoundingClientRect(); let top = rect.top; if (top < window.innerHeight) { oItem.load(); return false; } return true; }); } // 注册scroll事件 registerScroll() { this.wrap.addEventListener('scroll', (e) => { if (this.lazyImages.length) { this.loadImage(); } }); } } return LazyLoad; });