首先了解下什么是骨架屏?
骨架屏就是在頁面數據尚未加載前先給用戶展示出頁面的大致結構,直到請求數據返回后再渲染頁面,補充進需要顯示的數據內容。常用于文章列表、動態列表頁等相對比較規則的列表頁面。 很多項目中都有應用餓了么h5版本,知乎,facebook等網站中都有應用。
以下圖舉例,常用餓了么的童鞋,應該看到過餓了么的這個首頁預加載圖的效果:
餓了么h5實現方案
咱們來聊聊小程序的實現方案:
1.最簡單最快捷的最暴力的,直接讓設計一張圖片蓋上去,當loading使用。
舉例:餓了么的訂單頁面,查看了下源碼,是使用的SVG的圖
2.前端使用view寫死一套數據(缺點很明顯,假如頁面布局有修改的話,那么除了修改業務代碼之外還需要額外修改骨架屏,增加了維護的成本)
舉例:簡單寫了個代碼片段:https://developers.weixin.qq.com/s/ZAuYzHmX7ObC
3.頁面Data里寫死一套默認數據,使用小程序的wx.createSelectorQuery().selectAll 選擇了所有要渲染的矩形和圓形節點,在頁面中,使用循環,遍歷出所有的節點,再加上樣式。
基本原理就是
-
在組建初始化時,設置其絕對定位,大小為整個屏幕大小
-
然后用節點查詢方法,找到類名等于skeleton的元素,并設置組件的背景的位置及大小和元素的一致,覆蓋這個元素。
-
用節點查詢方法,找到所有的類名等于skeleton-radius 元素,并將它們的位置及大小信息加入到sklection-radius-Arr數組中,在wxml中用wx:for循環渲染出來(也是絕對定位)
-
用節點查詢方法,找到所有的類名等于skeleton-rect 元素,并將它們的位置及大小信息加入到sklection-rect-Arr數組中,在wxml中用wx:for循環渲染出來(也是絕對定位)
當然啦,這里還有一些判斷,還可以設置屏幕上提示是旋轉小圈圈還是背景色漸變提醒等,都是一些比較細節的東西,就不細說。
具體代碼參考:jayZOU,這里有他具體源碼以及實現邏輯,使用后會發現有些許異常未處理。
那么到這就完了嗎?當然木有,現在說下最后一種方案(目前我們小程序正在使用的方案)。
4. 如何更好的把骨架屏代碼嵌入到業務里面,是否可以在接口請求成功后,先渲染出一套接口返回的數據匹配的骨架,再展示給用戶看呢,減少用戶查看白屏(loading)時間。
這是我們線上版本效果示例圖:
首先來看 如何操作:
整個前邊部分跟jayZOU的邏輯思路一樣,使用wx.createSelectorQuery 獲取到相關節點進行渲染操作,但是我們把默認數據這一欄更改為動態數據,并且兼容修復了一部分bug。
核心代碼就是自定義組件內拋出的isNodes和isComplete屬性
//wxml
<skeletons isNodes="{{isNodes}}" isComplete="{{isComplete}}"" />
//頁面節點上需要手動添加一個樣式類。
比如輪播圖 寬686rpx,高140rox,是長方形那么給他的樣式上加上‘skeletions-rect’,如果是圓形給他加上‘skeletons-circle’
業務內代碼如下:
<!-- 輪播圖組件 -->
<block wx:if="{{swiperData.length > 0}}">
<swiper class="swiperSlide" indicator-dots="{{indicatorDots}}" indicator-color="#ccc" indicator-active-color="#00CC88" autoplay circular>
<block wx:for="{{swiperData}}" wx:key="{{index}}">
<swiper-item>
<view class="swiper-item">
<image lazy-load src="{{item.image}}" data-index="{{index}}" bindtap="universalJump" class="skeletons-rect" />
</view>
</swiper-item>
</block>
</swiper>
<!-- <qts-swiper resourseFrom="{{swiperData}}" indicatorDots="{{indicatorDots}}"></qts-swiper> -->
</block>
相關JS如下:
initData() {
let postData = {
townId: wx.getStorageSync('townId') || 87
}
// 初始化請求第一個接口
app.postAjax('https://url.com', postData).then((res) => {
if (res.success) {
this.setData({
bodyData: res.data, //頁面展示數據的大對象
isNodes: true //抓取節點繪制骨架屏
}, () => {
this.setData({
isComplete: true //節點繪制完成,隱藏骨架屏
})
})
} else {
util.toast(res.msg || '團團開小差啦,請稍后重試')
}
}, () => {
util.toast('團團開小差啦,請稍后重試')
})
},
目前遇到的難點在于,把功能點抽成自定義組件。skeletons的class類無法傳遞進去,試過用外部樣式影響自定義組件樣式,還是無法達到效果。如果有解決這個問題的歡迎留言溝通優化~
最后完整組件代碼地址:https://gitee.com/minchangyong/skeletons
已新增支付寶版本
社區關注可以走一走哦~:
青團社招聘:
招聘崗位:資深前端開發工程師P6及以上
坐標杭州市余杭區文一西路1380號金之源大廈11層
簡歷投遞到:hr@qtshe.com
職位描述:
1、負責前端模塊(PC、移動、小程序)的重要方案設計與研發
2、研究和探索創新的開發思路和前端技術,優化前端框架、設計方案,提高前端的開發交付效率。
3、理解產品業務的基礎上,提升產品用戶體驗,技術驅動業務發展。
4、定期組織主題分享,活躍技術氛圍,帶動組員提升技術能力
任職資格與條件要求描述
1、對 MVC/MVMM 有一定的理解,至少熟練掌握一個或多個前端框架(React、Vue等)
2、代碼結構清晰,javascript基礎扎實,精通任意一門前端MV*框架,如Vue、React等
3、熟悉 HTTP 協議,熟悉 Web 應用的性能優化,監控,分析方法
4、溝通能力強,責任心強,思維邏輯性強