版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第js前端圖片加載異常兜底方案網(wǎng)絡(luò)環(huán)境總是多樣且復(fù)雜的,一張圖片可能會因為網(wǎng)路狀況差而加載失敗或加載超長時間,也可能因為權(quán)限不足或者資源不存在而加載失敗,這些都會導(dǎo)致用戶體驗變差,所以我們需要一個圖片加載異常的兜底方案。
img加載錯誤解決方案
直接在img標(biāo)簽上使用內(nèi)聯(lián)事件處理圖片加載失敗的情況,但是這種方式代碼侵入性太大,指不定就會有地方漏掉。
imgsrc=xxxxxonerror=this.src=default.png
全局img添加事件
第一個方案侵入性太大,我們將入口收斂,為所有img標(biāo)簽統(tǒng)一添加error處理事件。
constimgs=document.getElementsByTagName(img)
Atotype.forEach.call(imgs,img={
img.addEventListener(error,e={
e.target.src=default.png
利用error事件捕獲
為每個img添加事件處理函數(shù)的代價還是高了點,我們知道一般事件會經(jīng)歷三個階段:
捕獲階段
處于目標(biāo)階段
冒泡階段
根據(jù)MDN文檔中的描述:
Whenaresource(suchasanimgorscript)failstoload,anerroreventusinginterfaceEventisfiredattheelementthatinitiatedtheload,andtheonerror()handlerontheelementisinvoked.Theseerroreventsdonotbubbleuptowindow,butcanbehandledwithaEventTarget.addEventListenerconfiguredwithuseCapturesettotrue.
我們可以知道img和srcipt標(biāo)簽的error并不會冒泡,但是會經(jīng)歷捕獲階段和處于目標(biāo)階段。前兩個方案就是利用處于目標(biāo)階段觸發(fā)事件函數(shù),這一次我們在捕獲階段截獲并觸發(fā)函數(shù),從而減少性能損耗。
document.addEventListener(
error,
e={
lettarget=e.target
consttagName=target.tagName||
if(tagName.toLowerCase=img){
target.src=default.png
target=null
true
替換src方式的最優(yōu)解
上面的方案有兩個缺點:
如果是因為網(wǎng)絡(luò)差導(dǎo)致加載失敗,那么加載默認(rèn)圖片的時候也極大概率會失敗,于是會陷入無限循環(huán)。
如果是網(wǎng)絡(luò)波動導(dǎo)致的加載失敗,那么圖片可能重試就會加載成功。
所以我們可以為每個img標(biāo)簽額外添加一個data-retry-times計數(shù)屬性,當(dāng)重試超過限制次數(shù)后就用base64圖片作為默認(rèn)兜底。
document.addEventListener(
error,
e={
lettarget=e.target
consttagName=target.tagName||
constcurTimes=Number(target.dataset.retryTimes)||0
if(tagName.toLowerCase()===img){
if(curTimes=3){
target.src=data:image/png;base64,xxxxxx
}else{
target.dataset.retryTimes=curTimes+1
target.src=target.src
target=null
true
CSS處理的最優(yōu)解
上面方式是采用替換src的方式來展示兜底圖,這種解決方式有一個缺陷:
原圖的資源鏈接無法從標(biāo)簽上獲?。m然可以通過加data-xxx屬性的方式hack解決)。
所以還有一種更好的方式,就是利用CSS偽元素::before和::after覆蓋原本元素,直接展示兜底base64圖片。
CSS樣式如下:
img.error{
display:inline-block;
transform:scale(1);
content:
color:transparent;
img.error::before{
content:
position:absolute;
left:0;top:0;
width:100%;height:100%;
background:#f5f5f5url(data:image/png;base64,xxxxxx)no-repeatcenter/50%50%;
img.error::after{
content:attr(alt);
position:absolute;
left:0;bottom:0;
width:100%;
line-height:2;
background-color:rgba(0,0,0,.5);
color:white;
font-size:12px;
text-align:center;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
JS代碼如下:
document.addEventListener(
error,
e={
lettarget=e.target
consttagName=target.tagName||
constcurTimes=Number(target.dataset.retryTimes)||0
if(tagName.toLowerCase()===img){
if(curTimes=3){
target.classList.remove(error)
target.classList.add(error)
}else{
target.dataset.retryTimes=curTimes+1
target.src=target.src
target=null
true
img加載超時解決方案
目前大多數(shù)應(yīng)用都會接入CDN來加速資源請求,但是CDN存在節(jié)點覆蓋不全的問題,導(dǎo)致DNS查詢超時,此時如果切換Domain可能就會加載成功。
嗅探切換Domain(CNAME)
我們可以使用嗅探的方式,測試CDN提供的Domain是否能夠正常訪問,如果不行或者超時就及時切換成可訪問Domain。其中有幾個注意點:
為了防止嗅探圖片緩存,需要添加時間戳保持新鮮度
Image圖片加載沒有超時機制,使用setTimeout模擬超時
//防止嗅探圖片存在緩存,添加時間戳保持新鮮度
exportconstimgUri=`/img/xxxxxtimestamp=${Date.now()}${Math.random()}`;
exportconstoriginDomain=
//可采用配置下發(fā)的方式
exportconstcdnDomains=[
,
,
,
exportconstvalidateImageUrl=(url:string)={
returnnewPromisestring((resolve,reject)={
constimg=newImage();
img.onload=()={
resolve(url);
img.onerror=(e:string|Event)={
reject(e);
//promise的狀態(tài)不可變性,使用setTimeout模擬超時
consttimer=setTimeout(()={
clearTimeout(timer);
reject(newError(ImageLoadTimeout
},10000);
img.src=url;
exportconstsetCDNDomain=()={
constcdnLoop=()={
returnPromise.race(
cdnDomains.map((domain:string)=validateImageUrl(domain+imgUri)),
).then(url={
window.shouldReplaceDomain=true;
consturlHost=url.split(/)[2];
window.replaceDomain=urlHost;
returnvalidateImageUrl(`${originDomain}${imgUri}`)
.then(()={
window.shouldReplaceDomain=false;
window.replaceDomain=
.catch(()={
returncdnLoop();
//替換URL
exportconstreplaceImgDomain=(src:string)={
if(srcwindow.shouldReplaceDomainwindow.replaceDomain){
returnsrc.replace(originDomain.split(/)[2],window.replaceDomain);
returnsrc;
服務(wù)端下發(fā)Domain(CNAME)
該方案需要后臺同學(xué)配合,由后臺判斷當(dāng)前當(dāng)前可用Domain并返回。
getUsefulDomain()
.then(e={
window.imgDomain=e.data.imgDomain||
background-image加載異常解決方案
實際應(yīng)用中背景圖也會加載失敗,通常這些元素沒有error事件,所以也就無從捕獲error事件了。此時就可以利用dispatchEvent,它同樣擁有捕獲階段,MDN文檔上是這么介紹的:
DispatchesanEventatthespecifiedEventTarget,(synchronously)invokingtheaffectedEventListenersintheappropriateorder.Thenormaleventprocessingrules(includingthecapturingandoptionalbubblingphase)alsoapplytoeventsdispatchedmanuallywithdispatchEvent().
可以看到支持度也還是可以的,我們首先需要自定義一個事件并初始化這個事件,在背景圖加載失敗的時候觸發(fā)這個自定義事件,最后在上層捕獲這個事件并執(zhí)行事件函數(shù)。
自定義事件
自定義事件有兩種方式:
使用createEvent()和initEvent(),但是根據(jù)MDN文檔,initEvent方法已經(jīng)從瀏覽器標(biāo)準(zhǔn)中移除,并不安全,但支持度很高。
使用newEvent()的方式,但是支持率稍微差一點
這里以第二種為例,根據(jù)MDN文檔的用法創(chuàng)建一個自定義事件:
constevent=newEvent(bgImgError)
嗅探加載情況
使用前面定義的方法嗅探圖片資源的情況。
validateImageUrl(xxx.png)
.catch(e={
letele=document.getE
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 多污染物聯(lián)合暴露下社區(qū)慢病的健康風(fēng)險評價
- 2025年高職無人機應(yīng)用技術(shù)(無人機植保技術(shù))試題及答案
- 2025年大學(xué)化工類(化工基礎(chǔ)實訓(xùn))試題及答案
- 2026年電動車維修(電池案例)試題及答案
- 2025年中職計算機應(yīng)用(數(shù)據(jù)處理)試題及答案
- 2025年高職(旅游管理綜合實訓(xùn))規(guī)劃優(yōu)化實操試題及答案
- 2025年中職第一學(xué)年(中醫(yī)養(yǎng)生保健)中醫(yī)食療養(yǎng)生試題及答案
- 2026年污水處理(工業(yè)廢水處理工藝)試題及答案
- 2025年中職建筑施工(混凝土澆筑)試題及答案
- 2025年中職第二學(xué)年(水產(chǎn)養(yǎng)殖實訓(xùn))魚塘水質(zhì)調(diào)節(jié)實操綜合測試試題及答案
- 魯科版高中化學(xué)必修一教案全冊
- 提高隧道初支平整度合格率
- 2023年版測量結(jié)果的計量溯源性要求
- 建筑能耗與碳排放研究報告
- GB 29415-2013耐火電纜槽盒
- 中國古代經(jīng)濟試題
- 軟件定義汽車:產(chǎn)業(yè)生態(tài)創(chuàng)新白皮書
- 磷石膏抹灰專項施工方案
- 水電水利工程施工質(zhì)量管理培訓(xùn)講義
- ArcMap制圖-地圖版面設(shè)計實驗報告
- 建設(shè)部37號令危大工程標(biāo)識牌樣表
評論
0/150
提交評論