撸一个图片懒加载指令v-lazy__Vue.js
发布于 3 年前 作者 banyungong 1636 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

懒加载定义

图片懒加载其实就是延迟加载。也就是不用一次性加载所有的图片,等到用户需要某张图片的时候再加载,这样可以避免在同一时间请求大量的数据。也就是当图片滚动到可视区域的时候再去加载图片。

指令

Vue中除了平时常用的v-show、v-bind等指令外,还可以自定义指令。由于自定义指令过于简单,这里只是大致说一下用得到的钩子函数的作用。

bind:只调用一次,指令绑定到元素时调用,可以用来初始化。

inserted:被绑定的元素插入到父节点时调用。

实现

在component文件夹中新建LazyLoad文件夹,在文件夹里新建index.js。

代码如下:

const LazyLoad = {
// install方法
install(Vue,options){
	  // 代替图片的loading图
    let defaultSrc = options.default;
    Vue.directive('lazy',{
        bind(el,binding){
            LazyLoad.init(el,binding.value,defaultSrc);
        },
        inserted(el){
            // 兼容处理
            if('IntersectionObserver' in window){
                LazyLoad.observe(el);
            }else{
                LazyLoad.listenerScroll(el);
            }
            
        },
    })
},
// 初始化
init(el,val,def){
    // data-src 储存真实src
    el.setAttribute('data-src',val);
    // 设置src为loading图
    el.setAttribute('src',def);
},
// 利用IntersectionObserver监听el
observe(el){
    let io = new IntersectionObserver(entries => {
        let realSrc = el.dataset.src;
        if(entries[0].isIntersecting){
            if(realSrc){
                el.src = realSrc;
                el.removeAttribute('data-src');
            }
        }
    });
    io.observe(el);
},
// 监听scroll事件
listenerScroll(el){
    let handler = LazyLoad.throttle(LazyLoad.load,300);
    LazyLoad.load(el);
    window.addEventListener('scroll',() => {
        handler(el);
    });
},
// 加载真实图片
load(el){
    let windowHeight = document.documentElement.clientHeight
    let elTop = el.getBoundingClientRect().top;
    let elBtm = el.getBoundingClientRect().bottom;
    let realSrc = el.dataset.src;
    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){
        let currTime = Date.now();
        let 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);
    }
}
}

export default LazyLoad;

使用

在main.js里添加

import LazyLoad from './components/LazyLoad';

Vue.use(LazyLoad,{
    default:'https://tva1.sinaimg.cn/large/007S8ZIlgy1gfyof9vr4mj3044032dfl.jpg'
});

在组件中使用

<img v-lazy="https://tva1.sinaimg.cn/large/007S8ZIlgy1gfynwi1sejj30ij0nrdx0.jpg" />

最终效果

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: Special同志77964 原文链接:https://juejin.im/post/6844904198933315592

回到顶部