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"/>配置項的參數說明
| preLoad | 表示lazyload的元素, 距離頁面底部距離的百分比. 計算值為(preload - 1) | 1.3 | Number |
| error | 加載失敗后圖片地址 | 'data-src' | String |
| loading | 加載時圖片地址 | 'data-src' | String |
| attempt | 圖片加載失敗后的重試次數 | 3 | Number |
| listenEvents | 觸發懶加載的事件 | ['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove'] | 無 |
| adapter | 注冊img 的loading,loaded,error 三個狀態的回調函數, 參數會暴露懶加載的img元素, 可以對其進行操作. | { } | 無 |
| filter | img未加載之前, 解析到src 的時候注冊的回調函數. 可以在加載圖片之前,對src進行修改. 注冊在filter下的所有的函數都會執行 | { } | 無 |
| lazyComponent | 是否啟用懶加載組件. <lazy-component>組件中的內容 只有在出現在preload的 位置中才會加載組件. 這個lazyloadComponent 組件有個缺點 就是,組件在加載前 是什么都不渲染的, 這樣子的話,有可能會影響布局, 以及加載前到加載后的切換不好, 有點突兀和生硬. | false | 無 |
| dispatchEvent | 觸發dom事件 | false | Boolean |
| throttleWait | 等待時長 | 200 | Number |
| observer | 是否啟用IntersectionObserver, 這個api有兼容問題 | false | Boolean |
| observerOptions | IntersectionObserver選項 | { rootMargin: '0px', threshold: 0.1 } | 無 |
| silent | 不打印調試信息 | true | Boolean |
因為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就行, 如下代碼
五、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>總結
以上是生活随笔為你收集整理的Vue 图片懒加载 之 Vue-Lazyload的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Xp正版验证补丁
- 下一篇: 告诉你C盘里的每个文件夹都是干什么用的