Vue自定义图片懒加载指令v-lazyload详解

来源:互联网 发布:专业足球数据网站 编辑:程序博客网 时间:2024/06/08 02:42

Vue是可以自定义指令的,最近学习过程中遇见了一个需要图片懒加载的功能,最后参考了别人的代码和思路自己重新写了一遍。以下将详细介绍如何实现自定义指令v-lazyload。

先看如何使用这个指令:  

<img v-lazyload="imageSrc" >

imageSrc是要加载的图片的实际路径。

为了实现这个指令,我们首先单独建立一个文件,名字为lazyload.js.并填写基本的代码,如下:  

//Vue 图片懒加载,导出模块export default (Vue , options = {})=>{  //初始化的选项,default是未加载图片时显示的默认图片  var init = {     default: 'https://gw.alicdn.com/tps/i1/TB147JCLFXXXXc1XVXXxGsw1VXX-112-168.png'  }  //addListener为Vue指令的具体实现功能函数,我们这里为所有使用v-lazyload的指令的元素添加监听  //ele 是dom元素,binding是绑定的具体值,  //例如:<img v-lazyload="imageSrc" > ele是img binding是imageSrc  const addListenner = (ele,binding) =>{      }  //Vue自定义指令,lazyload为指令的名称  Vue.directive('lazyload',{    inserted:addListener,    updated:addListener  })}

inserted 和 updated为Vue指令的执行不同阶段提供的钩子函数,查看Vue的官网可以看到一共有5个阶段, 

指令定义函数提供了几个钩子函数(可选):

bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。

update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。

componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。

unbind: 只调用一次, 指令与元素解绑时调用。

这里我们只用inserted和updated就够了。

  接下来我们具体实现addListener的实现。我们的具体思路如下:

  1、先看看这个图片是否需要懒加载。有两种情况,一是图片还没到达可视区域,二是图片已经加载过了。

  2、然后监听窗口的scroll事件,判断哪些图片可以进行懒加载了。

  这里我们需要一个需要进行监听需要懒加载的图片列表和一个需要记录已经加载过得图片列表。另外为了方便数组的操作,我们加一个数组的remove方法。

继续我们的代码。

//Vue 图片懒加载export default (Vue , options = {})=>{    //数组item remove方法  if(!Array.prototype.remove){    Array.prototype.remove = function(item){      if(!this.length) return      var index = this.indexOf(item);      if( index > -1){        this.splice(index,1);        return this      }    }  }  var init = {       default: 'https://gw.alicdn.com/tps/i1/TB147JCLFXXXXc1XVXXxGsw1VXX-112-168.png'   }    //需要进行监听的图片列表,还没有加载过得   var listenList = [];  //已经加载过得图片缓存列表  var imageCatcheList = [];  //是否已经加载过了  const isAlredyLoad = (imageSrc) => {      }  //检测图片是否可以加载,如果可以则进行加载  const isCanShow = (item) =>{      };  //添加监听事件scroll  const onListenScroll = () =>{      }  //Vue 指令最终的方法  const addListener = (ele,binding) =>{    //绑定的图片地址    var imageSrc = binding.value;    //如果已经加载过,则无需重新加载,直接将src赋值    if(isAlredyLoad(imageSrc)){      ele.src = imageSrc;      return false;    }    var item = {      ele:ele,      src:imageSrc    }    //图片显示默认的图片    ele.src = init.default;    //再看看是否可以显示此图片    if(isCanShow(item)){      return    }    //否则将图片地址和元素均放入监听的lisenList里    listenList.push(item);        //然后开始监听页面scroll事件    onListenScroll();  }  Vue.directive('lazyload',{    inserted:addListener,    updated:addListener  })}

接下来就几个空方法的实现了。

isAlredyLoad ,判断是否已经加载过了这个图片

const isAlredyLoad = (imageSrc) => {    if(imageCatcheList.indexOf(imageSrc) > -1){      return true;    }else{      return false;    }  }

isCanShow 图片是否进入可视区域,如果已经进入则进行加载

//检测图片是否可以加载,如果可以则进行加载  const isCanShow = (item) =>{    var ele = item.ele;    var src = item.src;    //图片距离页面顶部的距离    var top = ele.getBoundingClientRect().top;    //页面可视区域的高度    var windowHeight = window.innerHight;    //top + 10 已经进入了可视区域10像素    if(top + 10 < window.innerHeight){      var image = new Image();      image.src = src;      image.onload = function(){        ele.src = src;        imageCatcheList.push(src);        listenList.remove(item);      }      return true;    }else{      return false;    }  };

