tui-skeleton

tui-skeleton 骨架屏,数据请求时常见到锁屏的loading动画,而现在越来越多的产品倾向于使用Skeleton Screen替代 。

组件结构

  1. <view class="tui-skeleton-cmomon tui-skeleton-box" :style="{width: winWidth+'px', height:winHeight+'px', backgroundColor:backgroundColor}">
  2. <view class="tui-skeleton-cmomon" v-for="(item,index) in skeletonElements" :key="index" :style="{width: item.width+'px', height:item.height+'px', left: item.left+'px', top: item.top+'px',backgroundColor: skeletonBgColor,borderRadius:getRadius(item.skeletonType,borderRadius)}"></view>
  3. <view class="tui-loading" :class="[getLoadingType(loadingType)]" v-if="isLoading"></view>
  4. </view>

组件脚本

  1. <script>
  2. export default {
  3. name: "tuiSkeleton",
  4. props: {
  5. //选择器(外层容器)
  6. selector: {
  7. type: String,
  8. default: "tui-skeleton"
  9. },
  10. //外层容器背景颜色
  11. backgroundColor: {
  12. type: String,
  13. default: "#fff"
  14. },
  15. //骨架元素背景颜色
  16. skeletonBgColor: {
  17. type: String,
  18. default: "#e9e9e9"
  19. },
  20. //骨架元素类型:矩形,圆形,带圆角矩形["rect","circular","fillet"]
  21. //默认所有,根据页面情况进行传值
  22. //页面对应元素class为:tui-skeleton-rect,tui-skeleton-circular,tui-skeleton-fillet
  23. //如果传入的值不在下列数组中,则为自定义class值,默认按矩形渲染
  24. skeletonType: {
  25. type: Array,
  26. default () {
  27. return ["rect", "circular", "fillet"]
  28. }
  29. },
  30. //圆角值,skeletonType=fillet时生效
  31. borderRadius: {
  32. type: String,
  33. default: "16rpx"
  34. },
  35. //骨架屏预生成数据:提前生成好的数据,当传入该属性值时,则不会再次查找子节点信息
  36. preloadData: {
  37. type: Array,
  38. default () {
  39. return []
  40. }
  41. },
  42. //是否需要loading
  43. isLoading: {
  44. type: Boolean,
  45. default: true
  46. },
  47. //loading类型[1-10]
  48. loadingType: {
  49. type: Number,
  50. default: 1
  51. }
  52. },
  53. created() {
  54. const res = uni.getSystemInfoSync();
  55. this.winWidth = res.windowWidth;
  56. this.winHeight = res.windowHeight;
  57. //如果有预生成数据,则直接使用
  58. this.isPreload(true)
  59. },
  60. // #ifdef H5
  61. mounted() {
  62. this.$nextTick(() => {
  63. this.nodesRef(`.${this.selector}`).then((res) => {
  64. this.winHeight = res[0].height + Math.abs(res[0].top)
  65. });
  66. !this.isPreload() && this.selectorQuery()
  67. })
  68. },
  69. // #endif
  70. onReady() {
  71. this.nodesRef(`.${this.selector}`).then((res) => {
  72. this.winHeight = res[0].height + Math.abs(res[0].top)
  73. });
  74. !this.isPreload() && this.selectorQuery()
  75. },
  76. data() {
  77. return {
  78. winWidth: 375,
  79. winHeight: 800,
  80. skeletonElements: []
  81. };
  82. },
  83. methods: {
  84. getLoadingType: function(type) {
  85. let value = 1
  86. if (type && type > 0 && type < 11) {
  87. value = type
  88. }
  89. return 'tui-loading-' + value
  90. },
  91. getRadius: function(type, val) {
  92. let radius = "0"
  93. if (type == "circular") {
  94. radius = "50%"
  95. } else if (type == "fillet") {
  96. radius = val
  97. }
  98. return radius;
  99. },
  100. isPreload(init) {
  101. let preloadData = this.preloadData || []
  102. if (preloadData.length) {
  103. init && (this.skeletonElements = preloadData)
  104. return true
  105. }
  106. return false
  107. },
  108. async selectorQuery() {
  109. let skeletonType = this.skeletonType || []
  110. let nodes = []
  111. for (let item of skeletonType) {
  112. let className = `.${this.selector} >>> .${item}`
  113. // #ifdef H5
  114. className = `.${item}`
  115. // #endif
  116. if (~"rect_circular_fillet".indexOf(item)) {
  117. // #ifndef H5
  118. className = `.${this.selector} >>> .${this.selector}-${item}`
  119. // #endif
  120. // #ifdef H5
  121. className = `.${this.selector}-${item}`
  122. // #endif
  123. }
  124. await this.nodesRef(className).then((res) => {
  125. res.map(d => {
  126. d.skeletonType = item
  127. })
  128. nodes = nodes.concat(res)
  129. })
  130. }
  131. this.skeletonElements = nodes
  132. },
  133. async nodesRef(className) {
  134. return await new Promise((resolve, reject) => {
  135. uni.createSelectorQuery().selectAll(className).boundingClientRect((res) => {
  136. if (res) {
  137. resolve(res);
  138. } else {
  139. reject(res)
  140. }
  141. }).exec();
  142. })
  143. }
  144. }
  145. }
  146. </script>

组件样式

... 此处省略n行

脚本说明

props

参数类型描述默认值
selectorString选择器(外层容器)tui-skeleton
backgroundColorString外层容器背景颜色#fff
skeletonBgColorString骨架元素背景颜色#e9e9e9
skeletonTypeArray骨架元素类型:矩形,圆形,带圆角矩形["rect", "circular", "fillet"]
borderRadiusString圆角值,skeletonType=fillet时生效16rpx
preloadDataArray骨架屏预生成数据[]
isLoadingBoolean是否需要loadingtrue
loadingTypeNumberloading类型[1-10]1

methods

名称描述
getLoadingType获取loading类型
getRadius获取圆角值
isPreload骨架屏是否有预生成数据
selectorQuery查找骨架元素节点
nodesRef查找骨架元素节点api执行

示例

... 此处省略n行,下载源码查看

预览图

#

tui-skeleton 骨架屏 - 图1