中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue頁面骨架屏的實現方法

發布時間:2020-10-02 09:44:08 來源:腳本之家 閱讀:293 作者:RThong 欄目:web開發

在開發webapp的時候總是會受到首屏加載時間過長的影響,主流的解決方法是在載入完成之前顯示loading圖效果,而一些大公司會配置一套服務端渲染的架構來解決這個問題。考慮到ssr所要解決的一系列問題,越來越多的APP采用了“骨架屏”的方式去提升用戶體驗。

小米商城:

Vue頁面骨架屏的實現方法

一、分析Vue頁面的內容加載過程

vue項目中的入口index.html只有簡單的內容:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="root">    
  </div>
  <script type="text/javascript" src="bundle.js"></script></body>
</body>
</html>

當js執行完之后,會用vue渲染成的dom將div#root完全替換掉。

我們在div#root中加入模擬骨架屏,在Chrome開發者工具調整網速:

<div id="root">
  這里是骨架屏
</div>

Vue頁面骨架屏的實現方法

由此可知,將骨架屏內容直接插入div#root中即可實現骨架屏。

二、使用vue-server-renderer來實現骨架屏

我們需要骨架屏也是一個單獨的.vue文件,因此我們需要用到vue-server-renderer。對vue服務端渲染有所了解的同學一定知道,這個插件能夠將vue項目在node端打包成一個bundle,然后由bundle生成對應的html。
首先是生成項目:

.
├── build
│  ├── webpack.config.client.js
│  └── webpack.config.server.js
├── src
│  └── views
│    ├── index
│    │  └── index.vue
│    ├── skeleton
│    │  └── skeleton.vue
│    ├── app.vue
│    ├── index.js
│    └── skeleton-entry.js
├── index.html
└── skeleton.js
└── package.json

vue的服務端渲染一般會用vue-server-renderer將整個項目在node端打包成一份bundle,而這里我們只要一份有骨架屏的html,所以會有一個單獨的骨架屏入口文件skeleton-entry.js,一個骨架屏打包webpack配置webpack.config.server.js,而skeleton.js作用是將webpack打包出來的bundle寫入到index.html中。

//skeleton-entry.js
import Vue from 'vue'
import Skeleton from './views/skeleton/skeleton.vue'

export default new Vue({
 components: {
  Skeleton
 },
 template: '<skeleton />'
})
//webpack.config.server.js
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

module.exports = {
 mode: process.env.NODE_ENV,
 target: 'node',
 entry: path.join(__dirname, '../src/skeleton-entry.js'),
 output: {
  path: path.join(__dirname, '../server-dist'),
  filename: 'server.bundle.js',
  libraryTarget: 'commonjs2'
 },
 module: {
  rules: [
   {
    test: /\.vue$/,
    loader: 'vue-loader'
   },
   {
    test: /\.css$/,
    use: [
     'vue-style-loader',
     'css-loader'
    ]
   }  
  ]
 },
 externals: Object.keys(require('../package.json').dependencies),
 resolve: {
  alias: {
   'vue$': 'vue/dist/vue.esm.js'
  }
 },
 plugins: [
  new VueLoaderPlugin(),
  new VueSSRServerPlugin({
   filename: 'skeleton.json'
  })
 ]
}

其中骨架屏的webpack配置因為是node端,所以需要target: 'node' libraryTarget: 'commonjs2'。在VueSSRServerPlugin中,指定了其輸出的json文件名。當執行webpack會在/server-dist目錄下生成一個skeleton.json文件,這個文件記載了骨架屏的內容和樣式,會提供給vue-server-renderer使用。

//skeleton.js
const fs = require('fs')
const path = require('path')

const createBundleRenderer = require('vue-server-renderer').createBundleRenderer

// 讀取`skeleton.json`,以`index.html`為模板寫入內容
const renderer = createBundleRenderer(path.join(__dirname, './server-dist/skeleton.json'), {
 template: fs.readFileSync(path.join(__dirname, './index.html'), 'utf-8')
})

// 把上一步模板完成的內容寫入(替換)`index.html`
renderer.renderToString({}, (err, html) => {
 fs.writeFileSync('index.html', html, 'utf-8')
})

注意,作為模板的html文件,需要在被寫入內容的位置添加<!--vue-ssr-outlet-->占位符,本例子在div#root里寫入:

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

最后執行node skeleton就能實現vue的骨架屏。

最終的index.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <title>Document</title>
<style data-vue-ssr-id="a7049cb4:0">
.skeleton[data-v-61761ff8] {
 position: relative;
 height: 100%;
 overflow: hidden;
 padding: 15px;
 box-sizing: border-box;
 background: #fff;
}
.skeleton-nav[data-v-61761ff8] {
 height: 45px;
 background: #eee;
 margin-bottom: 15px;
}
.skeleton-swiper[data-v-61761ff8] {
 height: 160px;
 background: #eee;
 margin-bottom: 15px;
}
.skeleton-tabs[data-v-61761ff8] {
 list-style: none;
 padding: 0;
 margin: 0 -15px;
 display: flex;
 flex-wrap: wrap;
}
.skeleton-tabs-item[data-v-61761ff8] {
 width: 25%;
 height: 55px;
 box-sizing: border-box;
 text-align: center;
 margin-bottom: 15px;
}
.skeleton-tabs-item span[data-v-61761ff8] {
 display: inline-block;
 width: 55px;
 height: 55px;
 border-radius: 55px;
 background: #eee;
}
.skeleton-banner[data-v-61761ff8] {
 height: 60px;
 background: #eee;
 margin-bottom: 15px;
}
.skeleton-productions[data-v-61761ff8] {
 height: 20px;
 margin-bottom: 15px;
 background: #eee;
}
</style></head>
<body>
  <div id="root">
    <div data-server-rendered="true" class="skeleton page" data-v-61761ff8><div class="skeleton-nav" data-v-61761ff8></div> <div class="skeleton-swiper" data-v-61761ff8></div> <ul class="skeleton-tabs" data-v-61761ff8><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li></ul> <div class="skeleton-banner" data-v-61761ff8></div> <div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div></div>
  </div>
</body>
</html>

看下效果:

Vue頁面骨架屏的實現方法

效果還是闊以的。

尾聲

文章開頭小米商城手機頁面就是用的這樣的方法,不同的是它的骨架屏是一個base64的圖片。

更多關于vue-server-renderer內容請戳vue-ssr

文章相關代碼已經同步到Github,歡迎查閱~

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沭阳县| 商河县| 黑龙江省| 贵溪市| 文成县| 尼勒克县| 龙陵县| 兰考县| 图木舒克市| 桐柏县| 察雅县| 时尚| 常熟市| 潜山县| 雷州市| 忻城县| 疏勒县| 温泉县| 张北县| 梨树县| 东乌珠穆沁旗| 茶陵县| 株洲市| 安庆市| 肇源县| 新平| 陇川县| 上林县| 睢宁县| 乌拉特中旗| 白山市| 孙吴县| 宝鸡市| 茂名市| 甘孜| 江安县| 阜南县| 科技| 仁寿县| 湖口县| 西城区|