在頁面初始時沒有加載出來,頁面顯示一片空白,永不體驗不好,就可以使用骨架屏,就是在頁面內容還未加載完成的時候,先讓一些圖片或者固定結構站位,
待內容加載完成之后把他替換掉
思路:
webpack中最終生成的html頁面使用的是html-webpack-plugin插件,它提供了一系列的事件,我們可以注冊到他處理html之前,使用html-webpack-plugin-before-html-processing事件把骨架屏動態插入進去;
插件:plugin.js
骨架屏的代碼:
<div id="app"> <div style="width:100%;height:50px;background: rgb(211, 219, 224);"></div> <ul class="loading-skeleton" style=""> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> </ul> <style> .loading-skeleton{ width:100%;height:auto;list-style: none;overflow: hidden;margin:0;padding:0; } .loading-skeleton li{ width: 40%; height: 180px; float: left; margin: 3% 7% 3% 3%; } .loading-skeleton li .d1{ width: 100%; height: 130px; background: rgb(211, 219, 224); } .loading-skeleton li .d2{ width: 100%; height: 15px; background: rgb(211, 219, 224); margin-top: 5px; } .loading-skeleton .o { float:left;width:92%;height:100px;margin:3%; background: rgb(211, 219, 224); animation: skeleton-stripes 1s linear infinite; transform-origin: left; animation: skeleton-stretch .5s linear infinite alternate; } .loading-skeleton .d { float:left;width:92%;height:100px;margin:3%; background: rgb(211, 219, 224); animation: skeleton-stripes 1s linear infinite; transform-origin: left; animation: skeleton-stretch .5s -.5s linear infinite alternate; } @keyframes skeleton-stretch { from { transform: scalex(1); } to { transform: scalex(.3); } } </style> </div>
效果:
插件plugin.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); class MyPlugin_skeleton { constructor(options) { this.options = options; } apply(compiler) { compiler.hooks.compilation.tap('MyPlugin', (compilation) => { // //編譯之前,生成一個text.txt文件,通過compilation操作文件,只是演示與骨架屏沒有關系,本身是node環境,根據node+fs也可以使用 console.log(this.options); compilation.assets['./text.txt'] = { source: () => this.options.text, size: () => this.options.text.length }; HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync('MyPlugin', (data, cb) => { ////在編譯html文件之前把骨架屏動態加入進去 data.html = data.html.replace('<div id="app"></div>', `這里是骨架屏代碼`); //錯誤優先原則,如果處理有錯誤,傳遞到第一個參數,否則參數的位置就null cb(null, data) //重點,一定要有回調函數,否則內容不會生效 } ) }) } } module.exports = MyPlugin_skeleton;
在webpack.prod.conf.js中引入插件,並使用,它是根據HtmlWbpackPlugin提供的一個口子來處理,插件需要安裝在htmlwebapckplugin下面
打包項目 npm run build
打開dist/index.html 可以看到我們的骨架屏已經插入到root中
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>index</title> <link href="static/css/main.css" rel="stylesheet"> </head> <body> <div id="app"> <div style="width:100%;height:50px;background: rgb(211, 219, 224);"></div> <ul class="loading-skeleton" style=""> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> <li> <div class="d1"></div> <div class="d2 o"></div> <div class="d2 d"></div> </li> </ul> <style> .loading-skeleton { width: 100%; height: auto; list-style: none; overflow: hidden; margin: 0; padding: 0; } .loading-skeleton li { width: 40%; height: 180px; float: left; margin: 3% 7% 3% 3%; } .loading-skeleton li .d1 { width: 100%; height: 130px; background: rgb(211, 219, 224); } .loading-skeleton li .d2 { width: 100%; height: 15px; background: rgb(211, 219, 224); margin-top: 5px; } .loading-skeleton .o { float: left; width: 92%; height: 100px; margin: 3%; background: rgb(211, 219, 224); animation: skeleton-stripes 1s linear infinite; transform-origin: left; animation: skeleton-stretch .5s linear infinite alternate; } .loading-skeleton .d { float: left; width: 92%; height: 100px; margin: 3%; background: rgb(211, 219, 224); animation: skeleton-stripes 1s linear infinite; transform-origin: left; animation: skeleton-stretch .5s -.5s linear infinite alternate; } @keyframes skeleton-stretch { from { transform: scalex(1); } to { transform: scalex(.3); } } </style> </div> <script src="static/js/main.c43cd934e03c41d9a79f.js"></script> </body> </html>
這是一個通用的骨架屏模板,也可以根據自己的需求,設置不同的骨架屏
拓展
其實還可以根據用戶訪問路徑進行打包不同的骨架,無非就加入path判斷,塞入不同樣式。
var hash=window.location.hash;
var path=window.location.pathname;
根據path不同,顯示不同的骨架屏