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 相关文章推荐
Mozilla中显示textarea中选择的文字
Sep 07 Javascript
JQueryEasyUI Layout布局框架的使用
Apr 08 Javascript
Jquery实现自定义窗口随意的拖拽
Mar 12 Javascript
Node.js返回JSONP详解
May 18 Javascript
jQuery插件 Jqplot图表实例
Jun 18 Javascript
Bootstrap CSS组件之下拉菜单(dropdown)
Dec 17 Javascript
关于使用js算总价的问题
Jun 23 Javascript
关于javascript sort()排序你可能忽略的一点理解
Jul 18 Javascript
JS+Canvas绘制动态时钟效果
Nov 10 Javascript
promise和co搭配生成器函数方式解决js代码异步流程的比较
May 25 Javascript
JS/jQuery实现超简单的Table表格添加,删除行功能示例
Jul 31 jQuery
Vue实现将数据库中带html标签的内容输出(原始HTML(Raw HTML))
Oct 28 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
是否存在第一台收音机的说法
2021/03/01 无线电
zen cart新进商品的随机排序修改方法
2010/09/10 PHP
PHP文件读写操作之文件写入代码
2011/01/13 PHP
php可扩展的验证类实例(可对邮件、手机号、URL等验证)
2015/07/09 PHP
php基于SQLite实现的分页功能示例
2017/06/21 PHP
PHP获取数组中指定的一列实例
2017/12/27 PHP
PHP精确到毫秒秒杀倒计时实例详解
2019/03/14 PHP
PHP mkdir创建文件夹实现方法解析
2020/11/13 PHP
关于js datetime的那点事
2011/11/15 Javascript
js中根据字数截取字符串,不能截断url
2012/01/12 Javascript
浅析JQuery UI Dialog的样式设置问题
2013/12/18 Javascript
javascript中普通函数的使用介绍
2013/12/19 Javascript
js 左右悬浮对联广告特效代码
2014/12/12 Javascript
jQuery寻找n以内完全数的方法
2015/06/24 Javascript
浅谈Javascript中substr和substring的区别
2015/09/30 Javascript
深入理解bootstrap框架之入门准备
2016/10/09 Javascript
js使用ajax传值给后台,后台返回字符串处理方法
2018/08/08 Javascript
深入理解react 组件类型及使用场景
2019/03/07 Javascript
小程序瀑布流组件实现翻页与图片懒加载
2020/05/19 Javascript
vue设置全局访问接口API地址操作
2020/08/14 Javascript
详解Python编程中包的概念与管理
2015/10/16 Python
利用Python自带PIL库扩展图片大小给图片加文字描述的方法示例
2017/08/08 Python
python机器人行走步数问题的解决
2018/01/29 Python
python读出当前时间精度到秒的代码
2019/07/05 Python
Python3 chardet模块查看编码格式的例子
2019/08/14 Python
Python读写文件模式和文件对象方法实例详解
2019/09/17 Python
基于python实现FTP文件上传与下载操作(ftp&amp;sftp协议)
2020/04/01 Python
Anaconda使用IDLE的实现示例
2020/09/23 Python
YSL圣罗兰美妆美国官网:Yves Saint Lauret US
2016/11/21 全球购物
美国校园市场:OCM
2017/06/08 全球购物
日本最大级玩偶手办购物:あみあみ Amiami
2018/04/23 全球购物
Feelunique德国官方网站:欧洲最大的在线美容零售商
2019/07/20 全球购物
金融专业毕业生推荐信
2013/11/26 职场文书
人力管理专业毕业生求职信
2014/02/27 职场文书
2014校长四风问题对照检查材料思想汇报
2014/09/16 职场文书
个性发展自我评价2015
2015/03/09 职场文书