关于Vue单页面骨架屏实践记录

网友投稿 350 2023-03-06


关于Vue单页面骨架屏实践记录

关于骨架屏介绍

骨架屏的作用主要是在网络请求较慢时,提供基础占位,当数据加载完成,恢复数据展示。这样给用户一种很自然的过渡,不会造成页面长时间白屏或者闪烁等情况。 常见的骨架屏实现方案有ssr服务端渲染和prerender两种解决方案。

这里主要通过代码为大家展示如何一步步做出这样一个骨架屏:

prerender 渲染骨架屏

本组件库骨http://架屏的实现也是基于预渲染去实现的,有关于预渲染更详细的介绍请参考这篇文章:处理 vue 单页面 Meta SEO的另一种思路 下面我们主要介绍其实现步骤,首先我们也是需要配置webpack-plugin,不过已经有实现好的prerender-spa-plugin可用

var path = require('path')

var PrerenderSpaPlugin = require('prerender-spa-plugin')

module.exports = {

// ...

plugins: [

new PrerenderSpaPlugin(

// Absolute path to compiled SPA

path.join(__dirname, '../dist'),

/http:/// List of routes to prerender

['/']

)

]

}

然后写好我们的骨架屏文件main.skeleton.vue

当初次进入页面的时候我们需要显示骨架屏,数据加载完,我们需要移除骨架屏:

ssr 渲染骨架屏

下面我用我灵魂画师的笔法,画出了大致的过程:

首先创建我们的skeleton.entry.js

import Vue from 'vue';

import Skeleton from './skeleton.vue';

export default new Vue({

components: {

Skeleton

},

template: ''

});

当然这里的skeleton.vue使我们事先写好的骨架屏组件,看起来可能是这样:

然后我们需要的是能把skeleton.entry.js编译成服务端渲染可用的bundle文件,所以我们需要有个编译骨架屏的webpack.ssr.conf.js文件:

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: []

});

接下来最终的步骤,就是编写我们的webpackPlugin,我们期望我们的webpackPlugin可以帮我们把入口文件编译成bundle,然后再通过vue-server-renderer来render bundle,最终产出响应的html片段和css片段,这里贴出核心代码:

// webpack start to work

var serverCompiler = webpack(serverWebpackConfig);

var mfs = new MFS();

// output to 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');

// create renderer with bundle

var renderer = createBundleRenderer(bundle);

// use vue ssr to render skeleton

renderer.renderToString({}, function (err, skeletonHtmliSpyDcMcyn) {

if (err) {

reject(err);

}

else {

resolve({skeletonHtml: skeletonHtml, skeletonCss: skeletonCss});

}

});

});

最后一步,我们对产出的html片段, css片段进行组装,产出最终的html,所以我们需要监听webpack 的编译挂载之前的事件:

compiler.plugin('compilation', function (compilation) {

// add listener for html-webpack-plugin

compilation.plugin('html-webpack-plugin-before-html-processing', function (htmlPluginData, callback) {

ssr(webpackConfig).then(function (ref) {

var skeletonHtml = ref.skeletonHtml;

var skeletonCss = ref.skeletonCss;

// insert inlined styles into html

var headTagEndPos = htmlPluginData.html.lastIndexOf('');

htmlPluginData.html = insertAt(htmlPluginData.html, (""), headTagEndPos);

// replace mounted point with ssr result in html

var appPos = htmlPluginData.html.lastIndexOf(insertAfter) + insertAfter.length;

htmlPluginData.html = insertAt(htmlPluginData.html, skeletonHtml, appPos);

callback(null, htmlPluginData);

});

});

});

github 地址: VV-UI/VV-UI

演示地址: vv-ui

文档地址:skeleton

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:入库接口测试用例图解说明(入库指令是什么)
下一篇:调用微信支付的接口开发(微信支付接口开发文档)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~