Vue頁面顯示骨架屏

Vue頁面顯示骨架屏css

1.什麼是骨架屏幕?html

在頁面加載數據以前,有一段空白時間,要麼用loading加載,要麼就用骨架屏。vue

 

2.如何快速用Vue實現骨架屏效果?node

#①直接把下面的CSS代碼複製,粘貼到vue項目的index.html <head>...</head>裏面webpack

<style>
  .skeleton {
    position: fixed;
    height: 100%;
    overflow: hidden;
    padding: 15px;
    box-sizing: border-box;
    background: #fff;
    width: 98%;
    top: 0;
  }
  .skeleton-nav {
    height: 110px;
    background: #eee;
    margin-bottom: 15px;
  }
  .skeleton-swiper {
    height: 440px;
    background: #eee;
    margin-bottom: 15px;
  }
  .skeleton-tabs {
    list-style: none;
    padding: 0;
    margin: 0 -15px;
    display: flex;
    flex-wrap: wrap;
  }
  .skeleton-tabs-item {
    width: 22%;
    height: 80px;
    box-sizing: border-box;
    text-align: center;
    margin-bottom: 15px;
  }
  .skeleton-tabs-item span {
    display: inline-block;
    width: 80px;
    height: 80px;
    border-radius: 55px;
    background: #eee;
  }
  .skeleton-banner {
    height: 250px;
    background: #eee;
    margin-bottom: 15px;
  }
  .skeleton-productions {
    height: 50px;
    margin-bottom: 15px;
    background: #eee;
  }
</style>

#②把下面的html代碼複製,粘貼到vue項目的index.html 的 <div id=app>.....</div>裏面web

 1  <div data-server-rendered=true class="skeleton page">
 2     <div class=skeleton-nav></div>
 3     <div class=skeleton-swiper></div>
 4     <ul class=skeleton-tabs>
 5       <li class=skeleton-tabs-item><span></span></li>
 6       <li class=skeleton-tabs-item><span></span></li>
 7       <li class=skeleton-tabs-item><span></span></li>
 8       <li class=skeleton-tabs-item><span></span></li>
 9       <li class=skeleton-tabs-item><span></span></li>
10       <li class=skeleton-tabs-item><span></span></li>
11       <li class=skeleton-tabs-item><span></span></li>
12       <li class=skeleton-tabs-item><span></span></li>
13     </ul>
14     <div class=skeleton-banner></div>
15     <div class=skeleton-productions></div>
16     <div class=skeleton-productions></div>
17     <div class=skeleton-productions></div>
18     <div class=skeleton-productions></div>
19     <ul class=skeleton-tabs>
20       <li class=skeleton-tabs-item><span></span></li>
21       <li class=skeleton-tabs-item><span></span></li>
22       <li class=skeleton-tabs-item><span></span></li>
23       <li class=skeleton-tabs-item><span></span></li>
24       <li class=skeleton-tabs-item><span></span></li>
25       <li class=skeleton-tabs-item><span></span></li>
26       <li class=skeleton-tabs-item><span></span></li>
27       <li class=skeleton-tabs-item><span></span></li>
28     </ul>
29     <div class=skeleton-swiper></div>
30     <div class=skeleton-nav></div>
31   </div>

#③若是你是vue-cli腳手架搭的,直接就能夠看到效果了,而後npm run build。就成了。vue-cli

下圖是我作的效果。npm

 

 3.既然來到了這裏,咱們確定要知道原理的。json

  感謝做者的分享: 附上連接  https://segmentfault.com/a/1190000014832185segmentfault

  原理:

  DOM裏面有且僅有一個div#app,當js被執行完成以後,此div#app會被整個替換掉,也就是「測試測試測試測試測試測試測試測試」這部份內容,會被替換掉。

  因此:咱們寫在裏面的html代碼首屏時會顯示,但DOM通過render渲染結束後,裏面就被替換了。

       以下代碼:是index.html裏面代碼

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>vue-skeleton</title>
  </head>
  <body>
    <div id="app">
      測試測試測試測試測試測試測試測試
    </div>
    <script src="/dist/build.js"></script>
  </body>
</html>    

4.如何從無到有些一個骨架屏

  ①經過vue-cli安裝一個簡易版的vue項目

vue init webpack-simple vue-skeleton

  ②安裝第一次插件:

npm install vue-server-renderer --save  
 //安裝服務端渲染插件,利用它可以把.vue文件處理成html和css字符串的功能,來完成骨架屏的注入

npm install webpack-node-externals --save-dev
//安裝外部插件,在項目中給css設置白名單
npm install html-webpack-plugin --save-dev  //打包的時候能夠將index.html一塊兒打包

  ③在/src目錄下新建一個Skeleton.vue文件,樣式均可以本身定義的,爲了方便,能夠直接複製粘貼。

 1 <template>
 2   <div class="skeleton page">
 3     <div class="skeleton-nav"></div>
 4     <div class="skeleton-swiper"></div>
 5     <ul class="skeleton-tabs">
 6       <li v-for="i in 8" class="skeleton-tabs-item"><span></span></li>
 7     </ul>
 8     <div class="skeleton-banner"></div>
 9     <div v-for="i in 4" class="skeleton-productions"></div>
