UNPKG

balm-ui

Version:

A modular and customizable UI library based on Material Design and Vue 3

127 lines (109 loc) 2.78 kB
const DEFAULT_OPTIONS = { src: '', delay: 300, scrollEvent: 'scroll' }; let globalOptions = DEFAULT_OPTIONS; let canRendering = true; const getImageElement = (el, fn) => { const imgEl = el.tagName === 'IMG' ? el : el.querySelector('img'); if (imgEl && imgEl.tagName === 'IMG') { fn(imgEl); } else { canRendering = false; throw new Error('[v-lazyload]: <image> element not found'); } }; const LazyLoad = { // 初始化 init(el, value) { el.setAttribute('data-src', value); el.setAttribute('src', globalOptions.src); }, // 利用IntersectionObserver监听el observe(el) { const io = new IntersectionObserver((entries) => { const realSrc = el.dataset.src; if (entries[0].isIntersecting) { if (realSrc) { el.src = realSrc; el.removeAttribute('data-src'); } } }); io.observe(el); }, // 监听scroll事件 listenerScroll(el) { const handler = LazyLoad.throttle(LazyLoad.load, globalOptions.delay); LazyLoad.load(el); window.addEventListener(globalOptions.scrollEvent, () => { handler(el); }); }, // 加载真实图片 load(el) { const windowHeight = document.documentElement.clientHeight; const elTop = el.getBoundingClientRect().top; const elBtm = el.getBoundingClientRect().bottom; if (elTop - windowHeight < 0 && elBtm > 0) { const realSrc = el.dataset.src; if (realSrc) { el.src = realSrc; el.removeAttribute('data-src'); } } }, // 节流 throttle(fn, delay) { let timer; let prevTime; return function (...args) { const currTime = Date.now(); const context = this; if (!prevTime) prevTime = currTime; clearTimeout(timer); if (currTime - prevTime > delay) { prevTime = currTime; fn.apply(context, args); clearTimeout(timer); return; } timer = setTimeout(function () { prevTime = Date.now(); timer = null; fn.apply(context, args); }, delay); }; } }; const vLazyLoad = { name: 'lazyload', definition: { beforeMount(el, { value }) { if (canRendering) { getImageElement(el, (imgEl) => { LazyLoad.init(imgEl, value); }); } }, mounted(el) { if (canRendering) { getImageElement(el, (imgEl) => IntersectionObserver ? LazyLoad.observe(imgEl) : LazyLoad.listenerScroll(imgEl) ); } } } }; function install(app, options = {}) { globalOptions = Object.assign({}, DEFAULT_OPTIONS, options); app.directive(vLazyLoad.name, vLazyLoad.definition); } const $lazyload = { install }; export default $lazyload; export { install };