JavaScript前端靜態(tài)資源預(yù)加載實現(xiàn)示例
為什么要靜態(tài)資源預(yù)加載?
靜態(tài)資源文件主要指的就是圖片,我們在項目中用到最多的靜態(tài)資源文件也是圖片。但是圖片作為一種可替換元素,在使用時有很多的問題。
在了解圖片問題之前,先看看發(fā)生在我身上的真實小故事,幫助大家更好的理解。
在一個陽光明媚的清晨,你因為各種原因出門晚了。你一路飛奔找到最近的小藍車,途中完成wifi切換流量、打開支付寶、點擊哈羅等操作??粗M入小程序的loading,你知道今天又能擠上地鐵,嘴角不禁微微上揚。
在loading消失的最后一秒你也剛好氣喘吁吁的跑到了小藍車面前,迫不及待的點擊"掃一掃"三個大字...
就在你手指將要觸碰到屏幕的那一瞬間,頁面突然一閃,原來掃一掃的位置變成了去購買。下一秒頁面不出意外的跳轉(zhuǎn)到了優(yōu)惠活動頁,重新開始了loading...
待你點擊返回掃開小藍,紅綠燈已經(jīng)由黃轉(zhuǎn)紅,今天鐵定是遲到了...
相信每天踩著最后一秒打卡的朋友一定很理解我的心路歷程??????。
封面的動圖就是那個頁面的變動過程,這個動圖也很好的說明了圖片在前端渲染時出現(xiàn)的問題。
圖片在使用時的問題
文件大小要大于文字,在網(wǎng)絡(luò)中傳輸慢。
故事中同一個接口的去購買文字已經(jīng)展示出來,但是banner圖還沒渲染出來。
影響用戶體驗
故事中打開頁面后原本是banner圖的位置有一大塊空白,這對于用戶體驗來說不夠好。
試想如果一個頁面中大大小小的圖片有很多,在加載時都是這樣的空白會是什么體驗?
或者當你點擊了跳轉(zhuǎn)或者打開一個內(nèi)容時,內(nèi)容中的圖片位置總是先顯示空白會是什么體驗?
影響Dom結(jié)構(gòu)
故事中頁面之所以會發(fā)生抖動和閃爍,是因為dom結(jié)構(gòu)發(fā)生了變化。故事中dom結(jié)構(gòu)變化的原因可能是因為優(yōu)惠接口返回慢而導(dǎo)致的,但是圖片的加載和渲染也能出現(xiàn)類似的場景。進而導(dǎo)致用戶的行為因為頁面dom的變動而發(fā)生錯誤。
圖片會裂開
將圖片作為背景圖片時,加載失敗頂多導(dǎo)致背景空白。但是直接使用image
標簽如果圖片加載失敗就會有一個裂開的圖片展示到頁面上,這種場景相信大家都見到過。
解決辦法
- 可以將圖片壓縮到盡可能小,這樣可以大幅提高傳輸和加載的速度;
- 使用背景圖片代替image標簽;
- 可以嘗試將小圖標整合成精靈圖雪碧圖;
- 針對dom結(jié)構(gòu)變動,可以參考哈羅在圖片外層設(shè)置一個差不多高度的div預(yù)先給圖片留個位置;
無法解決的場景
以上的解決方法都適用于所用到的圖片比較小,或者比較少的情況下。當圖片本身比較大時即使經(jīng)過壓縮還是很大,也不方便做成精靈圖。當一個項目擁有很多圖片,用戶在不同項目的子路由間跳轉(zhuǎn)或者通過交互觸發(fā)頁面上大量圖片更新時,上面的方法就不是很適用了。
什么是靜態(tài)資源預(yù)加載?
靜態(tài)資源預(yù)加載的原理是利用瀏覽器的緩存機制
配合img的onload事件
,將漫長的圖片的加載過程放在真正進入頁面之前,進入頁面后所有用到的圖片都會直接從內(nèi)存讀取。
也就是說要將頁面的初始化接口在進入頁面之前調(diào)用,從而獲取要加載的圖片鏈接。
靜態(tài)資源預(yù)加載的優(yōu)點和缺點
優(yōu)點
- 用戶進入頁面后一瞬間就可以看到整個頁面而不會出現(xiàn)白屏;
- 用戶在
切換tab
或者是跳轉(zhuǎn)到子路由頁面
時不會因為加載圖片而出現(xiàn)頁面的卡頓; - 不會出現(xiàn)圖片由空白從上至下一點點的向下渲染的過程;
- 不會出現(xiàn)因為圖片沒及時加載出來而導(dǎo)致的dom結(jié)構(gòu)崩亂,造成頁面閃爍;
缺點
- 漫長的圖片加載放到進入頁面之前會讓用戶的等待時間變長;
- 過長的等待時間可能會導(dǎo)致轉(zhuǎn)化率的下降;
缺點的處理
為了應(yīng)對這個缺陷,在做靜態(tài)資源預(yù)加載處理進入頁面之前,我們通常都會搭配一個可以顯示進度的loading。這樣可以讓用戶實時獲取到加載進度,而不是無謂的等待。這樣一定程度上可以增加用戶停留在當前頁面的時間,從而進入到下個頁面。
靜態(tài)資源預(yù)加載的實現(xiàn)
通過遞歸的方式在每一張圖片onload成功之后開始加載下一個圖片,直到圖片全部都加載完成。
import isFunction from 'lodash/isFunction'; /** * 圖片資源預(yù)加載 * @param {Array} urlArr 圖片鏈接數(shù)組 * @param {number} index 當前加載的是第幾張圖片 * @param {function} imgLoadFn 單張圖片加載成功的回調(diào) * @param {function} successFn 成功失敗回調(diào)函數(shù) * @param {function} errorFn 加載失敗回調(diào)函數(shù) */ imgLoader(urlArr, index, imgLoadFn, successFn, errorFn) { if (index === urlArr.length && !urlArr[ index ]) return; downloadPic(...arguments); } // 加載單張圖片 downloadPic(urlArr, index, imgLoadFn, successFn, errorFn) { console.log('開始加載第', index, '張圖') const img = document.createElement('img'); img.src = urlArr[ index ]; img.onload = () => { // 這里每一個圖片加載完成時傳入的應(yīng)該是index+1,因為index是從0開始的,而這里表示的是第幾張圖片完成加載的回調(diào),傳入數(shù)組長度用于計算百分比 isFunction(imgLoadFn) && imgLoadFn(index + 1, urlArr.length); if (index === urlArr.length - 1) { // 加載完最后一張時調(diào)用全部完成函數(shù) successFn(index); } else { // 否則開啟下一張圖片的加載 index += 1; downloadPic(urlArr, index, imgLoadFn, successFn, errorFn); } }; img.onError = errorFn ? () => { isFunction(errorFn) && errorFn({ index, url: urlArr[ index ] }) } : () => imgLoaderError(index); } /** * 圖片加載失敗 * @param {number} index 數(shù)組下標 */ imgLoaderError(index) { console.error(`第${ index }張圖片加載失敗`); }
靜態(tài)資源預(yù)加載的調(diào)用
// 定義好對應(yīng)的處理函數(shù) const imgLoadFn = (current, total) => { // 用百分比來顯示當前的加載進度顯示在頁面loading中 this.percent = parseInt(current / total * 100) + '%'; } const successFn = () => { this.percent = '100%'; this.showLoading = false; // 關(guān)閉loading console.log('圖片已全部預(yù)加載完成,可以跳轉(zhuǎn)到對應(yīng)頁面') } const errorFn = () => { console.log('加載資源錯誤'); } // 調(diào)用 imgLoader(urlArr, 0, imgLoadFn, successFn, errorFn);
靜態(tài)資源預(yù)加載的應(yīng)用場景
靜態(tài)資源預(yù)加載常用于各種活動頁面,例如雙11、618、818、年度賬單、周年活動等。
為了讓用戶在進入活動頁之后的交互更流暢,通常會在進入頁面前使用靜態(tài)資源加載將所需的資源文件都加載到緩存中。
所以,這也是我們在進入這些頁面之前經(jīng)??梢钥吹揭粋€加載進度loading的原因。關(guān)于如何實現(xiàn)一個帶進度的loading,可以看我的這篇文章。
以上就是JavaScript前端靜態(tài)資源預(yù)加載實現(xiàn)示例的詳細內(nèi)容,更多關(guān)于JavaScript前端靜態(tài)資源預(yù)加載的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript動態(tài)控制服務(wù)器控件實例
在頁面中放入一個DropDownList控件,并添加一項,用來分析其產(chǎn)生的HTML代碼,這樣在使用js進行動態(tài)控制時,將會非常清晰2014-09-09Javascript實現(xiàn)的常用算法(如冒泡、快速、鴿巢、奇偶等)
這篇文章主要介紹了Javascript實現(xiàn)的常用算法,如冒泡、快速、鴿巢、選擇、木桶、奇偶等,需要的朋友可以參考下2014-04-04javascript實現(xiàn)的彈出層背景置灰-模擬(easyui dialog)
本文為大家介紹下使用javascript實現(xiàn)的彈出層背景置灰-模擬(easyui dialog) 具體實現(xiàn)如下,感興趣的朋友可以參考下2013-12-12詳談innerHTML innerText的使用和區(qū)別
下面小編就為大家?guī)硪黄斦刬nnerHTML innerText的使用和區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08js 實現(xiàn)圖片預(yù)加載(js操作 Image對象屬性complete ,事件onload 異步加載圖片)
通過js操縱DOM很多情況下都是為了實現(xiàn)和當前頁html元素的異步載入,我談?wù)剬mage對象的一些認識。2011-03-03