關於骨架屏與首屏渲染
- 2020 年 4 月 2 日
- 筆記
為了提升下用戶體驗,講下項目中這個骨架屏的處理吧。 項目相關:vue-mall
1、骨架屏
- 骨架屏就是可以由原來的在尚未載入前轉圈圈變成先給用戶展示出頁面的大致結構,這樣可以讓用戶有個更好的體驗感。
- 把網速調低點,以我們的mall項目的首頁載入為例:

2、實現方式
搜了下網上的教程,大概有這麼幾種方式: (1)使用圖片
- 就是直接麻煩設計切張圖片,控制這張圖片的隱藏和顯示。
(2)餓了嗎方案
- 第2種就是使用餓了嗎的page-skeleton-webpack-plugin這個插件。我在項目首頁中用了一下,效果不太理想,不知道是不是首頁的元素太多了。
- 它的配置還是比較簡簡單的的,但是項目很久沒維護了,還是有坑,你可以按照這篇文章的步驟一步步自己試一下–>參考。
(3)ssr渲染
- 第三種方案就是一種ssr的思路,使用的是
vue-server-renderer
這個插件。 - 我們知道vue在渲染好後會掛載到指定的
#app
這個元素上,這個方案就是先生成一個骨架屏的樣式文件,在#app
中先佔個位,達到在vue未掛載前有一個過渡效果。
<div id="app"> <!--vue-ssr-outlet--> </div>
// main.js new Vue({ router, store, render: h => h(App) }).$mount('#app')
- vue頁面骨架屏這篇文章也講的很清楚,我也是參考它試了一下,但是也是有問題。比如文章底部的這個提問:

- 我們的
vue
掛載到了#app
上面的這個渲染時間不是我們要解決目的所在,只是因為網路問題數據遲遲沒到所以造成頁面不完整,所以需要骨架屏。不知道看到這裡的看官對這個方案有沒有什麼好的解決辦法。
(4)藉助Puppeteer自動生成骨架屏
- 這個是利用chrome的puppeteer來獲取頁面的DOM結構,然後來生成骨架屏。考拉就是利用的這個方案,–>詳見。
- 當你看完了以後,你就會發現最後也是生成一張
base64
為的圖片做替換而已,還挺麻煩的,再個是puppeteer我不會啊。
(5)vue-content-loader庫
- 最後,我們mall項目中還是使用了這個比較簡單直接的方案。第
5
種其實就是第1種的衍生,使用vue-content-loader這個插件自己按照設計稿畫出一個大致的svg
圖,然後控制其顯示隱藏。
3、具體實現
- 先安裝下這個吧:
$ sudo npm install vue-content-loader -S # 切換鏡像以後還是報錯? $ sudo npm install --unsafe-perm vue-content-loader -S
- 以首頁為例,你可以參考設計稿把大概的輪廓畫出就可以了。–>Skeleton.vue
- 然後講下如何控制它的顯示與隱藏達到最好的一個首屏展示效果。
4、首屏渲染
- 以我們項目中的首頁的為例,一共有從上到下一共四個區域:
輪播圖
、金剛區
、精選會場
、推薦列表
。 - 由於前三個區域是用戶直接可見的,所以前三項的數據請求優先於最後一項,所以我們使用
promise
保證一下優先順序以及骨架屏的隱藏顯示。
mounted() { Promise.all([this.getBanner(), this.getCategory(), this.getSession()]) .then(() => { this.isSkeletonShow = false this.getGoodsList() }) }
- 使用
preloading
載入將首頁路由的優先順序提高一下:
const routes = [ { path: '*', name: 'Home', component: () => import(/* webpackPreload: true */ '@/views/home') } ]
- 最後我們把介面返回數據的時間delay,網速調低,刷新首頁後看到其實效果還可以:

5、小結
- 綜上所述,目前我能想到的骨架屏解決方案就是這樣的了,
mall
項目中也是這樣寫的,麻煩的地方就是需要骨架屏的頁面都需要自己去定位然後寫下骨架屏,不夠自動化,但是我覺得也還好吧,其實一個項目中幾個主要的頁面走下骨架屏就行了,並不需要每個頁面都骨架屏。 - 但是不管怎樣,這都是我的一種解決方案吧,不夠自動化確實是它的缺點,但從結果上和產出投入比來看,我覺得可以。
參考鏈接: vue-content-loader page-skeleton-webpack-plugin vue-content-loader vue頁面骨架屏