阅读 1125

uniapp的骨架屏生成指南(uniapp骨架屏实现原理)

常规首页的布局

一般而言,我们的首页的基础布局是包含的有:顶部搜索、轮播、金刚区、新闻简报、活动魔方。

<template>     <view class="content">         <!-- 顶部搜索 -->         <headerSerch></headerSerch>         <!-- 轮播 -->         <swiperBg></swiperBg>         <!-- 金刚区 -->         <menus></menus>         <!-- 新闻简报 -->         <news></news>         <!-- 活动魔方 -->         <activity></activity>         <!-- 骨架屏 -->         <skeleton :show="show"></skeleton>     </view> </template> <script>     import headerSerch from './components/headerSerch.vue'     import swiperBg from './components/swiperBg.vue'     import menus from './components/menus.vue'     import news from './components/news.vue'     import activity from './components/activity.vue'     import skeleton from './components/skeleton.vue'     export default {         components: {             headerSerch,             swiperBg,             menus,             news,             activity,             skeleton         },         data() {             return {                 show: true             }         },         mounted() {             setTimeout(()=>{                 this.show = false             },1200)         }     } </script> <style scoped> </style> 复制代码

skeleton组件的实现

代码如下,稍后给大家解释

<template> <!-- 骨架屏的高度宽度和背景,用绝对定位提高层级 --> <view v-if="show"> <view :style="{ width: windowWidth, height: windowHeight, backgroundColor: bgColor, position: 'absolute', zIndex: 9999, top: top, left: left }"> <view v-for="(item,index) in rectNodes" :key="index + 'Rect'" class="skeleton-fade" :style="{ width: item.width + 'px', height: item.height + 'px', backgroundColor: elColor, position: 'absolute', top: item.top + 'px', left: item.left + 'px' }"> </view> <view v-for="(item,index) in circleNodes" :key="index" class="skeleton-fade" :style="{ width: item.width + 'px', height: item.height + 'px', backgroundColor: elColor, borderRadius: item.width/2 + 'px',  position: 'absolute', top: item.top + 'px', left: item.left + 'px' }"> </view> </view> </view> </template> <script>     let systemInfo = uni.getSystemInfoSync();     export default {         name: 'skeleton',         props: {             show: {                 type: Boolean,                 default: true             }         },         data() {             return {                 windowWidth: systemInfo.windowWidth + 'px',                 windowHeight: systemInfo.windowHeight + 'px',                 bgColor: '#fff',                 elColor: '#e5e5e5',                 top: 0,                 left: 0,                 borderRadius: 10,                 rectNodes: [{                         "id": "",                         "dataset": {},                         "left": 15,                         "right": 87,                         "top": 4,                         "bottom": 30.5,                         "width": 72,                         "height": 32                 }, {                         "id": "",                         "dataset": {},                         "left": 102,                         "right": 360.20001220703125,                         "top": 4,                         "bottom": 32,                         "width": 258.20001220703125,                         "height": 32                 }, {                         "id": "",                         "dataset": {},                         "left": 15,                         "right": 360.20001220703125,                         "top": 46,                         "bottom": 171,                         "width": 345.20001220703125,                         "height": 125                 }, {                         "id": "",                         "dataset": {},                         "left": 15,                         "right": 360.20001220703125,                         "top": 343,                         "bottom": 373,                         "width": 345.20001220703125,                         "height": 30                 }, {                         "id": "",                         "dataset": {},                         "left": 15,                         "right": 183,                         "top": 383,                         "bottom": 533,                         "width": 168,                         "height": 150                 }, {                         "id": "",                         "dataset": {},                         "left": 188.1999969482422,                         "right": 360.1999969482422,                         "top": 384,                         "bottom": 457,                         "width": 172,                         "height": 73                 }, {                         "id": "",                         "dataset": {},                         "left": 188.1999969482422,                         "right": 360.1999969482422,                         "top": 459,                         "bottom": 532,                         "width": 172,                         "height": 73                 }],                 circleNodes: [{                         "id": "",                         "dataset": {},                         "left": 27.012500762939453,                         "right": 72.01250076293945,                         "top": 184,                         "bottom": 229,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 96.05000305175781,                         "right": 141.0500030517578,                         "top": 184,                         "bottom": 229,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 165.08750915527344,                         "right": 210.08750915527344,                         "top": 184,                         "bottom": 229,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 234.125,                         "right": 279.125,                         "top": 184,                         "bottom": 229,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 303.1625061035156,                         "right": 348.1625061035156,                         "top": 184,                         "bottom": 229,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 27.012500762939453,                         "right": 72.01250076293945,                         "top": 265,                         "bottom": 310,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 96.05000305175781,                         "right": 141.0500030517578,                         "top": 265,                         "bottom": 310,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 165.08750915527344,                         "right": 210.08750915527344,                         "top": 265,                         "bottom": 310,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 234.125,                         "right": 279.125,                         "top": 265,                         "bottom": 310,                         "width": 45,                         "height": 45                 }, {                         "id": "",                         "dataset": {},                         "left": 303.1625061035156,                         "right": 348.1625061035156,                         "top": 265,                         "bottom": 310,                         "width": 45,                         "height": 45                 }]             }         },         mounted() {             // 矩形骨架元素             this.getRectEls();             // 圆形骨架元素             this.getCircleEls();         },         methods: {             getRectEls() {                 let query = uni.createSelectorQuery().in(this.$parent)                 query.selectAll('.skeleton-rect').boundingClientRect(res => {                         console.log('rect', JSON.stringify(res));                 }).exec(function() {                 })             },             getCircleEls() {                 let query = uni.createSelectorQuery().in(this.$parent)                 query.selectAll('.skeleton-circle').boundingClientRect(res => {                         console.log('circle', JSON.stringify(res));                 }).exec(function() {                                  })             }         },     } </script> <style>     .skeleton-fade {         width: 100%;         height: 100%;         background: rgb(194, 207, 214);         animation-duration: 1.5s;         animation-name: blink;         animation-timing-function: ease-in-out;         animation-iteration-count: infinite;     }     @keyframes blink {         0% {             opacity: .4;         }         50% {             opacity: 1;         }         100% {             opacity: .4;         }     } </style> 复制代码

步骤一 设置骨架屏的基础样式

我们通过绝对定位的方式把组件的根元素提高层级,避免被父组件的其他组件覆盖掉。使用 uni.getSystemInfoSync()同步获取系统的可使用窗口宽度和可使用窗口高度并赋值给组件根元素的宽高。

<view :style="{ width: windowWidth, height: windowHeight, backgroundColor: bgColor, position: 'absolute', zIndex: 9999, top: top, left: left }">  ...... ...... </view> <script>     let systemInfo = uni.getSystemInfoSync();     export default {         name: 'skeleton',         props: {             show: {                 type: Boolean,                 default: true             },         },         data() {             return {                 windowWidth: systemInfo.windowWidth + 'px',                 windowHeight: systemInfo.windowHeight + 'px',                 bgColor: '#fff',                 top: 0,                 left: 0,             }         }      } </script> 复制代码

步骤二 渲染出占位的灰色块

通过uniapp的uni.createSelectorQuery()接口,查询页面带有指定类名的元素的位置和尺寸, 通过绝对定位的方式,用同样尺寸的灰色块定位到相同的位置。

在骨架屏中多数用的主要的矩形节点rectNodes 和圆形节点circleNodes。

首先给这些元素加上相同的skeleton-fade类,这个类的主要为了有一个灰色的背景并使用animate属性使其看到颜色的深浅变化。

<view :style="{ width: windowWidth, height: windowHeight, backgroundColor: bgColor, position: 'absolute', zIndex: 9999, top: top, left: left }">      <view v-for="(item,index) in rectNodes" :key="index + 'Rect'" class="skeleton-fade" :style="{         width: item.width + 'px',         height: item.height + 'px',         backgroundColor: elColor,         position: 'absolute',         top: item.top + 'px',         left: item.left + 'px'}">     </view>     <view v-for="(item,index) in circleNodes" :key="index" class="skeleton-fade" :style="{         width: item.width + 'px',         height: item.height + 'px',         backgroundColor: elColor,         borderRadius: item.width/2 + 'px',          position: 'absolute',         top: item.top + 'px',         left: item.left + 'px'}">     </view> </view> <script>     let systemInfo = uni.getSystemInfoSync();     export default {         name: 'skeleton',         props: {             show: {                 type: Boolean,                 default: true             },         },         data() {             return {                 windowWidth: systemInfo.windowWidth + 'px',                 windowHeight: systemInfo.windowHeight + 'px',                 bgColor: '#fff',                 top: 0,                 left: 0,                 rectNodes: [],                 circleNodes: []             }         }      } </script> <style>     .skeleton-fade {         width: 100%;         height: 100%;         background: rgb(194, 207, 214);         animation-duration: 1.5s;         animation-name: blink;         animation-timing-function: ease-in-out;         animation-iteration-count: infinite;     }     @keyframes blink {         0% {             opacity: .4;         }         50% {             opacity: 1;         }         100% {             opacity: .4;         }     } </style> 复制代码

按照官方的API使用说明,我们得在mounted 后进行调用方法。 在uni.createSelectorQuery()的后面加in(this.$parent)在微信小程序才能生效,在H5端不用加也生效。(我们主要是获取指定元素的位置和高度详细并赋值给rectNodes、circleNodes,所以得到之后可以把这两个方法删掉。)

mounted() {     // 矩形骨架元素     this.getRectEls();     // 圆形骨架元素     this.getCircleEls(); }, methods: {     getRectEls() {         let query = uni.createSelectorQuery().in(this.$parent)         query.selectAll('.skeleton-rect').boundingClientRect(res => {                 console.log('rect', JSON.stringify(res));         }).exec(function() {         })     },     getCircleEls() {         let query = uni.createSelectorQuery().in(this.$parent)         query.selectAll('.skeleton-circle').boundingClientRect(res => {                 console.log('circle', JSON.stringify(res));         }).exec(function() {         })     } }, 复制代码

如下图,在控制台上可以得到我们想到的节点信息。

微信截图_20211203205846.png

然后再复制粘贴给data中的rectNodes、circleNodes。 skeleton组件基本上就完成了。我们再做下优化,skeleton组件接收父组件传的show值,默认是true,当父组件的数据接口请求完成之后show设置为false。

大功告成,以下的在浏览器端和微信小程序端的骨架屏展示:

微信截图_20211203205906.png

微信截图_20211203205921.png


作者:清风programmer
链接:https://juejin.cn/post/7037476325480742920

伪原创工具 SEO网站优化  https://www.237it.com/ 


文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