這篇文章主要給大家介紹了關於Vue單頁骨架屏實踐的相關資料,文中透過範例程式碼介紹的非常詳細,對大家學習或使用vue具有一定的參考學習價值,需要的朋友們下面來一起看看吧。
關於骨架螢幕介紹
骨架螢幕的作用主要是在網路請求較慢時,提供基礎佔位,當資料載入完成,恢復資料展示。這樣給使用者一種很自然的過渡,不會造成頁面長時間白屏或閃爍等狀況。常見的骨架螢幕實作方案有ssr服務端渲染和prerender兩種解決方案。
這裡主要透過程式碼為大家展示如何一步步做出這樣一個骨架螢幕:
#prerender 渲染骨架螢幕
本元件庫骨架螢幕的實作也是基於預渲染去實現的,有關於預渲染更詳細的介紹請參考這篇文章:處理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'), // List of routes to prerender ['/'] ) ] }
然後寫好我們的骨架螢幕檔案main.skeleton.vue
<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>
當初次進入頁面的時候我們需要顯示骨架屏,資料載入完,我們需要移除骨架屏:
<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>
ssr 渲染骨架屏
下面我用我靈魂畫師的筆法,畫出了大致的過程:
#首先創建我們的skeleton.entry.js
import Vue from 'vue'; import Skeleton from './skeleton.vue'; export default new Vue({ components: { Skeleton }, template: '<skeleton />' });
當然這裡的skeleton.vue使我們事先寫好的骨架螢幕元件,看起來可能是這樣:
<template> <p class="skeleton-wrapper"> <header class="skeleton-header"></header> <p class="skeleton-block"></p> </p> </template>
然後我們需要的是能把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, skeletonHtml) { 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('</head>'); htmlPluginData.html = insertAt(htmlPluginData.html, ("<style>" + skeletonCss + "</style>"), 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
上面是我整理給大家的,希望今後會對大家有幫助。
相關文章:
詳細解答Webpack Babel React環境建構(詳細教學)
以上是在Vue中有關如何實現單頁面骨架屏的詳細內容。更多資訊請關注PHP中文網其他相關文章!