Vue实现一个图片懒加载插件


Posted in Javascript onMarch 11, 2019

前言

图片懒加载是一个很常用的功能,特别是一些电商平台,这对性能优化至关重要。今天就用vue来实现一个图片懒加载的插件。 这篇博客采用“三步走”战略——Vue.use()、Vue.direction、Vue图片懒加载插件实现,逐步实现一个Vue的图片懒加载插件。

Vue.use()

就像开发jQuery插件要用$.fn.extent()一样,开发Vue插件我们要用Vue.use()。其实就是官方内部实现的一个方法,供广大开发者灵活开发属于自己的插件。只需要按照约定好的规则开发就行。

用法

安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。

该方法需要在调用 new Vue() 之前被调用。

当 install 方法被同一个插件多次调用,插件将只会被安装一次。

注:install方法或者被当做install方法的方法它的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象。

参考链接:

  • https://cn.vuejs.org/v2/api/#Vue-use
  • https://3water.com/article/146461.htm 

Vue.direction自定义指令

用法——全局注册和局部注册

全局注册

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
 // 当被绑定的元素插入到 DOM 中时……
 inserted: function (el) {
 // 聚焦元素
 el.focus()
 }
})

局部注册

directives: {
 focus: {
 // 指令的定义
 inserted: function (el) {
 el.focus()
 }
 }
}

钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

钩子函数的参数

  • el:指令所绑定的元素,可以用来直接操作 DOM 。
  • binding:一个对象,包含以下属性:
  • name:指令名,不包括 v- 前缀。
  • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
  • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
  • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
  • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
  • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
  • vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

参考链接:https://cn.vuejs.org/v2/guide/custom-directive.html

Vue图片懒加载插件实现

思路:事先提供俩个空数组listenList(收集未加载的图片元素和资源)和imageCacheList(收集已加载的图片资源)。然后,判断图片是否到达可视区,如果到达,则用Image对象去加载资源图片,加载完毕后赋值给绑定元素的src让其显示。同时,将加载过的资源放入imageCacheList数组,用isAlredyLoad方法做个判断,防止之后相同的资源重复加载。如果没到达,则将元素和资源对象放到listenList数组,最后进行滚动监听。监听listenList数组中的元素是否可以加载资源。

插件的实现:

// 引入Vue构造函数
import Vue from 'vue'

