关于骨架屏与首屏渲染

865 阅读3分钟

为了提升下用户体验,讲下项目中这个骨架屏的处理吧。 项目相关: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页面骨架屏