vue-cli3配置骨架屏方案
前言
最近在學(xué)vue
,準(zhǔn)備使用vue寫一個(gè)移動(dòng)端項(xiàng)目⊙欤考慮到首頁(yè)白屏優(yōu)化,需要實(shí)現(xiàn)骨架屏需求抬旺。
步驟
- 安裝
vue-skeleton-webpack-plugin
插件
npm install --save-dev vue-skeleton-webpack-plugin
- vue.config.js配置
const path = require('path')
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin');
module.exports = {
css: {
extract: true, // css拆分ExtractTextPlugin插件祥楣,默認(rèn)true - 骨架屏需要為true
},
configureWebpack: (config)=>{
// vue骨架屏插件配置
config.plugins.push(new SkeletonWebpackPlugin({
webpackConfig: {
entry: {
app: path.join(__dirname, './src/utils/skeleton.js'),
},
},
minimize: true,
quiet: true,
}))
},
}
- 新建一個(gè)
skeleton.js
文件放在src->utils
文件夾下面、
import Vue from 'vue';
import Skeleton from '../components/Skeleton/skeleton-2';
export default new Vue({
components: {
Skeleton,
},
render: h => h(Skeleton),
});
這個(gè)文件是用來注入骨架屏的
- 新建一個(gè)
skeleton-2.vue
骨架屏組件
<template>
<div class="skeleton page">
<div class="skeleton-nav"></div>
<div class="skeleton-swiper"></div>
<ul class="skeleton-tabs">
<li v-for="i in 8" class="skeleton-tabs-item"><span></span></li>
</ul>
<div class="skeleton-banner"></div>
<div v-for="i in 6" class="skeleton-productions"></div>
</div>
</template>
<style>
.skeleton {
position: relative;
height: 100%;
overflow: hidden;
padding: 15px;
box-sizing: border-box;
background: #fff;
}
.skeleton-nav {
height: 45px;
background: #eee;
margin-bottom: 15px;
}
.skeleton-swiper {
height: 160px;
background: #eee;
margin-bottom: 15px;
}
.skeleton-tabs {
list-style: none;
padding: 0;
margin: 0 -15px;
display: flex;
flex-wrap: wrap;
}
.skeleton-tabs-item {
width: 25%;
height: 55px;
box-sizing: border-box;
text-align: center;
margin-bottom: 15px;
}
.skeleton-tabs-item span {
display: inline-block;
width: 55px;
height: 55px;
border-radius: 55px;
background: #eee;
}
.skeleton-banner {
height: 60px;
background: #eee;
margin-bottom: 15px;
}
.skeleton-productions {
height: 20px;
margin-bottom: 15px;
background: #eee;
}
.skeleton {
padding: 10px;
}
.skeleton .skeleton-head,
.skeleton .skeleton-title,
.skeleton .skeleton-content {
background: rgb(194, 207, 214);
}
.skeleton-head {
width: 100px;
height: 100px;
float: left;
}
.skeleton-body {
margin-left: 110px;
}
.skeleton-title {
width: 500px;
height: 60px;
transform-origin: left;
animation: skeleton-stretch .5s linear infinite alternate;
}
.skeleton-content {
width: 260px;
height: 30px;
margin-top: 10px;
transform-origin: left;
animation: skeleton-stretch .5s -.3s linear infinite alternate;
}
@keyframes skeleton-stretch {
from {
transform: scalex(1);
}
to {
transform: scalex(.3);
}
}
</style>
- 新建一個(gè)
skeleton-1.vue
骨架屏組件
<template>
<div class="skeleton">
<div class="skeleton-head"></div>
<div class="skeleton-body">
<div class="skeleton-title"></div>
<div class="skeleton-content"></div>
</div>
</div>
</template>
<style>
.skeleton {
padding: 10px;
}
.skeleton .skeleton-head,
.skeleton .skeleton-title,
.skeleton .skeleton-content {
background: rgb(194, 207, 214);
}
.skeleton-head {
width: 100px;
height: 100px;
float: left;
}
.skeleton-body {
margin-left: 110px;
}
.skeleton-title {
width: 500px;
height: 60px;
transform-origin: left;
animation: skeleton-stretch 0.5s linear infinite alternate;
}
.skeleton-content {
width: 260px;
height: 30px;
margin-top: 10px;
transform-origin: left;
animation: skeleton-stretch 0.5s -0.3s linear infinite alternate;
}
@keyframes skeleton-stretch {
from {
transform: scalex(1);
}
to {
transform: scalex(0.3);
}
}
</style>
- 修改
main.js配置
const app = new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
- 重啟項(xiàng)目
思路
- 將骨架屏也看成路由組件,在構(gòu)建時(shí)使用 Vue 預(yù)渲染功能历葛,將骨架屏組件的渲染結(jié)果 HTML 片段插入 HTML 頁(yè)面模版的掛載點(diǎn)中嘀略,將樣式內(nèi)聯(lián)到 head 標(biāo)簽中。這樣等前端渲染完成時(shí)屎鳍,Vue 將使用客戶端混合问裕,把掛載點(diǎn)中的骨架屏內(nèi)容替換成真正的頁(yè)面內(nèi)容。
缺點(diǎn)
- 這種方案實(shí)現(xiàn)的是固定死的骨架(可以查看
skeleton-2.vue
skeleton-1.vue
)兩個(gè)文件粮宛,不能夠自動(dòng)根據(jù)頁(yè)面DOM結(jié)構(gòu)生成骨架
優(yōu)化的方向
- 餓了么團(tuán)隊(duì) page-skeleton-webpack-plugin開發(fā)的自動(dòng)生成頁(yè)面骨架屏方案