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 相关文章推荐
phpwind放自动注册方法
Dec 02 Javascript
找出字符串中出现次数最多的字母和出现次数精简版
Nov 07 Javascript
Jquery刷新页面背景图片随机变换的实现方法
Mar 15 Javascript
window.open()详解及浏览器兼容性问题示例探讨
May 29 Javascript
干货分享:让你分分钟学会javascript闭包
Dec 25 Javascript
理解JavaScript事件对象
Jan 25 Javascript
Js获取图片原始宽高的实现代码
May 17 Javascript
vue2.0 常用的 UI 库实例讲解
Dec 12 Javascript
JavaScript实现写入文件到本地的方法【基于FileSaver.js插件】
Mar 15 Javascript
jQuery实现中奖播报功能(让文本滚动起来) 简单设置数值即可
Mar 20 jQuery
基于vue实现探探滑动组件功能
May 29 Javascript
Vue 中使用lodash对事件进行防抖和节流操作
Jul 26 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读写文件的方法(生成HTML)
2006/11/27 PHP
解析smarty模板中类似for的功能实现
2013/06/18 PHP
PHP函数eval()介绍和使用示例
2014/08/20 PHP
php微信公众账号开发之前五个坑(一)
2016/09/18 PHP
PHP编程实现微信企业向用户付款的方法示例
2017/07/26 PHP
laravel框架创建授权策略实例分析
2019/11/22 PHP
防止jQuery ajax Load使用缓存的方法小结
2014/02/22 Javascript
jQuery使用post方法提交数据实例
2015/03/25 Javascript
jquery validate和jquery form 插件组合实现验证表单后AJAX提交
2015/08/26 Javascript
JS右下角广告窗口代码(可收缩、展开及关闭)
2015/09/04 Javascript
jQuery.uploadify文件上传组件实例讲解
2016/09/23 Javascript
Bootstrap在线电子商务网站实战项目5
2016/10/14 Javascript
bootstrap监听滚动实现头部跟随滚动
2016/11/08 Javascript
js拖拽功能实现代码解析
2016/11/28 Javascript
Node.js Mongodb 密码特殊字符 @的解决方法
2017/04/11 Javascript
详解vue-router 2.0 常用基础知识点之router.push()
2017/05/10 Javascript
Angular中封装fancyBox(图片预览)遇到问题小结
2017/09/01 Javascript
浅谈Vue内置component组件的应用场景
2018/03/27 Javascript
小程序实现左滑删除功能
2018/10/30 Javascript
python socket 超时设置 errno 10054
2014/07/01 Python
python将文本转换成图片输出的方法
2015/04/28 Python
Python的Flask框架中SQLAlchemy使用时的乱码问题解决
2015/11/07 Python
python如何通过实例方法名字调用方法
2018/03/21 Python
python aiohttp的使用详解
2019/06/20 Python
pandas取出重复数据的方法
2019/07/04 Python
python利用wx实现界面按钮和按钮监听和字体改变的方法
2019/07/17 Python
python numpy 反转 reverse示例
2019/12/04 Python
CSS3实现超慢速移动动画效果非常流畅无卡顿
2014/06/15 HTML / CSS
英国家庭珠宝商:T. H. Baker
2018/02/08 全球购物
美国温暖商店:The Warming Store
2018/12/15 全球购物
社区活动策划方案
2014/08/21 职场文书
学校机关党总支领导班子整改工作方案
2014/10/26 职场文书
车间安全生产管理制度
2015/08/06 职场文书
原来闭幕词是这样写的呀!
2019/07/01 职场文书
JavaScript实现简单拖拽效果
2021/09/15 Javascript
Java 实战项目之家居购物商城系统详解流程
2021/11/11 Java/Android