10     <ul class="skeleton-tabs">
11       <li v-for="i in 8" class="skeleton-tabs-item"><span></span></li>
12     </ul>
13     <div class="skeleton-swiper"></div>
14     <div class="skeleton-nav"></div>
15   </div>
16 </template>
17 
18 <style>
19   .skeleton {
20     position: fixed;
21     height: 100%;
22     overflow: hidden;
23     padding: 15px;
24     box-sizing: border-box;
25     background: #fff;
26     width: 98%;
27     top: 0;
28   }
29   .skeleton-nav {
30     height: 110px;
31     background: #eee;
32     margin-bottom: 15px;
33   }
34   .skeleton-swiper {
35     height: 440px;
36     background: #eee;
37     margin-bottom: 15px;
38   }
39   .skeleton-tabs {
40     list-style: none;
41     padding: 0;
42     margin: 0 -15px;
43     display: flex;
44     flex-wrap: wrap;
45   }
46   .skeleton-tabs-item {
47     width: 22%;
48     height: 80px;
49     box-sizing: border-box;
50     text-align: center;
51     margin-bottom: 15px;
52   }
53   .skeleton-tabs-item span {
54     display: inline-block;
55     width: 80px;
56     height: 80px;
57     border-radius: 55px;
58     background: #eee;
59   }
60   .skeleton-banner {
61     height: 250px;
62     background: #eee;
63     margin-bottom: 15px;
64   }
65   .skeleton-productions {
66     height: 50px;
67     margin-bottom: 15px;
68     background: #eee;
69   }
70 </style>

  ④在Skeleton.vue同個目錄下,創建一個skeleton.entry.js入口文件

1 import Vue from 'vue'
2 import Skeleton from './Skeleton.vue'
3 
4 export default new Vue({
5   components: {
6     Skeleton
7   },
8   template: '<skeleton />'
9 })

  ⑤在根目錄新建一個webpack.skeleton.conf.js文件,以專門用來進行骨架屏的構建,vue-server-renderer就是將Skeleton.vue生成json文件,以便插入到html。

    該配置文件和普通的配置文件基本徹底一致,主要的區別在於其target: 'node',配置了externals,以及在plugins裏面加入了VueSSRServerPlugin。在VueSSRServerPlugin中,

        指定了其輸出的json文件名。咱們能夠經過運行下列指令,在/dist目錄下生成一個skeleton.json文件

const path = require('path')
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = { target: 'node', entry: { skeleton: './src/skeleton.entry.js' },
output: { path: path.resolve(__dirname,
'./dist'), publicPath: '/dist/', filename: '[name].js', libraryTarget: 'commonjs2' },
plugins: [
new HtmlWebpackPlugin(
{
title: 'test',
template: 'index.html',
}
)
],
module: { rules: [ { test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ] }, { test: /\.vue$/, loader: 'vue-loader' } ] }, externals: nodeExternals({ whitelist: /\.css$/ }), resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' }, extensions: ['*', '.js', '.vue', '.json'] }, plugins: [ new VueSSRServerPlugin({ filename: 'skeleton.json' }) ] }

  ⑥使用命令   將skeleton.vue文件變成json格式

webpack --config ./webpack.skeleton.conf.js 

  ⑦在根目錄下新建一個skeleton.js,該文件即將被用於往index.html內插入骨架屏

 1 const fs = require('fs')
 2 const { resolve } = require('path')
 3 
 4 const createBundleRenderer = require('vue-server-renderer').createBundleRenderer
 5 
 6 // 讀取`skeleton.json`,以`index.html`爲模板寫入內容
 7 const renderer = createBundleRenderer(resolve(__dirname, './dist/skeleton.json'), {
 8   template: fs.readFileSync(resolve(__dirname, './index.html'), 'utf-8')
 9 })
10 
11 // 把上一步模板完成的內容寫入(替換)`index.html`
12 renderer.renderToString({}, (err, html) => {
13   fs.writeFileSync('index.html', html, 'utf-8')
14 })

  ⑧將<!--vue-ssr-outlet-->佔位符寫在index.html裏面,才能注入代碼

<div id="app">
 <!--vue-ssr-outlet-->
</div>

  ⑨最後,只要運行node skeleton.js,就能夠完成骨架屏的注入了。能夠看下index.html的結果。

  ⑩進一步處理,把這些內容都壓縮一下,改寫skeleton.js

 

 1 ...
 2 
 3 + const htmlMinifier = require('html-minifier')
 4 
 5 ...
 6 
 7 renderer.renderToString({}, (err, html) => {
 8 +  html = htmlMinifier.minify(html, {
 9 +    collapseWhitespace: true,
10 +    minifyCSS: true
11 +  })
12   fs.writeFileSync('index.html', html, 'utf-8')
13 })

 

結果:

看不懂,能夠再次參考原做者https://segmentfault.com/a/1190000014832185

相關文章
相關標籤/搜索