这篇文章主要给大家介绍了关于Vue单页面骨架屏实践的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用vue具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
关于骨架屏介绍
骨架屏的作用主要是在网络请求较慢时,提供基础占位,当数据加载完成,恢复数据展示。这样给用户一种很自然的过渡,不会造成页面长时间白屏或者闪烁等情况。 常见的骨架屏实现方案有ssr服务端渲染和prerender两种解决方案。
这里主要通过代码为大家展示如何一步步做出这样一个骨架屏:

prerender 渲染骨架屏
本组件库骨架屏的实现也是基于预渲染去实现的,有关于预渲染更详细的介绍请参考这篇文章:处理 Vue 单页面 Meta SEO的另一种思路 下面我们主要介绍其实现步骤,首先我们也是需要配置webpack-plugin,不过已经有实现好的prerender-spa-plugin可用
1 2 3 4 5 6 7 8 9 10 11 12 13 | var path = require ('path')
var PrerenderSpaPlugin = require ('prerender-spa-plugin')
module.exports = {
plugins: [
new PrerenderSpaPlugin(
path.join(__dirname, '../dist'),
['/']
)
]
}
|
Salin selepas log masuk
然后写好我们的骨架屏文件main.skeleton.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <template>
<p class = "main-skeleton" >
<w-skeleton height= "80px" ></w-skeleton>
<p>
<p class = "skeleton-container" >
<p class = "skeleton" >
<w-skeleton height= "300px" ></w-skeleton>
</p>
<w-skeleton height= "45px" ></w-skeleton>
</p>
<p class = "skeleton-bottom" >
<w-skeleton height= "45px" ></w-skeleton>
</p>
</p>
</p>
</template>
|
Salin selepas log masuk
当初次进入页面的时候我们需要显示骨架屏,数据加载完,我们需要移除骨架屏:
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 | <template>
<p id= "app" >
<mainSkeleton v- if = "!init" ></mainSkeleton>
<p v- else >
<p class = "body" ></p>
</p>
</p>
</template>
<script>
import mainSkeleton from './main.skeleton.vue'
export default {
name: 'app',
data () {
return {
init: false
}
},
mounted () {
setTimeout(() => {
this.init = true
}, 250)
},
components: {
mainSkeleton
}
}
</script>
|
Salin selepas log masuk
ssr 渲染骨架屏
下面我用我灵魂画师的笔法,画出了大致的过程:

首先创建我们的skeleton.entry.js
1 2 3 4 5 6 7 8 | import Vue from 'vue';
import Skeleton from './skeleton.vue';
export default new Vue({
components: {
Skeleton
},
template: '<skeleton />'
});
|
Salin selepas log masuk
当然这里的skeleton.vue使我们事先写好的骨架屏组件,看起来可能是这样:
1 2 3 4 5 6 | <template>
<p class = "skeleton-wrapper" >
<header class = "skeleton-header" ></header>
<p class = "skeleton-block" ></p>
</p>
</template>
|
Salin selepas log masuk
然后我们需要的是能把skeleton.entry.js编译成服务端渲染可用的bundle文件,所以我们需要有个编译骨架屏的webpack.ssr.conf.js文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | const path = require ('path');
const merge = require ('webpack-merge');
const baseWebpackConfig = require ('./webpack.base.conf');
const nodeExternals = require ('webpack-node-externals');
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = merge(baseWebpackConfig, {
target: 'node',
devtool: false,
entry: {
app: resolve('./src/skeleton.entry.js')
},
output: Object.assign({}, baseWebpackConfig.output, {
libraryTarget: 'commonjs2'
}),
externals: nodeExternals({
whitelist: /\.css$/
}),
plugins: []
});
|
Salin selepas log masuk
接下来最终的步骤,就是编写我们的webpackPlugin,我们期望我们的webpackPlugin可以帮我们把入口文件编译成bundle,然后再通过vue-server-renderer来render bundle,最终产出响应的html片段和css片段,这里贴出核心代码:
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 31 32 | var serverCompiler = webpack(serverWebpackConfig);
var mfs = new MFS();
serverCompiler.outputFileSystem = mfs;
serverCompiler.watch({}, function (err, stats) {
if (err) {
reject(err);
return ;
}
stats = stats.toJson();
stats.errors.forEach( function (err) {
console.error(err);
});
stats.warnings.forEach( function (err) {
console.warn(err);
});
var bundle = mfs.readFileSync(outputPath, 'utf-8');
var skeletonCss = mfs.readFileSync(outputCssPath, 'utf-8');
var renderer = createBundleRenderer(bundle);
renderer.renderToString({}, function (err, skeletonHtml) {
if (err) {
reject(err);
}
else {
resolve({skeletonHtml: skeletonHtml, skeletonCss: skeletonCss});
}
});
});
|
Salin selepas log masuk
最后一步,我们对产出的html片段, css片段进行组装,产出最终的html,所以我们需要监听webpack 的编译挂载之前的事件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-before-html-processing', function (htmlPluginData, callback) {
ssr(webpackConfig).then( function (ref) {
var skeletonHtml = ref.skeletonHtml;
var skeletonCss = ref.skeletonCss;
var headTagEndPos = htmlPluginData.html.lastIndexOf('</head>');
htmlPluginData.html = insertAt(htmlPluginData.html, ( "<style>" + skeletonCss + "</style>" ), headTagEndPos);
var appPos = htmlPluginData.html.lastIndexOf(insertAfter) + insertAfter.length;
htmlPluginData.html = insertAt(htmlPluginData.html, skeletonHtml, appPos);
callback(null, htmlPluginData);
});
});
});
|
Salin selepas log masuk
github 地址: VV-UI/VV-UI
演示地址: vv-ui
文档地址:skeleton
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
详细解答Webpack+Babel+React环境搭建(详细教程)
详细介绍webpack中scss的相关配置
在Vue中项目组件化开发(详细教程)
如何实现webpack多入口文件打包配置
在JavaScript中如何实现多重继承
Atas ialah kandungan terperinci 在Vue中有关如何实现单页面骨架屏. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!