ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [vue] vue skeleton 사용하기
    프론트엔드/Vuejs 2020. 7. 13. 22:34

    프론트에서 개발하다보면 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 화면 구성]

     

    반응형

    댓글

Designed by Tistory.