微信小程序image加載成功前顯示默認占位圖

在微信小程序中,我們使用Image組件來展示圖片,圖片源可以是本地資源,也可以是服務(wù)器資源。但是為了內(nèi)容的動態(tài)展示,我們絕大多數(shù)情況下,會使用服務(wù)器資源來展現(xiàn)作為image的圖片源。既然是服務(wù)器資源,那么就需要依賴于網(wǎng)絡(luò)的快慢,如果在網(wǎng)絡(luò)慢的情況下,image加載圖片的過程可能會非常慢,所以在加載圖片的過程中,如果不做處理,會出現(xiàn)一片空白的情況,直到圖片加載完成,這是非常差的用戶體驗。

為了提高用戶體驗度,我們可以在圖片加載完成之前,預(yù)先展示一張本地的默認占位圖片,而不是顯示空白。

小程序的image組件沒有提供默認圖片的屬性,需要我們自己實現(xiàn)這個功能。

實現(xiàn)原理

微信小程序的image組件有兩個屬性:

屬性名 類型 說明
binderror HandleEvent 當(dāng)錯誤發(fā)生時,發(fā)布到 AppService 的事件名,事件對象event.detail = {errMsg: 'something wrong'}
bindload HandleEvent 當(dāng)圖片載入完畢時,發(fā)布到 AppService 的事件名,事件對象event.detail = {height:'圖片高度px', width:'圖片寬度px'}

我們可以實現(xiàn)這兩個事件:

  • 實現(xiàn)bindload,在圖片未加載完成時,顯示占位圖,一旦加載完成,馬上隱藏占位圖,顯示真正的業(yè)務(wù)圖片
  • 實現(xiàn)binderror,在圖片加載錯誤時,顯示占位圖。

具體實現(xiàn)

新建一個小程序項目

打開微信開發(fā)者工具,新建一個小程序項目Demo,刪除無用代碼

自定義組件

在實際開發(fā)中,在多個地方都會用到image組件,如果在每個使用的地方都去實現(xiàn)一遍占位圖的功能,不僅會增加代碼量,而且也增加維護量,所以,我們可以把這些邏輯,封裝為一個自定義組件,這里我們?nèi)∶麨?code>image-loader,然后任何用到的地方,直接用image-loader去代替image就可以了。

新建image-loader

使用微信開發(fā)工具新建一個自定義組件,并位于項目的目錄components中,這個大家使用過微信開發(fā)工具的肯定都會操作,這里就不在贅述。然后找到一張占位圖,放到項目的images目錄下,完成之后

現(xiàn)在項目的目錄結(jié)構(gòu):

$ tree
.
├── app.js
├── app.json
├── app.wxss
├── components
│   ├── image-loader.js
│   ├── image-loader.json
│   ├── image-loader.wxml
│   └── image-loader.wxss
├── images
│   └── placeholder800x400.png
├── pages
│   └── index
│       ├── index.js
│       ├── index.json
│       ├── index.wxml
│       └── index.wxss
└── project.config.json

實現(xiàn)image-loader

我們在image-loader中,加入兩個image,一個image用于加載默認圖片,一個image用于加載真正的圖片。為了描述方便,我們把這兩個image稱為image-defaultimage-real

在初始化的時候,我們顯示的是image-default圖片,同時,image-real也會一起加載,只不過,會通過css屬性控制image-real不顯示:

.before-load {
  width: 0;
  height: 0;
  opacity: 0;
}

然后給image-real實現(xiàn)bindloadbinderror,在加載完成并成功后,把image-defaultwidthheight都置為空,這樣image-default就不會再顯示,同時讓image-realwidhthheight恢復(fù)原始值,并把opcity置為1

下面貼出所有代碼

image-loader.js

/**
 * 圖片預(yù)加載組件
 */
Component({
  properties: {
    //默認圖片
    defaultImage: String,
    //原始圖片
    originalImage: String,
    width: String,
    height: String,
    //圖片剪裁mode,同Image組件的mode
    mode: String
  },
  data: {
    finishLoadFlag: false
  },
  methods: {
    finishLoad: function (e) {
      this.setData({
        finishLoadFlag: true
      })
    }
  }
})

image-loader.jsong

{
  "component": true,
  "usingComponents": {}
}

image-loader.wxml

<image wx:if='{{!finishLoadFlag}}' mode='{{mode}}' src='{{defaultImage}}' style='{{width ? "width:" + width : ""}};{{height ? "height:" + height : ""}}' />
<image mode='{{mode}}' class='{{finishLoadFlag ? "" : "before-load"}}' src='{{originalImage}}' bindload='finishLoad' style='{{finishLoadFlag && width ? "width:" + width : ""}};{{finishLoadFlag && height ? "height:" + height : ""}}' />

image-loader.wxss

.before-load {
  width: 0;
  height: 0;
  opacity: 0;
}

注意:我這里為了簡化,只實現(xiàn)了imagebindload而未實現(xiàn)binderror。

測試

最后,我們修改pages/index頁面代碼測試一下

  • 啟用插件

index.json

{
    "usingComponents": {
      "image-loader": "/components/image-loader"
    }
}
  • 測試代碼:

index.wxml

<image-loader  default-image='../images/placeholder800x400.png' mode='widthFix' original-image='https://www.neware.shop/demo/mobile/api/v1/public/image/download/201809051000165950' width="400rpx" height="200rpx" />

源碼

完整的組件源碼我放在了 Github 上,大家可以去查看:wx-mini-image-preload

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容