var lazyload = {
 // Vue.use() 默认加载install,并且将Vue当做第一个参数传递过来
 install(vue,payload) {
 // 数组扩展移除元素
 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 defaultImage = payload.defaultImage || 'https://gw.alicdn.com/tps/i1/TB147JCLFXXXXc1XVXXxGsw1VXX-112-168.png';
 var errorImage = payload.errorImage || 'https://gw.alicdn.com/tps/i1/TB147JCLFXXXXc1XVXXxGsw1VXX-112-168.png';
 // 默认离可视区10px时加载图片
 var distanece = payload.scrollDistance || 10;
 // 收集未加载的图片元素和资源
 var listenList = [];
 // 收集已加载的图片元素和资源
 var imageCacheList = [];

 // 是否已经加载完成的图片
 const isAlredyLoad = (imageSrc) => {
 if(imageCacheList.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 - distance 距离可视区域还有distance像素
 if(top - distanece < window.innerHeight){ 
 var image = new Image();
 image.src = src;
 image.onload = function() {
 ele.src = src;
 imageCacheList.push(src);
 listenList.remove(item);
 }
 image.onerror = function() {
 ele.src = errorImage;
 imageCacheList.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 = defaultImage;

 //再看看是否可以显示此图片
 if(isCanShow(item)){
 return
 }

 //否则将图片地址和元素均放入监听的lisenList里
 listenList.push(item);
 
 //然后开始监听页面scroll事件
 onListenScroll();
 }

 Vue.directive('lazyload',{
 inserted: addListener,
 updated: addListener
 })
 }
}

export default lazyload;

插件的调用:

import Vue from 'vue'
import App from './App'
import router from './router'
import Lazyload from './common/js/lazyload'

// 参数均为可选
Vue.use(Lazyload,{
 scrollDistance: 15, // 距离可视区还有15px时开发加载资源
 defaultImage: '', // 资源图片未加载前的默认图片(绝对路径)
 errorImage:'' // 资源图片加载失败时要加载的资源(绝对路径)
})

参考链接:https://3water.com/article/112355.htm

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
一行代码告别document.getElementById
Jun 01 Javascript
js中 关于undefined和null的区别介绍
Apr 16 Javascript
JS获得QQ号码的昵称,头像,生日的简单实例
Dec 04 Javascript
JQuery实现的购物车功能(可以减少或者添加商品并自动计算价格)
Jan 13 Javascript
详解JavaScript数组的操作大全
Oct 19 Javascript
javascript实现抽奖程序的简单实例
Jun 07 Javascript
基于Bootstrap的Metronic框架实现页面链接收藏夹功能
Aug 29 Javascript
Vue组件开发技巧总结
Mar 04 Javascript
详解如何用typescript开发koa2的二三事
Nov 13 Javascript
js使用文档就绪函数动态改变页面内容示例【innerHTML、innerText】
Nov 07 Javascript
vue props对象validator自定义函数实例
Nov 13 Javascript
解决pycharm双击但是无法打开的情况
Oct 31 Javascript
使用Jenkins部署React项目的方法步骤
Mar 11 #Javascript
vue基础之v-bind属性、class和style用法分析
Mar 11 #Javascript
配置eslint规范项目代码风格
Mar 11 #Javascript
vue基础之事件简写、事件对象、冒泡、默认行为、键盘事件实例分析
Mar 11 #Javascript
vue基础之事件v-onclick=&quot;函数&quot;用法示例
Mar 11 #Javascript
每天学点Vue源码之vm.$mount挂载函数
Mar 11 #Javascript
JavaScript中常用的简洁高级技巧总结
Mar 10 #Javascript
You might like
PHP文件上传判断file是否己选择上传文件的方法
2014/11/10 PHP
PHP中的Streams详细介绍
2014/11/12 PHP
php表单加入Token防止重复提交的方法分析
2016/10/10 PHP
php实现的SSO单点登录系统接入功能示例分析
2016/10/12 PHP
jQuery 剧场版 你必须知道的javascript
2009/05/27 Javascript
extjs tabpanel限制选项卡数量实现思路及代码
2013/04/02 Javascript
jquery 实现密码框的显示与隐藏示例代码
2013/09/18 Javascript
jQuery如何实现点击页面获得当前点击元素的id或其他信息
2014/01/09 Javascript
jQuery的:parent选择器定义和用法
2014/07/01 Javascript
js数组依据下标删除元素
2015/04/14 Javascript
jQuery实现带延迟效果的滑动菜单代码
2015/09/02 Javascript
JavaScript代码性能优化总结篇
2016/05/15 Javascript
bootstrap Validator 模态框、jsp、表单验证 Ajax提交功能
2017/02/17 Javascript
Angularjs使用指令做表单校验的方法
2017/03/31 Javascript
Node.JS 循环递归复制文件夹目录及其子文件夹下的所有文件
2017/09/18 Javascript
详解node nvm进行node多版本管理
2017/10/21 Javascript
Vue 创建组件的两种方法小结(必看)
2018/02/23 Javascript
Vue组件的使用及个人理解与介绍
2019/02/09 Javascript
Vue Autocomplete 自动完成功能简单示例
2019/05/25 Javascript
javascript 内存模型实例详解
2020/04/18 Javascript
浅谈使用nodejs搭建web服务器的过程
2020/07/20 NodeJs
[01:43]深扒TI7聊天轮盘语音出处4
2017/05/11 DOTA
python元组操作实例解析
2014/09/23 Python
Python实现好友全头像的拼接实例(推荐)
2017/06/24 Python
Python使用Scrapy爬虫框架全站爬取图片并保存本地的实现代码
2018/03/04 Python
python2 与 python3 实现共存的方法
2018/07/12 Python
Pytorch学习之torch用法----比较操作(Comparison Ops)
2020/06/28 Python
python3将变量输入的简单实例
2020/08/19 Python
利用python+request通过接口实现人员通行记录上传功能
2021/01/13 Python
HTML5引入的新数组TypedArray介绍
2012/12/24 HTML / CSS
ASOS西班牙官网:英国在线时尚和美容零售商
2020/01/10 全球购物
澳大利亚家居用品零售商:Harris Scarfe
2020/10/10 全球购物
影子教师研修方案
2014/06/14 职场文书
艺术学院毕业生自荐信
2014/07/05 职场文书
2019个人工作态度自我评价
2019/04/24 职场文书
加薪申请书应该这样写!
2019/07/04 职场文书