封装骨架屏组件

161 阅读1分钟

 原因

前面数据懒加载中提到过,组件数据懒加载是进入到可视区才开始加载数据,如果用户滚动过快,数据还没加载回来,会有白屏的效果,因此需要使用骨架屏组件进行优化

步骤

  1.  需要一个组件,做占位使用。这个占位组件有个专业术语:骨架屏组件。
  2.  属性:高,宽,背景,是否有闪动画,是否有淡入淡出动画。
  3.  这是一个公用组件,需要全局注册,将来这样的组件建议在vue插件中定义。
  4.  使用组件完成左侧分类骨架效果。

1.搭建静态骨架屏组件

在src/components/Skeleton/Skeleton.vue

<!-- //骨架组件 -->
<!-- 先写个死的,再改成活的 -->

<template>
  <div
    class="skeleton shan fade"
    style="width:300px;height:50px;"
  >
    <!-- 1 盒子-->
    <div class="block" :style="{ backgroundColor: '#ccc' }">
    </div>
    <!-- 2 闪效果 skeleton 伪元素 --->
  </div>
</template>

<style scoped lang="less">
.skeleton {
  display: inline-block;
  position: relative;
  overflow: hidden;
  vertical-align: middle;
  .block {
    width: 100%;
    height: 100%;
    border-radius: 2px;
  }
}
.shan {
  &::after {
    content: '';
    position: absolute;
    animation: shan 1.5s ease 0s infinite;
    top: 0;
    width: 50%;
    height: 100%;
    background: linear-gradient(
      to left,
      rgba(255, 255, 255, 0) 0,
      rgba(255, 255, 255, 0.3) 50%,
      rgba(255, 255, 255, 0) 100%
    );
    transform: skewX(-45deg);
  }
}
@keyframes shan {
  0% {
    left: -100%;
  }
  100% {
    left: 120%;
  }
}

.fade {
  animation: fade 1s linear infinite alternate;
}
@keyframes fade {
  from {
    opacity: 0.2;
  }
  to {
    opacity: 1;
  }
}
</style>

小结

fade:淡入淡出的效果   animated:动画  

定义props接收

最终代码如下

<!-- //骨架组件 -->
<!-- 先写个死的,再改成活的 -->
<script setup lang="ts">
// 定义props接收
const {bg='green', animated=false, fade=false} = defineProps<{
  width: number,
  height: number,
  bg?: string,
  animated?: boolean,
  fade?: boolean,
}>()

</script>
<template>
  <div
    class="skeleton"
    :class="{shan:animated, fade}"
    :style="{width:width+'px', height:height+'px'}"
  >
    <!-- 1 盒子-->
    <div class="block" :style="{ backgroundColor:bg }">
    </div>
    <!-- 2 闪效果 skeleton 伪元素 --->
  </div>
</template>

<style scoped lang="less">
.skeleton {
  display: inline-block;
  position: relative;
  overflow: hidden;
  vertical-align: middle;
  .block {
    width: 100%;
    height: 100%;
    border-radius: 2px;
  }
}
.shan {
  &::after {
    content: '';
    position: absolute;
    animation: shan 1.5s ease 0s infinite;
    top: 0;
    width: 50%;
    height: 100%;
    background: linear-gradient(
      to left,
      rgba(255, 255, 255, 0) 0,
      rgba(255, 255, 255, 0.3) 50%,
      rgba(255, 255, 255, 0) 100%
    );
    transform: skewX(-45deg);
  }
}
@keyframes shan {
  0% {
    left: -100%;
  }
  100% {
    left: 120%;
  }
}

.fade {
  animation: fade 1s linear infinite alternate;
}
@keyframes fade {
  from {
    opacity: 0.2;
  }
  to {
    opacity: 1;
  }
}
</style>

2.骨架组件-改进左侧分类

在分类组件中使用骨架屏组件

src/views/My/components/MyCate.vue

<template v-if="item.children">
  <RouterLink
              :to="`/cate/sub/${sub.id}`"
              :key="sub.id"
              v-for="sub in item.children?.slice(0, 2)"
              >
    {{ sub.name }}
    </RouterLink>
  </template>
  <template v-else>
  <Skeleton
               :width="60"
               :height="18"
               style="margin-right: 5px"
               bg="rgba(255,255,255,0.2)"
               animated
               />
  <Skeleton
               :width="50"
               :height="18"
               bg="rgba(255,255,255,0.2)"
               animated
               />
  </template>

3.骨架组件-全局注册(插件)

全局组件的基本使用

const app = createApp(App)

app.component('组件名',组件对象)

在v2 是 Vue.component('组件名',组件对象)

v2中插件 Vue.use

全局组件的使用-插件   

就是使用app.use

整体实现步骤

1.新建文件 components/index.ts

// 统一的注册所有的全局组件
import Skeleton from '@/components/Skeleton/Skeleton.vue'
// App 是在vue库中定义好的类型
import { App } from 'vue'
export default {
  install (app: App) {
    app.component('Skeleton', Skeleton)
  }
}

2.在main.ts中全局注册

import Cart from './components'
const app = createApp(App)
app.use(Cart)

在vue3中如果注册的是局部组件,那么props是有类型提示的,但是如果注册的是全局组件,props就没有类型提示了

这时,应该在src目录下新建一个文件 global.d.ts

import Skeleton from '@/components/Skeleton/Skeleton.vue'
// 参考:
declare module 'vue' {
  export interface GlobalComponents {
    Skeleton: typeof Skeleton
  }
}
export {}

在TS中定义了全局组件,有固定的套路让它具备提示效果