ElementPlus Skeleton 骨架屏

2021-09-26 15:45 更新

Skeleton 骨架屏

在需要等待加載內(nèi)容的位置設(shè)置一個骨架屏,某些場景下比 Loading 的視覺效果更好。

基礎(chǔ)用法

基礎(chǔ)的骨架效果。


<template>
  <el-skeleton />
</template>

更多參數(shù)

可以配置骨架屏段落數(shù)量,以便更接近真實渲染效果。顯示的數(shù)量會比傳入的數(shù)量多 1,首行會被渲染一個長度 33% 的段首。


<template>
  <el-skeleton :rows="5" />
</template>

動畫效果

顯示動畫效果。


<template>
  <el-skeleton :rows="5" animated />
</template>

自定義樣式

ElementPlus 提供的排版模式有時候并不滿足要求,當您想要用自己定義的模板時,可以通過一個具名 Slot 來自己設(shè)定模板。

我們提供了不同的模板單元可供使用,具體可選值請看 API 詳細描述。 建議在描述模板的時候,盡量靠近真實的 DOM 結(jié)構(gòu),這樣可以避免 DOM 高度差距引起的抖動。


<template>
  <el-skeleton style="width: 240px">
    <template #template>
      <el-skeleton-item variant="image" style="width: 240px; height: 240px;" />
      <div style="padding: 14px;">
        <el-skeleton-item variant="p" style="width: 50%" />
        <div
          style="display: flex; align-items: center; justify-items: space-between;"
        >
          <el-skeleton-item variant="text" style="margin-right: 16px;" />
          <el-skeleton-item variant="text" style="width: 30%;" />
        </div>
      </div>
    </template>
  </el-skeleton>
</template>

Loading 狀態(tài)

當 Loading 結(jié)束之后,我們往往需要顯示真實的 UI,可以通過 loading 的值來控制是否顯示真實的 DOM。然后通過 具名 Slot 來設(shè)置當 loading 結(jié)束之后需要展示的 UI。


<template>
  <el-space direction="vertical" alignment="flex-start">
    <div>
      <label style="margin-right: 16px;">切換 Loading</label>
      <el-switch v-model="loading" />
    </div>
    <el-skeleton style="width: 240px" :loading="loading" animated>
      <template #template>
        <el-skeleton-item
          variant="image"
          style="width: 240px; height: 240px;"
        />
        <div style="padding: 14px;">
          <el-skeleton-item variant="h3" style="width: 50%;" />
          <div
            style="display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px;"
          >
            <el-skeleton-item variant="text" style="margin-right: 16px;" />
            <el-skeleton-item variant="text" style="width: 30%;" />
          </div>
        </div>
      </template>
      <template #default>
        <el-card :body-style="{ padding: '0px', marginBottom: '1px' }">
          <img
            src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png" rel="external nofollow"  rel="external nofollow" 
            class="image"
          />
          <div style="padding: 14px;">
            <span>好吃的漢堡</span>
            <div class="bottom card-header">
              <span class="time">{{ currentDate }}</span>
              <el-button type="text" class="button">操作按鈕</el-button>
            </div>
          </div>
        </el-card>
      </template>
    </el-skeleton>
  </el-space>
</template>

<script>
  import { defineComponent } from 'vue'

  const dayjs = require('dayjs')

  export default defineComponent({
    data() {
      return {
        loading: true,
        currentDate: dayjs().format('YYYY-MM-DD'),
      }
    },
  })
</script>

渲染多條數(shù)據(jù)

大多時候, 骨架屏都被用來渲染列表, 當我們需要在從服務(wù)器獲取數(shù)據(jù)的時候來渲染一個假的 UI。利用 count 這個屬性就能控制渲染多少條假的數(shù)據(jù)在頁面上

請注意, 請盡可能的將 count 的大小保持在最小狀態(tài), 即使是假的 UI, DOM 元素多了之后, 照樣會引起性能問題, 并且在骨架屏銷毀時所消耗的時間也會更長(相對的)。


