forked from hilongjw/vue-lazyload
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vue-lazyload.js
6 lines (6 loc) · 17.7 KB
/
vue-lazyload.js
1
2
3
4
5
6
/*!
* Vue-Lazyload.js v1.3.4
* (c) 2022 Awe <[email protected]>
* Released under the MIT License.
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).VueLazyload={})}(this,(function(t){"use strict";function e(t,e){return t(e={exports:{}},e.exports),e.exports}var i=e((function(t){const e=Object.prototype.toString,i=Object.prototype.propertyIsEnumerable,r=Object.getOwnPropertySymbols;t.exports=(t,...s)=>{if("function"!=typeof(n=t)&&"[object Object]"!==e.call(n)&&!Array.isArray(n))throw new TypeError("expected the first argument to be an object");var n;if(0===s.length||"function"!=typeof Symbol||"function"!=typeof r)return t;for(let e of s){let s=r(e);for(let r of s)i.call(e,r)&&(t[r]=e[r])}return t}})),r=Object.freeze({__proto__:null,default:i,__moduleExports:i}),s=r&&i||r,n=e((function(t){const e=Object.prototype.toString,i=t=>"__proto__"!==t&&"constructor"!==t&&"prototype"!==t,r=t.exports=(t,...e)=>{let o=0;var a;for(("object"==typeof(a=t)?null===a:"function"!=typeof a)&&(t=e[o++]),t||(t={});o<e.length;o++)if(n(e[o])){for(const s of Object.keys(e[o]))i(s)&&(n(t[s])&&n(e[o][s])?r(t[s],e[o][s]):t[s]=e[o][s]);s(t,e[o])}return t};function n(t){return"function"==typeof t||"[object Object]"===e.call(t)}}));const o="undefined"!=typeof window&&null!==window,a=function(){if(o&&"IntersectionObserver"in window&&"IntersectionObserverEntry"in window&&"intersectionRatio"in window.IntersectionObserverEntry.prototype)return"isIntersecting"in window.IntersectionObserverEntry.prototype||Object.defineProperty(window.IntersectionObserverEntry.prototype,"isIntersecting",{get:function(){return this.intersectionRatio>0}}),!0;return!1}();const d="event",l="observer",h=function(){if(o)return"function"==typeof window.CustomEvent?window.CustomEvent:(t.prototype=window.Event.prototype,t);function t(t,e){e=e||{bubbles:!1,cancelable:!1,detail:void 0};var i=document.createEvent("CustomEvent");return i.initCustomEvent(t,e.bubbles,e.cancelable,e.detail),i}}();function c(t,e){if(!t.length)return;const i=t.indexOf(e);return i>-1?t.splice(i,1):void 0}function u(t,e){if("IMG"!==t.tagName||!t.getAttribute("data-srcset"))return;let i=t.getAttribute("data-srcset");const r=[],s=t.parentNode.offsetWidth*e;let n,o,a;i=i.trim().split(","),i.map((t=>{t=t.trim(),n=t.lastIndexOf(" "),-1===n?(o=t,a=999998):(o=t.substr(0,n),a=parseInt(t.substr(n+1,t.length-n-2),10)),r.push([a,o])})),r.sort((function(t,e){if(t[0]<e[0])return 1;if(t[0]>e[0])return-1;if(t[0]===e[0]){if(-1!==e[1].indexOf(".webp",e[1].length-5))return 1;if(-1!==t[1].indexOf(".webp",t[1].length-5))return-1}return 0}));let d,l="";for(let t=0;t<r.length;t++){d=r[t],l=d[1];const e=r[t+1];if(e&&e[0]<s){l=d[1];break}if(!e){l=d[1];break}}return l}function p(t,e){let i;for(let r=0,s=t.length;r<s;r++)if(e(t[r])){i=t[r];break}return i}const f=(t=1)=>o&&window.devicePixelRatio||t;function g(){if(!o)return!1;let t=!0;try{const e=document.createElement("canvas");e.getContext&&e.getContext("2d")&&(t=0===e.toDataURL("image/webp").indexOf("data:image/webp"))}catch(e){t=!1}return t}const b=function(){if(!o)return;let t=!1;try{let e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("test",null,e)}catch(t){}return t}(),m={on(t,e,i,r=!1){b?t.addEventListener(e,i,{capture:r,passive:!0}):t.addEventListener(e,i,r)},off(t,e,i,r=!1){t.removeEventListener(e,i,r)}},v=(t,e,i)=>{const r=t.el.attributes;let s=new Image;if(!t||!t.src){const t=new Error("image src is required");return i(t)}for(let t=0;t<r.length;t++)["id","class","src"].includes(r[t].name)||s.setAttribute(r[t].name,r[t].value);s.src=t.src,t.cors&&(s.crossOrigin=t.cors),s.onload=function(){e({naturalHeight:s.naturalHeight,naturalWidth:s.naturalWidth,src:s.src})},s.onerror=function(t){i(t)}},y=(t,e)=>"undefined"!=typeof getComputedStyle?getComputedStyle(t,null).getPropertyValue(e):t.style[e],w=t=>y(t,"overflow")+y(t,"overflow-y")+y(t,"overflow-x");function L(){}class _{constructor({max:t}){this.options={max:t||100},this._caches=[]}has(t){return this._caches.indexOf(t)>-1}add(t){this.has(t)||(this._caches.push(t),this._caches.length>this.options.max&&this.free())}free(){this._caches.shift()}}class z{constructor({el:t,src:e,error:i,loading:r,bindType:s,$parent:n,options:o,cors:a,elRenderer:d,imageCache:l}){this.el=t,this.src=e,this.error=i,this.loading=r,this.bindType=s,this.attempt=0,this.cors=a,this.naturalHeight=0,this.naturalWidth=0,this.options=o,this.rect=null,this.$parent=n,this.elRenderer=d,this._imageCache=l,this.performanceData={init:Date.now(),loadStart:0,loadEnd:0},this.filter(),this.initState(),this.render("loading",!1)}initState(){"dataset"in this.el?this.el.dataset.src=this.src:this.el.setAttribute("data-src",this.src),this.state={loading:!1,error:!1,loaded:!1,rendered:!1}}record(t){this.performanceData[t]=Date.now()}update({src:t,loading:e,error:i}){const r=this.src;this.src=t,this.loading=e,this.error=i,this.filter(),r!==this.src&&(this.attempt=0,this.initState())}getRect(){this.rect=this.el.getBoundingClientRect()}checkInView(){return this.getRect(),this.rect.top<window.innerHeight*this.options.preLoad&&this.rect.bottom>this.options.preLoadTop&&this.rect.left<window.innerWidth*this.options.preLoad&&this.rect.right>0}filter(){(function(t){if(!(t instanceof Object))return[];if(Object.keys)return Object.keys(t);{let e=[];for(let i in t)t.hasOwnProperty(i)&&e.push(i);return e}})(this.options.filter).map((t=>{this.options.filter[t](this,this.options)}))}renderLoading(t){this.state.loading=!0,v({src:this.loading,cors:this.cors,el:this.el},(e=>{this.render("loading",!1),this.state.loading=!1,t()}),(()=>{t(),this.state.loading=!1,this.options.silent||console.warn(`VueLazyload log: load failed with loading image(${this.loading})`)}))}load(t=L){return this.attempt>this.options.attempt-1&&this.state.error?(this.options.silent||console.log(`VueLazyload log: ${this.src} tried too more than ${this.options.attempt} times`),void t()):this.state.rendered&&this.state.loaded?void 0:this._imageCache.has(this.src)?(this.state.loaded=!0,this.render("loaded",!0),this.state.rendered=!0,t()):void this.renderLoading((()=>{this.attempt++,this.options.adapter.beforeLoad&&this.options.adapter.beforeLoad(this,this.options),this.record("loadStart"),v({src:this.src,cors:this.cors,el:this.el},(e=>{this.naturalHeight=e.naturalHeight,this.naturalWidth=e.naturalWidth,this.state.loaded=!0,this.state.error=!1,this.record("loadEnd"),this.render("loaded",!1),this.state.rendered=!0,this._imageCache.add(this.src),t()}),(t=>{!this.options.silent&&console.error(t),this.state.error=!0,this.state.loaded=!1,this.render("error",!1)}))}))}render(t,e){this.elRenderer(this,t,e)}performance(){let t="loading",e=0;return this.state.loaded&&(t="loaded",e=(this.performanceData.loadEnd-this.performanceData.loadStart)/1e3),this.state.error&&(t="error"),{src:this.src,state:t,time:e}}$destroy(){this.el=null,this.src=null,this.error=null,this.loading=null,this.bindType=null,this.attempt=0}}const E="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",A=["scroll","wheel","mousewheel","resize","animationend","transitionend","touchmove"],x={rootMargin:"0px",threshold:0};function $(t){return class{constructor({preLoad:t,error:e,throttleWait:i,preLoadTop:r,dispatchEvent:s,loading:n,attempt:o,silent:a=!0,scale:h,listenEvents:c,hasbind:u,filter:p,adapter:b,observer:m,observerOptions:v}){this.version='"1.3.4"',this.mode=d,this.ListenerQueue=[],this.TargetIndex=0,this.TargetQueue=[],this.options={silent:a,dispatchEvent:!!s,throttleWait:i||200,preLoad:t||1.3,preLoadTop:r||0,error:e||E,loading:n||E,attempt:o||3,scale:h||f(h),ListenEvents:c||A,hasbind:!1,supportWebp:g(),filter:p||{},adapter:b||{},observer:!!m,observerOptions:v||x},this._initEvent(),this._imageCache=new _({max:200}),this.lazyLoadHandler=function(t,e){let i=null,r=null,s=0,n=!1;return function(){if(n=!0,i)return;let o=Date.now()-s,a=this,d=arguments,l=function(){s=Date.now(),i=!1,t.apply(a,d)};o>=e?l():i=setTimeout(l,e),n&&(clearTimeout(r),r=setTimeout(l,2*e))}}(this._lazyLoadHandler.bind(this),this.options.throttleWait),this.setMode(this.options.observer?l:d)}config(t={}){n(this.options,t)}performance(){let t=[];return this.ListenerQueue.map((e=>{t.push(e.performance())})),t}addLazyBox(t){this.ListenerQueue.push(t),o&&(this._addListenerTarget(window),this._observer&&this._observer.observe(t.el),t.$el&&t.$el.parentNode&&this._addListenerTarget(t.$el.parentNode))}add(e,i,r){if(function(t,e){let i=!1;for(let r=0,s=t.length;r<s;r++)if(e(t[r])){i=!0;break}return i}(this.ListenerQueue,(t=>t.el===e)))return this.update(e,i),t.nextTick(this.lazyLoadHandler);let{src:s,loading:n,error:a,cors:d}=this._valueFormatter(i.value);t.nextTick((()=>{s=u(e,this.options.scale)||s,this._observer&&this._observer.observe(e);const l=Object.keys(i.modifiers)[0];let h;l&&(h=r.context.$refs[l],h=h?h.$el||h:document.getElementById(l)),h||(h=(t=>{if(!o)return;if(!(t instanceof HTMLElement))return window;let e=t;for(;e&&e!==document.body&&e!==document.documentElement&&e.parentNode;){if(/(scroll|auto)/.test(w(e)))return e;e=e.parentNode}return window})(e));const c=new z({bindType:i.arg,$parent:h,el:e,loading:n,error:a,src:s,cors:d,elRenderer:this._elRenderer.bind(this),options:this.options,imageCache:this._imageCache});this.ListenerQueue.push(c),o&&(this._addListenerTarget(window),this._addListenerTarget(h)),this.lazyLoadHandler(),t.nextTick((()=>this.lazyLoadHandler()))}))}update(e,i,r){let{src:s,loading:n,error:o}=this._valueFormatter(i.value);s=u(e,this.options.scale)||s;const a=p(this.ListenerQueue,(t=>t.el===e));a?a.update({src:s,loading:n,error:o}):this.add(e,i,r),this._observer&&(this._observer.unobserve(e),this._observer.observe(e)),this.lazyLoadHandler(),t.nextTick((()=>this.lazyLoadHandler()))}remove(t){if(!t)return;this._observer&&this._observer.unobserve(t);const e=p(this.ListenerQueue,(e=>e.el===t));e&&(this._removeListenerTarget(e.$parent),this._removeListenerTarget(window),c(this.ListenerQueue,e),e.$destroy())}removeComponent(t){t&&(c(this.ListenerQueue,t),this._observer&&this._observer.unobserve(t.el),t.$parent&&t.$el.parentNode&&this._removeListenerTarget(t.$el.parentNode),this._removeListenerTarget(window))}setMode(t){a||t!==l||(t=d),this.mode=t,t===d?(this._observer&&(this.ListenerQueue.forEach((t=>{this._observer.unobserve(t.el)})),this._observer=null),this.TargetQueue.forEach((t=>{this._initListen(t.el,!0)}))):(this.TargetQueue.forEach((t=>{this._initListen(t.el,!1)})),this._initIntersectionObserver())}_addListenerTarget(t){if(!t)return;let e=p(this.TargetQueue,(e=>e.el===t));return e?e.childrenCount++:(e={el:t,id:++this.TargetIndex,childrenCount:1,listened:!0},this.mode===d&&this._initListen(e.el,!0),this.TargetQueue.push(e)),this.TargetIndex}_removeListenerTarget(t){this.TargetQueue.forEach(((e,i)=>{e.el===t&&(e.childrenCount--,e.childrenCount||(this._initListen(e.el,!1),this.TargetQueue.splice(i,1),e=null))}))}_initListen(t,e){this.options.ListenEvents.forEach((i=>m[e?"on":"off"](t,i,this.lazyLoadHandler)))}_initEvent(){this.Event={listeners:{loading:[],loaded:[],error:[]}},this.$on=(t,e)=>{this.Event.listeners[t]||(this.Event.listeners[t]=[]),this.Event.listeners[t].push(e)},this.$once=(t,e)=>{const i=this;this.$on(t,(function r(){i.$off(t,r),e.apply(i,arguments)}))},this.$off=(t,e)=>{if(e)c(this.Event.listeners[t],e);else{if(!this.Event.listeners[t])return;this.Event.listeners[t].length=0}},this.$emit=(t,e,i)=>{this.Event.listeners[t]&&this.Event.listeners[t].forEach((t=>t(e,i)))}}_lazyLoadHandler(){const t=[];this.ListenerQueue.forEach(((e,i)=>{e.el&&e.el.parentNode||t.push(e);e.checkInView()&&e.load()})),t.forEach((t=>{c(this.ListenerQueue,t),t.$destroy()}))}_initIntersectionObserver(){a&&(this._observer=new IntersectionObserver(this._observerHandler.bind(this),this.options.observerOptions),this.ListenerQueue.length&&this.ListenerQueue.forEach((t=>{this._observer.observe(t.el)})))}_observerHandler(t,e){t.forEach((t=>{t.isIntersecting&&this.ListenerQueue.forEach((e=>{if(e.el===t.target){if(e.state.loaded)return this._observer.unobserve(e.el);e.load()}}))}))}_elRenderer(t,e,i){if(!t.el)return;const{el:r,bindType:s}=t;let n;switch(e){case"loading":n=t.loading;break;case"error":n=t.error;break;default:n=t.src}if(s?r.style[s]='url("'+n+'")':r.getAttribute("src")!==n&&r.setAttribute("src",n),r.setAttribute("lazy",e),this.$emit(e,t,i),this.options.adapter[e]&&this.options.adapter[e](t,this.options),this.options.dispatchEvent){const i=new h(e,{detail:t});r.dispatchEvent(i)}}_valueFormatter(t){let e=t,i=this.options.loading,r=this.options.error;var s;return null!==(s=t)&&"object"==typeof s&&(t.src||this.options.silent||console.error("Vue Lazyload warning: miss src with "+t),e=t.src,i=t.loading||this.options.loading,r=t.error||this.options.error),{src:e,loading:i,error:r}}}}$.install=(t,e={})=>{const i=new($(t))(e);"2"===t.version.split(".")[0]?t.directive("lazy",{bind:i.add.bind(i),update:i.update.bind(i),componentUpdated:i.lazyLoadHandler.bind(i),unbind:i.remove.bind(i)}):t.directive("lazy",{bind:i.lazyLoadHandler.bind(i),update(t,e){n(this.vm.$refs,this.vm.$els),i.add(this.el,{modifiers:this.modifiers||{},arg:this.arg,value:t,oldValue:e},{context:this.vm})},unbind(){i.remove(this.el)}})};const T=t=>({props:{tag:{type:String,default:"div"}},render(t){return t(this.tag,null,this.show?this.$slots.default:null)},data:()=>({el:null,state:{loaded:!1},rect:{},show:!1}),mounted(){this.el=this.$el,t.addLazyBox(this),t.lazyLoadHandler()},beforeDestroy(){t.removeComponent(this)},methods:{getRect(){this.rect=this.$el.getBoundingClientRect()},checkInView(){return this.getRect(),o&&this.rect.top<window.innerHeight*t.options.preLoad&&this.rect.bottom>0&&this.rect.left<window.innerWidth*t.options.preLoad&&this.rect.right>0},load(){this.show=!0,this.state.loaded=!0,this.$emit("show",this)},destroy(){return this.$destroy}}});T.install=function(t,e={}){const i=new($(t))(e);t.component("lazy-component",T(i))};class O{constructor({lazy:t}){this.lazy=t,t.lazyContainerMananger=this,this._queue=[]}bind(t,e,i){const r=new C({el:t,binding:e,vnode:i,lazy:this.lazy});this._queue.push(r)}update(t,e,i){const r=p(this._queue,(e=>e.el===t));r&&r.update({el:t,binding:e,vnode:i})}unbind(t,e,i){const r=p(this._queue,(e=>e.el===t));r&&(r.clear(),c(this._queue,r))}}const I={selector:"img"};class C{constructor({el:t,binding:e,vnode:i,lazy:r}){this.el=null,this.vnode=i,this.binding=e,this.options={},this.lazy=r,this._queue=[],this.update({el:t,binding:e})}update({el:t,binding:e}){this.el=t,this.options=n({},I,e.value);this.getImgs().forEach((t=>{this.lazy.add(t,n({},this.binding,{value:{src:"dataset"in t?t.dataset.src:t.getAttribute("data-src"),error:("dataset"in t?t.dataset.error:t.getAttribute("data-error"))||this.options.error,loading:("dataset"in t?t.dataset.loading:t.getAttribute("data-loading"))||this.options.loading}}),this.vnode)}))}getImgs(){return function(t){let e=t.length;const i=[];for(let r=0;r<e;r++)i.push(t[r]);return i}(this.el.querySelectorAll(this.options.selector))}clear(){this.getImgs().forEach((t=>this.lazy.remove(t))),this.vnode=null,this.binding=null,this.lazy=null}}C.install=(t,e={})=>{const i=new($(t))(e),r=new C({lazy:i});"2"===t.version.split(".")[0]?t.directive("lazy-container",{bind:r.bind.bind(r),componentUpdated:r.update.bind(r),unbind:r.unbind.bind(r)}):t.directive("lazy-container",{update(t,e){r.update(this.el,{modifiers:this.modifiers||{},arg:this.arg,value:t,oldValue:e},{context:this.vm})},unbind(){r.unbind(this.el)}})};const H=t=>({props:{src:[String,Object],tag:{type:String,default:"img"}},render(t){return t(this.tag,{attrs:{src:this.renderSrc}},this.$slots.default)},data:()=>({el:null,options:{src:"",error:"",loading:"",attempt:t.options.attempt},state:{loaded:!1,error:!1,attempt:0},rect:{},renderSrc:""}),watch:{src(){this.init(),t.addLazyBox(this),t.lazyLoadHandler()}},created(){this.init(),this.renderSrc=this.options.loading},mounted(){this.el=this.$el,t.addLazyBox(this),t.lazyLoadHandler()},beforeDestroy(){t.removeComponent(this)},methods:{init(){const{src:e,loading:i,error:r}=t._valueFormatter(this.src);this.state.loaded=!1,this.options.src=e,this.options.error=r,this.options.loading=i,this.renderSrc=this.options.loading},getRect(){this.rect=this.$el.getBoundingClientRect()},checkInView(){return this.getRect(),o&&this.rect.top<window.innerHeight*t.options.preLoad&&this.rect.bottom>0&&this.rect.left<window.innerWidth*t.options.preLoad&&this.rect.right>0},load(e=L){if(this.state.attempt>this.options.attempt-1&&this.state.error)return t.options.silent||console.log(`VueLazyload log: ${this.options.src} tried too more than ${this.options.attempt} times`),void e();const i=this.options.src;v({src:i,el:this.$el},(({src:t})=>{this.renderSrc=t,this.state.loaded=!0}),(t=>{this.state.attempt++,this.renderSrc=this.options.error,this.state.error=!0}))}}});H.install=(t,e={})=>{const i=new($(t))(e);t.component("lazy-image",H(i))};var Q={install(t,e={}){const i=new($(t))(e),r=new O({lazy:i}),s="2"===t.version.split(".")[0];t.prototype.$Lazyload=i,e.lazyComponent&&t.component("lazy-component",T(i)),e.lazyImage&&t.component("lazy-image",H(i)),s?(t.directive("lazy",{bind:i.add.bind(i),update:i.update.bind(i),componentUpdated:i.lazyLoadHandler.bind(i),unbind:i.remove.bind(i)}),t.directive("lazy-container",{bind:r.bind.bind(r),componentUpdated:r.update.bind(r),unbind:r.unbind.bind(r)})):(t.directive("lazy",{bind:i.lazyLoadHandler.bind(i),update(t,e){n(this.vm.$refs,this.vm.$els),i.add(this.el,{modifiers:this.modifiers||{},arg:this.arg,value:t,oldValue:e},{context:this.vm})},unbind(){i.remove(this.el)}}),t.directive("lazy-container",{update(t,e){r.update(this.el,{modifiers:this.modifiers||{},arg:this.arg,value:t,oldValue:e},{context:this.vm})},unbind(){r.unbind(this.el)}}))}};t.Lazy=$,t.LazyComponent=T,t.LazyContainer=O,t.LazyImage=H,t.default=Q,Object.defineProperty(t,"__esModule",{value:!0})}));