1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| const lazyLoad = { install(Vue, options) { const defaultSrc = options.default; Vue.directive('lazy', { bind(el, binding) { lazyLoad.init(el, binding.value, defaultSrc); }, inserted(el) { if (IntersectionObserver) { lazyLoad.observe(el); } else { lazyLoad.listenerScroll(el); } }, }); }, init(el, val, def) { el.setAttribute('data-src', val); el.setAttribute('src', def); }, 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); }, listenerScroll(el) { const handler = lazyLoad.throttle(lazyLoad.load, 300); lazyLoad.load(el); window.addEventListener('scroll', () => 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) { 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(() => { prevTime = Date.now(); clearTimeout(timer); timer = null; fn.apply(context, args); }, delay); }; }, }; export default lazyLoad;
|