微信小程式:如何在小程式中使用骨架屏?
阿新 • • 發佈:2018-12-10
前言
骨架屏,就是在頁面資料尚未載入前,先給使用者展示出頁面的大致結構,直到請求資料返回後,再渲染頁面,以優化使用者體驗。
骨架屏在前端的應用已經很普遍了,之前接手vue的專案,沒能用上,現在開發小程式,想在小程式中試一試。看著美團外賣小程式的骨架屏,很nice~
開始
沒有使用骨架屏的經驗,只能靠搜尋引擎了。找找找....終於在網上找到一份很好的例子,作者是騰訊的,程式碼已經在github開源,現在介紹給大家。
首先,從github克隆專案到本地,看看效果啦~(在微信開發工具開啟專案下的src目錄)
效果圖(載入中):
效果圖(載入完畢):
專案的目錄結構:
index.wxml:
<!-- 作為元件在頁面中使用 --> <skeleton selector="skeleton" loading="spin" bgcolor="#FFF" wx:if="{{showSkeleton}}"></skeleton> <!--index.wxml--> <!-- 渲染的根節點,加上 .skeleton --> <view class="container skeleton"> <view class="userinfo"> <block> <!-- 要渲染的圓形節點,加上 .skeleton-radius --> <image class="userinfo-avatar skeleton-radius" src="{{userInfo.avatarUrl}}" mode="cover"></image> <!-- 要渲染的矩形節點,加上 .skeleton-rect --> <text class="userinfo-nickname skeleton-rect">{{userInfo.nickName}}</text> </block> </view> <view style="margin: 20px 0"> <view wx:for="{{lists}}" wx:key="{{index}}" class="lists"> <icon type="success" size="20" class="list skeleton-radius"/> <text class="skeleton-rect">{{item}}</text> </view> </view> <view class="usermotto"> <text class="user-motto skeleton-rect">{{motto}}</text> </view> <view style="margin-top: 200px;">aaaaaaaaaaa</view> </view>
index.json:
{
// 引入骨架屏元件
"usingComponents": {
"skeleton": "/component/skeleton/skeleton"
}
}
最後來探索一下骨架屏元件的實現
skeleton.wxml:
<!-- 最外層的view綁定了js中定義的寬、高以及背景顏色 --> <view style="width: {{systemInfo.width}}px; height: {{systemInfo.height}}px; background-color: {{bgcolor}}; position: absolute; left:0; top:0; z-index:9998; overflow: hidden;"> <!-- 迴圈,遍歷繪製矩形節點,寬高參照js獲取到的節點寬高,以絕對定位的方式定位 --> <view wx:for="{{skeletonRectLists}}" wx:key="{{index}}" class="{{loading == 'chiaroscuro' ? 'chiaroscuro' : ''}}" style="width: {{item.width}}px; height: {{item.height}}px; background-color: rgb(194, 207, 214); position: absolute; left: {{item.left}}px; top: {{item.top}}px"></view> <!-- 迴圈,遍歷繪製矩形節點,寬高參照js獲取到的節點寬高,以絕對定位的方式定位 --> <view wx:for="{{skeletonCircleLists}}" wx:key="{{index}}" class="{{loading == 'chiaroscuro' ? 'chiaroscuro' : ''}}" style="width: {{item.width}}px; height: {{item.height}}px; background-color: rgb(194, 207, 214); border-radius: {{item.width}}px; position: absolute; left: {{item.left}}px; top: {{item.top}}px"></view> <view class="spinbox" wx:if="{{loading == 'spin'}}"> <view class="spin"></view> </view> </view>
skeleton.js:
Component({
// 元件對外暴露的屬性
properties: {
// 背景顏色
bgcolor: {
type: String,
value: '#FFF'
},
// 渲染的根節點的類名
selector: {
type: String,
value: 'skeleton'
},
// 載入動畫
loading: {
type: String,
value: 'spin'
}
},
data: {
loadingAni: ['spin', 'chiaroscuro'],
systemInfo: {},
skeletonRectLists: [],
skeletonCircleLists: []
},
attached: function() {
//預設的首屏寬高,防止內容閃現
const systemInfo = wx.getSystemInfoSync();
// 獲取系統的資訊,作為skeleton的寬和高
this.setData({
systemInfo: {
width: systemInfo.windowWidth,
height: systemInfo.windowHeight
},
// 設定動畫
loading: this.data.loadingAni.includes(this.data.loading) ? this.data.loading: 'spin'
})
},
ready: function() {
const that = this;
//繪製背景
// selectAll: 在當前頁面下選擇匹配選擇器 selector 的所有節點。
wx.createSelectorQuery().selectAll(`.$ {
this.data.selector
}`).boundingClientRect().exec(function(res) {
console.log(res);
that.setData({
'systemInfo.height': res[0][0].height + res[0][0].top
})
});
//繪製矩形
this.rectHandle();
//繪製圓形
this.radiusHandle();
},
methods: {
rectHandle: function() {
const that = this;
//繪製不帶樣式的節點
// 選擇所有 .skeleton-rect的節點
wx.createSelectorQuery().selectAll(`.$ {
this.data.selector
} - rect`).boundingClientRect().exec(function(res) {
console.log(res);
// 儲存資料,一維陣列是節點,二維陣列是節點的資訊
that.setData({
skeletonRectLists: res[0]
})
console.log(that.data);
});
},
radiusHandle: function() {
const that = this;
// 同樣地選擇所有的 .skeleton-radius節點
wx.createSelectorQuery().selectAll(`.$ {
this.data.selector
} - radius`).boundingClientRect().exec(function(res) {
console.log(res);
that.setData({
skeletonCircleLists: res[0]
})
console.log(that.data);
});
},
}
})
核心的程式碼是元件的.js和.wxml檔案,使用了wx.createSelectorQuery().selectAll 非常巧妙地選擇到了所有要渲染的矩形和圓形節點,在頁面中,使用迴圈,遍歷出所有的節點。
總結
就是這麼簡單的操作,實現了我們想要的效果。有時間真的應該好好看一些優秀的原始碼~
最後上一張使用的效果圖,要去吃飯了....
如果你還有什麼疑問或想法,歡迎留言評論,或者掃描下方二維碼,與我取得聯絡~ (記得備註:CSND喔~)