效果圖

注意點:
1, 引入組建后, template 標簽內加入<skeleton selector="skeleton" bgcolor="#FFF" v-if="showSkeleton"></skeleton>
- 其中
v-if="showSkeleton"為顯示骨架屏顯示的參數。
2, data對象中設置showSkeleton: true // 默認一開始進入頁面加載骨架屏內容。
- 骨架屏渲染形狀有兩種:矩形 & 圓形
- 在想顯示骨架屏的區域的父級標簽的
class加入skeleton表示該class下的內容進行骨架屏元素加載 - 需要
渲染矩形,則在該元素上的class加入skeleton-rect - 需要渲染
圓形,則在該元素上的class加入skeleton-radius
3, 渲染數據。
- 渲染骨架屏的元素,需要先填充元素。使vue能夠根據數據的長度進行渲染。
- 列表類數據 字段值可為空。例如:
dataList: [ { title: '', author: '', pubTime: '', avatar: '' }, { title: '', author: '', pubTime: '', avatar: '' } ]
- 此時會渲染兩條數據內容
如果要應用小程序,把uni替換成wx即可
skeleton.vue
<template> <div> <div class="wrap" :style="{'width':systemInfo.width+'px','height':systemInfo.height+'px', 'background-color':bgcolor}"> <div v-for="(item,index) in skeletonRectLists" :index='index' :key='index' class="chiaroscuro" :style="{'width':item.width+'px','height':item.height+'px','background-color':'rgba(233, 2, 233,1)','position':'absolute','left':item.left+'px','top':item.top+'px'}"> </div> <div v-for="(item,index) in skeletonCircleLists" :index='index' :key="'info2-'+index" class="chiaroscuro" :style="{'width':item.width+'px','height':item.height+'px','background-color':'rgba(233, , 233,1)','border-radius':item.width+'px','position':'absolute','left':item.left+'px','top':item.top+'px'}"> </div> </div> </div> </template> <script> /* eslint-disable */ export default { props: { bgcolor: { type: String, value: '#FFF' }, selector: { type: String, value: 'skeleton' }, }, data() { return { systemInfo: {}, skeletonRectLists: [], skeletonCircleLists: [], }; }, components: {}, methods: { rectHandle: function() { const that = this; //繪制不帶樣式的節點 uni .createSelectorQuery() .selectAll(`.${this.selector}-rect`) .boundingClientRect() .exec(function(res) { that.skeletonRectLists = res[0]; }); }, radiusHandle: function() { const that = this; uni .createSelectorQuery() .selectAll(`.${this.selector}-radius`) .boundingClientRect() .exec(function(res) { console.log(res[0].length); that.skeletonCircleLists = res[0]; }); }, }, mounted: function() { //默認的首屏寬高,防止內容閃現 const systemInfo = uni.getSystemInfoSync(); (this.systemInfo = { width: systemInfo.windowWidth, height: systemInfo.windowHeight, }); const that = this; //繪制背景 uni .createSelectorQuery() .selectAll(`.${this.selector}`) .boundingClientRect() .exec(function(res) { that.systemInfo.height = res[0][0].height + res[0][0].top || 0; }); //繪制矩形 this.rectHandle(); //繪制圓形 this.radiusHandle(); }, }; /* eslint-enable */ </script> <style scoped> .wrap { position: absolute; left: 0; top: 0; z-index: 9998; overflow: hidden; } .chiaroscuro { animation-duration: 1s; animation-fill-mode: forwards; animation-iteration-count: infinite; animation-name: placeHolderShimmer; animation-timing-function: linear; background: #f6f7f8; background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%); background-size: 800px 104px; height: 40px; position: relative; } @keyframes placeHolderShimmer{ 0% { background-position: -468px 0 } 100% { background-position: 468px 0 } } </style>
index.vue 頁面
<template> <view class="content "> <skeleton selector="skeleton" bgcolor="#FFF" v-if="showSkeleton"></skeleton> <view class="skeleton"> <image class="logo skeleton-rect" src="/static/logo.png"></image> <view class="text-area skeleton-radius"> <text class="title">{{title}}</text> </view> </view> </view> </template> <script> import skeleton from '../index/skeleton' export default { data() { return { showSkeleton:true, title: 'Hello', } }, components:{ 'skeleton':skeleton }, created() { this.reloadData(); }, methods: { reloadData() { setTimeout(() => { this.showSkeleton = false }, 2000) }, } } </script>
