반응형

프론트에서 개발하다보면 api 중에 시간소요가 1초 이상 소요되어 화면에 랜더링 되기 전에 어떤 구성된 화면이 나왔으면 하는 순간이 있습니다.

왜냐하면 api 로 데이터를 받아올 때 까지 로딩되는 화면에는 아무런 리스트 화면도 보여주지 않으면, 사용자 입장에서 어색한 느낌이 있습니다.

이럴때 쓰는 로딩 방식보고 skeleton 로딩이라고 합니다.

vue 에 라이브러리가 있나 찾아보았는데, 라이브러리 보다 css 만으로도 처리가 가능한 리소스를 찾아 내용 정리합니다.

1. vue skeletonBox 소스

<template>
  <span
    :style="{ height, width: computedWidth }"
    class="SkeletonBox"
  />
</template>

<script>
export default {
  name: `SkeletonBox`,
  props: {
    maxWidth: {
      default: 100,
      type: Number
    },
    minWidth: {
      default: 80,
      type: Number
    },
    height: {
      default: `1em`,
      type: String
    },
    width: {
      default: null,
      type: String
    }
  },
  computed: {
    computedWidth () {
      return this.width || `${Math.floor((0.9 * (this.maxWidth - this.minWidth)) + this.minWidth)}%`
    }
  }
}
</script>

<style lang="scss">
.SkeletonBox {
  display: inline-block;
  position: relative;
  vertical-align: middle;
  overflow: hidden;
  background-color: #DDDBDD;
  &::after {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    transform: translateX(-100%);
    background-image: linear-gradient(
      90deg,
      rgba(#fff, 0) 0,
      rgba(#fff, 0.2) 20%,
      rgba(#fff, 0.5) 60%,
      rgba(#fff, 0)
    );
    animation: shimmer 5s infinite;
    content: '';
  }
  @keyframes shimmer {
    100% {
      transform: translateX(100%);
    }
  }
}
</style>

2. 사용예시

<template>
<table summary="샘플">
  <colgroup>
    <col style="width:200px"/>
    <col style="width:340px"/>
    <col style="width:150px"/>
    <col/>
  </colgroup>
<tbody>
  <template v-if="isFirstLoading">
    <tr>
      <th><skeleton-box/></th>
      <td colspan="3"> <skeleton-box /><skeleton-box/><skeleton-box/></td>
    </tr>
    <tr>
        <th><skeleton-box/></th>
        <td colspan="3"> <skeleton-box/><skeleton-box/><skeleton-box/></td>
    </tr>
    <tr>
        <th><skeleton-box/></th>
        <td colspan="3"> <skeleton-box/><skeleton-box/><skeleton-box/></td>
    </tr>
    <tr>
        <th><skeleton-box/></th>
        <td colspan="3"> <skeleton-box/><skeleton-box/><skeleton-box/></td>
    </tr>
  </template>
  <template v-for="listItem in list">
   <!-- list 내용 -->
  </template>
</tbody>
</template>

<script>
import SkeletonBox from '@/components/common/SkeletonBox'

export default {
  name: 'ModalAttribute',
  components: {
    SkeletonBox
  },
  data () {
    return {
      isFirstLoading: true,
      list: []
    }
  },
}

위 소스코드가 예시로 짠 소스코드입니다.

간단히 설명하자면, isFirstLoading 이 true 이면, skelecton 박스가 보이게 되는 처리입니다.

 

아래 참고문헌의 코드를 그대로 구현 한 내용이고 다른 위의 예시 소스와 다른 내용은 라인 넓이를 랜덤함수로 구현된 내용은 수정했습니다.

넓이와 세로 px 값을 넣어줄 수 있어, 별다른 npm 다운 없이 위 소스코드만 복붙해서 사용가능합니다.

 

참고

https://markus.oberlehner.net/blog/skeleton-loading-animation-with-vue/  [skeleton 화면 구성]

 

반응형

+ Recent posts