国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

關于Vue單頁面骨架屏實踐記錄

2019-11-19 14:44:16
字體:
來源:轉載
供稿:網友

關于骨架屏介紹

骨架屏的作用主要是在網絡請求較慢時,提供基礎占位,當數據加載完成,恢復數據展示。這樣給用戶一種很自然的過渡,不會造成頁面長時間白屏或者閃爍等情況。 常見的骨架屏實現方案有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> <div class="main-skeleton"> <w-skeleton height="80px"></w-skeleton> <div> <div class="skeleton-container"> <div class="skeleton">  <w-skeleton height="300px"></w-skeleton> </div> <w-skeleton height="45px"></w-skeleton> </div> <div class="skeleton-bottom"> <w-skeleton height="45px"></w-skeleton> </div> </div> </div></template>

當初次進入頁面的時候我們需要顯示骨架屏,數據加載完,我們需要移除骨架屏:

 <template> <div id="app"> <mainSkeleton v-if="!init"></mainSkeleton> <div v-else> <div class="body"></div> </div> </div></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> <div class="skeleton-wrapper"> <header class="skeleton-header"></header> <div class="skeleton-block"></div> </div></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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 星座| 旺苍县| 嘉禾县| 江阴市| 鄢陵县| 丹巴县| 泉州市| 柯坪县| 邢台市| 仁寿县| 安图县| 高清| 青浦区| 白水县| 西宁市| 寿光市| 高密市| 同仁县| 江西省| 文水县| 文化| 古田县| 绥宁县| 镇原县| 松江区| 韶山市| 焉耆| 莱西市| 集安市| 龙泉市| 平和县| 桑日县| 车致| 临澧县| 兖州市| 长沙县| 玛曲县| 明光市| 舞钢市| 仁寿县| 兴宁市|