<template>
  <el-space direction="vertical" alignment="flex-start">
    <el-button @click="setLoading">點我重新加載</el-button>
    <el-skeleton style="width: 240px" :loading="loading" animated :count="3">
      <template #template>
        <el-skeleton-item
          variant="image"
          style="width: 400px; height: 267px;"
        />
        <div style="padding: 14px;">
          <el-skeleton-item variant="h3" style="width: 50%;" />
          <div
            style="display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px;"
          >
            <el-skeleton-item variant="text" style="margin-right: 16px;" />
            <el-skeleton-item variant="text" style="width: 30%;" />
          </div>
        </div>
      </template>
      <template #default>
        <el-card
          :body-style="{ padding: '0px', marginBottom: '1px' }"
          v-for="item in lists"
          :key="item.name"
        >
          <img :src="item.imgUrl" class="image multi-content" />
          <div style="padding: 14px;">
            <span>{{ item.name }}</span>
            <div class="bottom card-header">
              <span class="time">{{ currentDate }}</span>
              <el-button type="text" class="button">操作按鈕</el-button>
            </div>
          </div>
        </el-card>
      </template>
    </el-skeleton>
  </el-space>
</template>

<script>
  import { defineComponent } from 'vue'

  const dayjs = require('dayjs')

  export default defineComponent({
    data() {
      return {
        loading: true,
        currentDate: dayjs().format('YYYY-MM-DD'),
        lists: [],
      }
    },
    mounted() {
      this.loading = false
      this.lists = [
        {
          imgUrl:
            'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
          name: '鹿',
        },
        {
          imgUrl:
            'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
          name: '馬',
        },
        {
          imgUrl:
            'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
          name: '山獅',
        },
      ]
    },
    methods: {
      setLoading() {
        this.loading = true
        setTimeout(() => (this.loading = false), 2000)
      },
    },
  })
</script>

防止渲染抖動

有的時候,API 的請求回來的特別快,往往骨架占位剛剛被渲染,真實的數(shù)據(jù)就已經(jīng)回來了,用戶的界面會突然一閃,此時為了避免這種情況,就需要通過 throttle 屬性來避免這個問題。


<template>
  <el-space direction="vertical" alignment="flex-start">
    <div>
      <label style="margin-right: 16px;">切換 Loading</label>
      <el-switch v-model="loading" />
    </div>
    <el-skeleton
      style="width: 240px"
      :loading="loading"
      animated
      :throttle="500"
    >
      <template #template>
        <el-skeleton-item
          variant="image"
          style="width: 240px; height: 240px;"
        />
        <div style="padding: 14px;">
          <el-skeleton-item variant="h3" style="width: 50%;" />
          <div
            style="display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px;"
          >
            <el-skeleton-item variant="text" style="margin-right: 16px;" />
            <el-skeleton-item variant="text" style="width: 30%;" />
          </div>
        </div>
      </template>
      <template #default>
        <el-card :body-style="{ padding: '0px', marginBottom: '1px' }">
          <img
            src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png" rel="external nofollow"  rel="external nofollow" 
            class="image"
          />
          <div style="padding: 14px;">
            <span>好吃的漢堡</span>
            <div class="bottom card-header">
              <span class="time">{{ currentDate }}</span>
              <el-button type="text" class="button">操作按鈕</el-button>
            </div>
          </div>
        </el-card>
      </template>
    </el-skeleton>
  </el-space>
</template>

<script>
  import { defineComponent } from 'vue'

  const dayjs = require('dayjs')

  export default defineComponent({
    data() {
      return {
        loading: false,
        currentDate: dayjs().format('YYYY-MM-DD'),
      }
    },
  })
</script>

Skeleton Attributes

參數(shù)說明類型可選值默認值
animated是否使用動畫booleantrue / falsefalse
count渲染多少個 template, 建議使用盡可能小的數(shù)字numberinteger1
loading是否顯示真實的 DOM 結(jié)構(gòu)booleantrue / falsefalse
rows骨架屏段落數(shù)量number正整數(shù)3
throttle延遲占位 DOM 渲染的時間, 單位是毫秒number正整數(shù)0

Skeleton Item Attributes

參數(shù)說明類型可選值默認值
variant當前顯示的占位元素的樣式Enum(string)p / text / h1 / h3 / text / caption / button / image / circle / recttext

Skeleton Slots

namedescription
default用來展示真實 UI
template用來展示自定義占位符


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號