用于小程序中的骨架屏

基于uni-app的一个骨架屏插件。

在使用的时候可以直接在components中引入组件quick-skeleton.vue。组件代码如下:

 1 <template> 2 <view 3 v-show="show" 4  :style="{ 5  width: systemInfo.width + ‘px‘, 6  height: systemInfo.height + ‘px‘, 7  backgroundColor: bgcolor, 8  position: ‘absolute‘, 9  left: 0, 10  top: 0, 11  zIndex: 9998, 12  overflow: ‘hidden‘ 13  }" 14 > 15 <view 16 v-for="(item, rect_idx) in skeletonRectLists" 17  :key="rect_idx + ‘rect‘" 18  :class="[loading == ‘chiaroscuro‘ ? ‘chiaroscuro‘ : ‘‘]" 19  :style="{ 20  width: item.width + ‘px‘, 21  height: item.height + ‘px‘, 22  backgroundColor: ‘#f4f4f‘, 23  position: ‘absolute‘, 24  left: item.left + ‘px‘, 25  top: item.top + ‘px‘ 26  }" 27 ></view> 28 <view 29 v-for="(item, circle_idx) in skeletonCircleLists" 30  :key="circle_idx + ‘circle‘" 31  :class="loading == ‘chiaroscuro‘ ? ‘chiaroscuro‘ : ‘‘" 32  :style="{ 33  width: item.width + ‘px‘, 34  height: item.height + ‘px‘, 35  backgroundColor: ‘#f4f4f‘, 36  borderRadius: item.width + ‘px‘, 37  position: ‘absolute‘, 38  left: item.left + ‘px‘, 39  top: item.top + ‘px‘ 40  }" 41 ></view> 42  43 <view class="spinbox" v-if="loading == ‘spin‘"><view class="spin"></view></view> 44 </view> 45 </template> 46  47 <script> 48 export default { 49  name: skeleton, 50  props: { 51  bgcolor: { 52  type: String, 53  value: #FFF 54  }, 55  selector: { 56  type: String, 57  value: skeleton 58  }, 59  loading: { 60  type: String, 61  value: spin 62  }, 63  show: { 64  type: Boolean, 65  value: false 66  } 67  }, 68  data() { 69 return { 70  loadingAni: [spin, chiaroscuro], 71  systemInfo: {}, 72  skeletonRectLists: [], 73  skeletonCircleLists: [] 74  }; 75  }, 76  watch: { 77  show() { 78 this.attachedAction(); 79 this.readyAction(); 80  } 81  }, 82  methods: { 83  attachedAction: function() { 84 //默认的首屏宽高,防止内容闪现 85  const systemInfo = uni.getSystemInfoSync(); 86 this.systemInfo = { 87  width: 750, 88  height: 1440 89  }; 90 this.loading = this.loadingAni.includes(this.loading) ? this.loading : spin; 91  }, 92  readyAction: function() { 93  const that = this; 94 //绘制背景 95  uni.createSelectorQuery() 96  .selectAll(`.${this.selector}`) 97  .boundingClientRect() 98  .exec(function(res) { 99  that.systemInfo.height = res[0][0].height + res[0][0].top;100  });101 102 //绘制矩形103 this.rectHandle();104 105 //绘制圆形106 this.radiusHandle();107  },108  rectHandle: function() {109  const that = this;110 111 //绘制不带样式的节点112  uni.createSelectorQuery()113  .selectAll(`.${this.selector}-rect`)114  .boundingClientRect()115  .exec(function(res) {116  that.skeletonRectLists = res[0];117  });118  },119  radiusHandle() {120  const that = this;121 122  uni.createSelectorQuery()123  .selectAll(`.${this.selector}-radius`)124  .boundingClientRect()125  .exec(function(res) {126  that.skeletonCircleLists = res[0];127  });128  }129  }130 };131 </script>132 133 <style>134 .spinbox {135  position: fixed;136  display: flex;137  justify-content: center;138  align-items: center;139  height: 100%;140  width: 100%;141  z-index: 9999;142 }143 .spin {144  display: inline-block;145  width: 64rpx;146  height: 64rpx;147 }148 .spin:after {149  content: ‘ ‘;150  display: block;151  width: 46rpx;152  height: 46rpx;153  margin: 1rpx;154  border-radius: 50%;155  border: 5rpx solid #409eff;156  border-color: #409eff transparent #409eff transparent;157  animation: spin 1.2s linear infinite;158 }159 @keyframes spin {160  0% {161  transform: rotate(0deg);162 }163  100% {164  transform: rotate(360deg);165 }166 }167 168 .chiaroscuro {169  width: 100%;170  height: 100%;171  background: #f4f4f4;172  animation-duration: 2s;173  animation-name: blink;174  animation-iteration-count: infinite;175 }176 177 @keyframes blink {178  0% {179  opacity: 0.5;180 }181  50% {182  opacity: 1;183 }184  100% {185  opacity: 0.5;186 }187 }188 189 @keyframes flush {190  0% {191  left: -100%;192 }193  50% {194  left: 0;195 }196  100% {197  left: 100%;198 }199 }200 .shine {201  animation: flush 2s linear infinite;202  position: absolute;203  top: 0;204  bottom: 0;205  width: 100%;206  background: linear-gradient(to left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.85) 50%, rgba(255, 255, 255, 0) 100%);207 }208 </style>

 

引入代码后,在需要加载骨架屏的页面中,为整个页面的盒子加一类名skeleton,并加一个兄弟节点quick-skeleton引入组件:

showSkeleton控制骨架屏是否显示;

骨架屏显示时catchtouchmovefixed控制页面是否可以滑动,这里用fixed让页面不可滑动;

bgcolor为骨架屏的背景颜色。其余属性不需改动,可以直接使用。

onReady()中控制骨架屏的加载,

若是即时加载的骨架屏,可以将_this.showSkeleton = false;放在接口调用成功之后,这样就实现了加载完后骨架屏自动消失的效果,这里暂用定时器来实现骨架屏的隐藏。

 1 <view> 2 <quick-skeleton 3 :show="showSkeleton" 4  ref="skeleton" 5  catchtouchmove="true" 6  fixed="true" 7  loading="chiaroscuro" 8  selector="skeleton" 9  bgcolor="#FFF"10  style="overflow: hidden;"11 ></quick-skeleton>12 <div class="page-content skeleton"></div>13 </view>14 <script>15  import quickSkeleton from ../../components/quick-skeleton.vue;16  export default {17  data() {18 return {19  showSkeleton: true,20  };21  },22  components: {23  quickSkeleton24  },25  onReady() {26  let _this = this;27  _this.$refs.skeleton.attachedAction();28  _this.$refs.skeleton.readyAction();29  setTimeout(function() {30  _this.showSkeleton = false;31  }, 3000);32  },33  }34 </script>

 

然后只要在页面中为想要生成骨架屏的元素加类名即可:

skeleton-radius表示圆形,skeleton-rect表示矩形

注:如果是利用v-for动态生成的结构,不能自动生成骨架屏,所以这里写出结构模板,给模板元素固定的宽高和背景颜色(与骨架屏相同),再用showSkeleton控制页面加载完成后隐藏结构模板。

 1 <div v-show="showSkeleton"> 2 <navigator hover-class="none" class=""> 3 <div class=""> 4 <div class="skeleton-radius" style="background: #f5f6f7;"><img class="" mode="" /></div> 5 <div class=""> 6 <span class="skeleton-rect" style="background: #f5f6f7;height: 26px;"></span> 7 <div class="skeleton-rect" style="background: #f5f6f7;height: 15px;"></div> 8 </div> 9 </div>10 <ul class="skeleton-rect" style="background: #f5f6f7;"></ul>11 <ul class="skeleton-rect" style="background: #f5f6f7;">12 <li class=""><img class="" mode="" /></li>13 <li class=""><img class="" mode="" /></li>14 <li class=""><img class="" mode="" /></li>15 </ul>16 <div class="skeleton-rect" style="background: #f5f6f7;height: 20px;"></div>17 </navigator>18 </div>

 

此骨架屏为颜色渐浅的闪烁效果,如果想要修改的话只需在组件中修改css。

效果如下:

技术图片

 

 

 

 

 

相关文章