onListenScroll监听滚动事件,并且检测是否进入可视区域。

const onListenScroll = () =>{    window.addEventListener('scroll',function(){      var length = listenList.length;      for(let i = 0;i<length;i++ ){        isCanShow(listenList[i]);      }    })  }

最终我们的代码如下:

//Vue 图片懒加载export default (Vue , options = {})=>{  if(!Array.prototype.remove){    Array.prototype.remove = function(item){      if(!this.length) return      var index = this.indexOf(item);      if( index > -1){        this.splice(index,1);        return this      }    }  }  var init = {    lazyLoad: false,    default: 'https://gw.alicdn.com/tps/i1/TB147JCLFXXXXc1XVXXxGsw1VXX-112-168.png'  }  var listenList = [];  var imageCatcheList = [];  const isAlredyLoad = (imageSrc) => {    if(imageCatcheList.indexOf(imageSrc) > -1){      return true;    }else{      return false;    }  }  //检测图片是否可以加载,如果可以则进行加载  const isCanShow = (item) =>{    var ele = item.ele;    var src = item.src;    //图片距离页面顶部的距离    var top = ele.getBoundingClientRect().top;    //页面可视区域的高度    var windowHeight = window.innerHight;    //top + 10 已经进入了可视区域10像素    if(top + 10 < window.innerHeight){      var image = new Image();      image.src = src;      image.onload = function(){        ele.src = src;        imageCatcheList.push(src);        listenList.remove(item);      }      return true;    }else{      return false;    }  };  const onListenScroll = () =>{    window.addEventListener('scroll',function(){      var length = listenList.length;      for(let i = 0;i<length;i++ ){        isCanShow(listenList[i]);      }    })  }  //Vue 指令最终的方法  const addListener = (ele,binding) =>{    //绑定的图片地址    var imageSrc = binding.value;    //如果已经加载过,则无需重新加载,直接将src赋值    if(isAlredyLoad(imageSrc)){      ele.src = imageSrc;      return false;    }    var item = {      ele:ele,      src:imageSrc    }    //图片显示默认的图片    ele.src = init.default;    //再看看是否可以显示此图片    if(isCanShow(item)){      return    }    //否则将图片地址和元素均放入监听的lisenList里    listenList.push(item);        //然后开始监听页面scroll事件    onListenScroll();  }  Vue.directive('lazyload',{    inserted:addListener,    updated:addListener  })}

使用时需要在主文件中引入这个文件,并且vue.use();

import LazyLoad from 'lazyLoad.js'Vue.use(LazyLoad);

并且在需要懒加载的图片上均按照如下使用v-lazyload指令即可

<img v-lazyload="imageSrc" >

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 新生儿几个月可以竖着抱 婴儿几个月可以竖着抱 婴儿什么时候可以竖着抱 婴儿什么时候可以竖抱 新生儿几个月可以竖抱 宝宝三个月可以竖着抱吗 小孩几个月可以竖着抱 宝宝什么时候可以竖着抱 宝宝什么时候可以竖抱 孩子几个月可以竖着抱 小孩几个月可以竖抱 孩子几个月可以竖抱 宝宝几个月才能竖着抱 三个月的宝宝可以竖着抱吗 两个多月的宝宝可以竖着抱吗 宝宝什么时候能竖着抱 两个月的宝宝可以竖着抱吗 几个月的宝宝可以竖着抱 几个月婴儿可以竖着抱 婴儿三个月可以竖抱吗 2个月的宝宝可以竖着抱吗 小宝宝几个月可以竖着抱 婴儿两个月可以竖抱吗 婴幼儿几个月可以竖着抱 一个月的宝宝可以竖着抱吗 多大的婴儿可以竖着抱 二个月的宝宝可以竖着抱吗 几个月的宝宝可以竖抱 多大的宝宝可以竖着抱 3个月的宝宝可以竖着抱吗 新生儿多大可以竖着抱 宝宝两个月可以竖着抱吗 两个月宝宝喜欢竖着抱 三个月的婴儿可以竖着抱吗 2个多月的宝宝可以竖着抱吗 新生儿多久可以竖着抱 竖撇的字 一撇一竖是什么字 竖撇的写法图片 竖撇的写法 上面一个二下边一撇一竖