首頁  >  文章  >  web前端  >  在Vue中有關如何實現單頁面骨架屏

在Vue中有關如何實現單頁面骨架屏

亚连
亚连原創
2018-06-20 18:09:062684瀏覽

這篇文章主要給大家介紹了關於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 &#39;./main.skeleton.vue&#39;
 export default {
 name: &#39;app&#39;,
 data () {
 return {
 init: false
 }
 },
 mounted () {
 // 这里模拟数据请求
 setTimeout(() => {
 this.init = true
 }, 250)
 },
 components: {
 mainSkeleton
 }
 }
</script>

ssr 渲染骨架屏

下面我用我靈魂畫師的筆法,畫出了大致的過程:

#首先創建我們的skeleton.entry.js

import Vue from &#39;vue&#39;;
import Skeleton from &#39;./skeleton.vue&#39;;
export default new Vue({
 components: {
 Skeleton
 },
 template: &#39;<skeleton />&#39;
});

當然這裡的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(&#39;path&#39;);
const merge = require(&#39;webpack-merge&#39;);
const baseWebpackConfig = require(&#39;./webpack.base.conf&#39;);
const nodeExternals = require(&#39;webpack-node-externals&#39;);
function resolve(dir) {
 return path.join(__dirname, dir);
}
module.exports = merge(baseWebpackConfig, {
 target: &#39;node&#39;,
 devtool: false,
 entry: {
 app: resolve(&#39;./src/skeleton.entry.js&#39;)
 },
 output: Object.assign({}, baseWebpackConfig.output, {
 libraryTarget: &#39;commonjs2&#39;
 }),
 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, &#39;utf-8&#39;);
 var skeletonCss = mfs.readFileSync(outputCssPath, &#39;utf-8&#39;);
 // 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(&#39;compilation&#39;, function (compilation) {
 // add listener for html-webpack-plugin
 compilation.plugin(&#39;html-webpack-plugin-before-html-processing&#39;, 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(&#39;</head>&#39;);
  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環境建構(詳細教學)

詳細介紹webpack中scss的相關設定

在Vue中專案元件化開發(詳細教學)

#如何實作webpack多入口檔案包裝設定

在JavaScript中如何實作多重繼承

以上是在Vue中有關如何實現單頁面骨架屏的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn