700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Vue 图片懒加载 之 Vue-Lazyload

Vue 图片懒加载 之 Vue-Lazyload

时间:2024-04-13 02:52:43

相关推荐

Vue 图片懒加载 之 Vue-Lazyload

一、什么叫懒加载

通俗讲 : 懒加载就是延时加载,即当需要用到的时候再去加载。

那什么叫做需要用到的时候?

比如一个图片在没有出现在可视区域内,就已经加载当页面里了, 但只有滚动页面下方式才能看见, 则可以认为这个图片加载的"过早"了。

二、懒加载的优点

可以减少首页首次加载的数量,减少服务器的压力当网络请求比较慢的时候, 提前给这张图片添加一个像素比较低的占位图片,不至于堆叠在一块,或显示大片空白,让用户体验更好一点。

三、为什么使用懒加载

可以想象一个网页打开有成百上千的图片需要加载,页面会变得非常的卡顿,此时如果只是可视区域的图片加载,其他的图片可以暂时有一个占位 loading 图,等滚动它们到可视区域时再去请求真实图片并且替换就好了。vue-lazyload 插件就是解决此类问题的,对vue插件的写法不熟悉的可以先看一下vue插件

懒加载原理是什么

页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。

懒加载的原理就是先在页面中把所有的图片统一使用一张占位图进行占位,把真正的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,当js监听到该图片元素进入可视窗口时,即将自定义属性中的地址存储到src属性中,达到懒加载的效果。

四、vue中如何实现懒加载

第一步: 安装

npm install vue-lazyload --save

第二步: 全局注册(main.js)

// main.js 文件import VueLazyload from 'vue-lazyload'// Vue.use(VueLazyload) //无配置项// 配置项const loadimage = require('assets/img/common/loading.gif')// const errorimage = require('assets/img/common/error.gif')Vue.use(VueLazyload, {preLoad: 1.3, //预加载的宽高比loading: loadimage, //图片加载状态下显示的图片// error: errorimage, //图片加载失败时显示的图片attempt: 1, // 加载错误后最大尝试次数})// img元素上使用v-lazy="src";<img v-lazy="showImage"/>

配置项的参数说明

因为src中的文件会被webpack编译,assets文件夹中的图片地址,会在编译过程中重命名。vue-lazyload是在main.js文件中引入,不会被webpack进行编译,因此vue-lazyload无法获得正确的图片地址,所以直接写相对地址就无法获取到图片正确地址

第三步: 写loading图片的样式(不是必须, 视情况而定)

img[lazy="loading"]{display:block;width:50px !important;height:50px !important;margin:0 auto;}

第四步: 使用 ( :src--->v-lazy )

<div class="lazyLoad"><ul><li v-for="img in arr"><img v-lazy="img.thumbnail_pic_s"></li></ul></div>

这里有个坑需要注意

如设置了翻页功能,且每一页都是请求的数据进行渲染。

会发现其他的数据都变了,唯独图片还是原来的图片。

由于使用的数据是父组件传过来的,第一个想到父组件axios异步请求的数据导致子组件可能数据没有动态更新。但监听了下数据,发现确实是改变了 .

解决办法只要加个key就行, 如下代码

<ul> <li v-for="img in list"><img v-lazy="img.src" :key="img.src" ></li></ul>

五、js---懒加载的实现步骤?

1)首先,不要将图片地址放到src属性中,而是放到其它属性(data-original)中。

2)页面加载完成后,根据scrollTop判断图片是否在用户的视野内,如果在,则将data-original属性中的值取出存放到src属性中。

3)在滚动事件中重复判断图片是否进入视野,如果进入,则将data-original属性中的值取出存放到src属性中。

懒加载代码实现

方式一:

元素距顶部的高度 - 页面被卷去的高度 <= 浏览器可视区的高度)

