歷史回顧:javascript
骨架屏在前端的應用裏很普及,不過大多都是在H5的應用中,今天想談的是微信小程序中如何使用骨架屏,以及小程序骨架屏的實現原理,針對骨架屏項目還能夠提個PR,封裝出來一個npm包形式的第三方,爲前端社區作點小貢獻。html
npm install --save miniprogram-skeleton
複製代碼
{
"usingComponents": {
"skeleton": "../miniprogram_npm/miniprogram-skeleton"
}
}
複製代碼
小程序中npm的配置及使用:前端
miniprogram_npm
文件夾,項目用到的npm包都在這裏。miniprogram_npm
引入須要的包。注意下小程序中npm的配置及使用比普通的npm包的使用多了一些配置,引出了
miniprogram_npm
的概念。java
<!--引入骨架屏模版 -->
<skeleton wx:if="{{showSkeleton}}"></skeleton>
<!--index.wxml-->
<!--給頁面根節點class添加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}}" 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>
複製代碼
初始化默認的數據,用於撐開頁面結構,讓骨架屏能夠獲取到總體的頁面結構。git
//index.js
Page({
data: {
motto: 'Hello World',
userInfo: {
avatarUrl: 'https://wx.qlogo.cn/mmopen/vi_32/SYiaiba5faeraYBoQCWdsBX4hSjFKiawzhIpnXjejDtjmiaFqMqhIlRBqR7IVdbKE51npeF6X1cXxtDQD2bzehgqMA/132',
nickName: 'jayzou'
},
lists: [
'aslkdnoakjbsnfkajbfk',
'qwrwfhbfdvndgndghndeghsdfh',
'qweqwtefhfhgmjfgjdfghaefdhsdfgdfh',
],
showSkeleton: true //骨架屏顯示隱藏
},
onLoad: function () {
const that = this;
setTimeout(() => { //3S後隱藏骨架屏
that.setData({
showSkeleton: false
})
}, 3000)
}
})
複製代碼
在微信小程序中使用骨架屏比較簡單的,注意骨架屏組件的基礎傳參,以及顯示和隱藏骨架屏的控制。github
源碼地址:github.com/jayZOU/skel…npm
做者是騰訊的一位大佬,是他👇json
做者的實現思路相對比較簡單,所謂會者不難難者不會,瞭解了以後以爲聽簡單的。實現思路是在網絡請求接口數據的這段時間,經過獲取到dom節點的大小填充底色,當數據獲取到了,再將骨架屏隱藏。小程序
在這個過程當中有兩個點須要注意:微信小程序
利用微信小程序的 [selectorQuery](https://developers.weixin.qq.com/miniprogram/dev/api/wxml/SelectorQuery.html)
查找相關節點,提供瞭如下api:
將選擇器的選取範圍更改成自定義組件 component 內。(初始時,選擇器僅選取頁面範圍的節點,不會選取任何自定義組件中的節點)。
在當前頁面下選擇第一個匹配選擇器 selector 的節點。返回一個 NodesRef 對象實例,能夠用於獲取節點信息。
在當前頁面下選擇匹配選擇器 selector 的全部節點。
選擇顯示區域。可用於獲取顯示區域的尺寸、滾動位置等信息。
執行全部的請求。請求結果按請求次序構成數組,在callback的第一個參數中返回。
骨架屏組件指望能獲取匹配到的全部節點,做者使用的 SelectorQuery.selectAll()
。
先繪製一個層級較高的頁面,填充背景色,再講獲取到的節點,圓節點、長方形節點,用純灰色繪製。經過絕對定位的方式繪製骨架屏。
ready: function () {
const that = this;
//繪製背景
wx.createSelectorQuery().selectAll(`.${this.data.selector}`).boundingClientRect().exec(function(res){
that.setData({
'systemInfo.height': res[0][0].height + res[0][0].top
})
});
//繪製矩形
this.rectHandle();
//繪製圓形
this.radiusHandle();
},
methods: {
rectHandle: function () {
const that = this;
//繪製不帶樣式的節點
wx.createSelectorQuery().selectAll(`.${this.data.selector} >>> .${this.data.selector}-rect`).boundingClientRect().exec(function(res){
that.setData({
skeletonRectLists: res[0]
})
console.log(that.data);
});
},
radiusHandle: function () {
const that = this;
wx.createSelectorQuery().selectAll(`.${this.data.selector} >>> .${this.data.selector}-radius`).boundingClientRect().exec(function(res){
console.log(res);
that.setData({
skeletonCircleLists: res[0]
})
console.log(that.data);
});
},
}
複製代碼
>>>
爲微信小程序跨自定義組件的選擇器,用來獲取節點信息,具體細節請戳源碼。
我在使用的時候仍是組件式的,把源碼下載下來,拷貝到項目裏去,再使用,這種方式不是不行,就是不太方便。我前段時間封了個微信小程序自定義table組件爲npm,周下載量100+,就想着骨架屏也能夠封裝成npm,使用起來多香。
因而大家就看到上面的npm的使用方式,我給這個項目提了 pull request
,原做者 review
過代碼,改了一波合併了。這讓我開森了許久。😂😂😂 之後也想,多給開源項目提些PR,給前端社區作些貢獻。
還不會提PR的,看這裏👇, 阮一峯 Pull Request 的命令行管理