骨架屏概念已经很久了,实现骨架屏方式有很多种。下面介绍几种好用的骨架屏实现方案

page-skeleton-webpack-plugin 自动生成骨架屏 由ElemeFE团队开发

1.配置如下 基于vue cli3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const { SkeletonPlugin } = require('page-skeleton-webpack-plugin')
module.exports = {
chainWebpack: config => {
config.plugin('html').tap(opts => {
opts[0].minify = { removeComments: false }
return opts
})
config.plugin('SkeletonPlugin').use(SkeletonPlugin, [
{
pathname: path.resolve(__dirname, `./shell`), // 用来存储 shell 文件的地址
staticDir: path.resolve(__dirname, './dist'), // 最好和 `output.path` 相同
routes: ['/', '/about'] // 将需要生成骨架屏的路由添加到数组中
}
])
},
}

More info: vue cli 链式操作

shell 目录是用来存取生成的骨架屏目录。生成操作见:下面page-skeleton-webpack-plugin配置使用文档

vue cli3 下page-skeleton server listen at port: 8989报这个错误 按下修改

1
2
3
4
5
6
7
8
page-skeleton-webpack-plugin 包 下src/skeletonPlugin.js 25行 修改如下

SkeletonPlugin.prototype.createServer = function () { // eslint-disable-line func-names
if (!this.server) {
const server = this.server = new Server(this.options) // eslint-disable-line no-multi-assign
server.listen().catch(err => server.log.warn(err))
}
}

More info: page-skeleton-webpack-plugin有个fix分支未合并

More info: page-skeleton-webpack-plugin配置使用文档

2.html 里设置 <!-- shell --> 插件会替换此标签为对应的骨架屏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>eventcmswww</title>
</head>
<body>
<div id="app">
<!-- shell -->
</div>
<!-- built files will be auto injected -->
</body>
</html>

遇到的问题build后骨架屏没有出现

原因cli3 自动打开了打包注视删除操作。按上面设置removeComments false
打包后文件路径如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
dist
├── about
│   └── index.html
├── css
│   └── app.cdd9559b.css
├── favicon.ico
├── img
│   ├── card1.d9965849.png
│   ├── icons
│   └── logo.82b9c7a5.png
├── index.html
├── js
│   ├── app.1f058936.js
│   ├── app.1f058936.js.map
│   ├── chunk-vendors.5d7c9b8d.js
│   └── chunk-vendors.5d7c9b8d.js.map
├── manifest.json
├── precache-manifest.5dafe8fe95e326b40f63cb53925f6a27.js
├── robots.txt
└── service-worker.js

使用感受

1.会自动生成对应的静态文件 但是其他没有骨架屏的页面进入 会加载默认的骨架屏 此处不友好
2.骨架屏展示 到消失的原理:
    a.会根据对应的路由生成对应的html 文件
    b.浏览器加载对应的页面在 js加载之前首先渲染静态dom骨架屏展示出现
    c.页面里js加载完成后 加载对应的路由 替换index.html 里 <div id=app ></div> 中间的内容骨架屏消失

vue-skeleton-webpack-plugin 根据已有骨架屏自动插入对应的路由

1.vue.config.js配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin')
const path = require('path')
module.exports = {
chainWebpack: config => {
config.plugin('SkeletonWebpackPlugin').use(SkeletonWebpackPlugin,[
{
webpackConfig: {
entry:{
app: path.resolve(__dirname,'./src/entry-skeleton.js')
}
},
quiet: true,
minimize: true,
router: {
mode: 'history', //router 模式
routes: [
{
path: '/seo',
skeletonId: 'skeletonIndex'
},
{
path: '/seo/about',
skeletonId: 'skeletonAbout'
},
]
}
}
])
}
}

2.entry-skeleton.js 文件设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue';
import Skeleton1 from './skeleton/Skeleton1.vue';
import Skeleton2 from './skeleton/Skeleton2.vue';

export default new Vue({
components: {
Skeleton1,
Skeleton2
},
template: `
<div>
<skeleton1 id="skeletonIndex" style="display:none"/>
<skeleton2 id="skeletonAbout" style="display:none"/>
</div>
`
});
注:
    1.id[skeletonIndex] 与vue.config.js里的skeletonId 想对应
    2.entry-skeleton.js 里引入的Skeleton1.vue 文件就是骨架屏文件

使用感受

1.此插件会把骨架屏文件根据配置打包到 index.html里 通过路由path与skeletonId 来匹配展示
2.可以对骨架屏做路由 开发环境下调试开发
3.需要手写骨架屏文件  比较麻烦

vue-content-loader 快速自定义出骨架屏 react-content-loader(react)

一个快速开发 绚丽骨架屏的框架

More info: vue-content-loader

More info: 基于vue-content-loader在线设置骨架屏