来判断是否符合我们想要的条件.需要实时监听页面滚动时 图片的高度变化

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>* {padding: 0;margin: 0;list-style: none;}img {width: 400px;height: 300px;}</style><script>window.onload = function () {var imgs = document.querySelectorAll("img");// 初始化执行lazyLoad(imgs);// 滚动执行window.addEventListener("scroll", function () {lazyLoad(imgs);});function lazyLoad(imgs) {for (let i = 0; i < imgs.length; i++) {var imgoffsetT = imgs[i].offsetTop; // 图片的距顶部的高度var wheight = window.innerHeight; // 浏览器可视区的高度var scrollT = document.documentElement.scrollTop; // 页面被卷去的高度if (imgoffsetT - scrollT <= wheight) {// 判断图片是否将要出现imgs[i].src = imgs[i].dataset.src; // 出现后将自定义地址转为真实地址}}}};/* obj.getAttribute("属性名")通过元素节点的属性名称获取属性的值。使用data-前缀设置我们需要的自定义属性,来进行一些数据的存放,dataset 获取自定义属性值的使用*/</script></head><body><ul><li><img data-src="./img/img1.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img2.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img3.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img4.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img5.png" src="./img/loading.gif" alt="" /></li></ul></body></html>

方式二 getBoundingClientRect()

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>* {padding: 0;margin: 0;list-style: none;}img {width: 400px;height: 300px;}</style><script>window.onload = function () {var imgs = document.querySelectorAll("img");// 初始调动一次lazyLoad();window.addEventListener("scroll", throttle(lazyLoad, 1000), false);//函数1:封装判定图片是否在可视区function isInVisibleArea(imgOne) {const info = imgOne.getBoundingClientRect();// 获取页面可视区的高度,宽度let windowH = window.innerHeight;let windowW = window.innerWidth;// 限定参数在可视区内let res = info.bottom > 0 && info.top < windowH && info.right > 0 && info.left < windowW;return res;}//函数2: 封装滚动时重新加载函数function lazyLoad() {for (let i = 0; i < imgs.length; i++) {const imgOne = imgs[i];// 判定是否在可视区内if (isInVisibleArea(imgOne)) {// 替换src方法一:// imgOne.src = imgOne.getAttribute("data-src");// 替换src方法二:imgOne.src = imgOne.dataset.src;// imgs.splice(i,1)// i--;}console.log("我滚了"); //所以要做节流操作}}//函数3:节流函数/* 参数1: 函数参数2:执行时间*/function throttle(fn, time = 250) {let lastTime = null;return function (...args) {const now = Date.now(); //当前时间if (now - lastTime >= time) {fn();//帮助执行函数,改变上下文lastTime = now;}};}};/* getBoundingClientRect()——获取元素位置,这个方法没有参数——用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。——是DOM元素到浏览器可视范围的距离(不包含文档卷起的部分)。该函数返回一个Object对象,该对象有6个属性:top,lef,right,bottom,width,height;*/</script></head><body><ul><li><img data-src="./img/img1.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img2.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img3.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img4.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img5.png" src="./img/loading.gif" alt="" /></li></ul></body></html>

方式三:IntersectionObserver(callback)

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>* {padding: 0;margin: 0;list-style: none;}img {width: 400px;height: 300px;}</style></head><body><ul id="view"><li><img data-src="./img/img1.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img2.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img3.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img4.gif" src="./img/loading.gif" alt="" /></li><li><img data-src="./img/img5.png" src="./img/loading.gif" alt="" /></li></ul><script>const imgs = document.querySelectorAll("img");const callback = (res) => {//res 是观察的元素数组 info 每个被观察的图片信息res.forEach((info) => {// isIntersecting 目标是否被观察到,返回布尔值if (info.isIntersecting) {// img 就是当前的图片标签const img = info.target;img.src = img.getAttribute("data-src");// 真实地址替换后 取消对它的观察obs.unobserve(img);console.log("触发");}});};const obs = new IntersectionObserver(callback);// 实例化 IntersectionObserver// 遍历imgs所有的图片,然后给每个图片添加观察实例imgs.forEach((img) => {// observe : 被调用的IntersectionObserver实例。给每个图片添加观察实例obs.observe(img);});/* IntersectionObserver(callback) callback回调触发两次,看见了出发,看不见也触发*/</script></body></html>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。