前言:用户在等待数据渲染的时候,有可能因为网络速度慢,手机硬件等问题,造成等待时间延长,使得用户体验不好。

之前的做法是放个加载中的图标,而现在是直接根据页面原有元素绘制图形的方式,让用户有种页面就快渲染好的错觉。

参考资料:

https://ext.dcloud.net.cn/plugin?id=256

备注:我是准备应用到项目中,从uniapp的插件市场下载了demo,结果出现一些小问题,在下载下来的demo做了些小修改

加载过程效果图:如图,从图一到图二,最底部多出了一个动态加载的骨架,模拟同一页面多个数据请求(每个请求所需时间不同),

  我这边的处理是在每个请求的回调中,先赋值渲染的动态数据,再重新抓取需要绘制的动态元素(因为绘制的元素需要先有数据给它撑开),

  最后页面中的请求基本完成的时候,隐藏骨架屏,显示原先的页面

问题:对demo有更好建议的可以提出来哈,相互学习一下

uniapp实现骨架屏uniapp实现骨架屏uniapp实现骨架屏

代码如下:

组件

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

相关文章:

  • 2021-12-03
  • 2021-12-22
  • 2021-12-03
  • 2021-11-08
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-12-06
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2023-03-21
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案