Что такое каркасный экран?
Проще говоря, скелетный экран должен использовать некоторую простую графику, чтобы примерно обрисовать основной контур страницы, когда страница не отображается, создавая у пользователя иллюзию загрузки страницы, а затем заменить скелетный экран страницей после страница отображается. , чтобы сократить время белого экрана страницы и повысить удобство работы пользователей.
Анализ процесса рендеринга VUE
Создайте проект с vue-cli3.0:vue create project
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>project</title>
</head>
<body>
<noscript>
<strong>We're sorry but project doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Видно, что в DOM есть div#app.После выполнения js этот div#app будет полностью заменен.Поэтому как реализовать каркасный экран на странице Vue уже имеет очень четкое представление — в Вы можете напрямую вставить соответствующее содержимое экрана скелета в приложение div#.
План реализации
Ненаучно вручную записывать содержимое скелетного экрана в div#app, поэтому требуется хорошо масштабируемое и автоматизированное простое в обслуживании решение. Так как он находится в проекте Vue, так называемый скелетный экран также является файлом .vue, который может быть автоматически внедрен инструментом в div#app во время построения. Сначала мы создаем новый файл Skeleton.vue в каталоге /src со следующим содержимым:
<template>
<div class="skeleton page">
<div class="skeleton-nav"></div>
<div class="skeleton-swiper">
<div class="skeleton-swiper-item item-one"></div>
<div class="skeleton-swiper-item item-two"></div>
</div>
</div>
</template>
<style>
html,body,div{
margin:0;
padding:0;
}
.skeleton {
height: 100%;
overflow: hidden;
box-sizing: border-box;
background: #fff;
}
.skeleton-nav {
height: 54px;
background: #eee;
margin-bottom: 20px;
}
.skeleton-swiper {
min-height:600px;
max-width:1280px;
margin:0 auto;
}
.skeleton-swiper-item{
min-height: 600px;
height:100%;
background:#eee;
border-radius:5px;
}
.item-one{
width:20%;
float:left;
}
.item-two{
width:78%;
float:right;
}
</style>
Затем создайте новый входной файл каркаса.entry.js в каталоге /src:
import Vue from 'vue';
import Skeleton from './Skeleton.vue';
export default new Vue({
components: {
Skeleton,
},
template: '<skeleton />',
});
После завершения подготовки скелетного экрана нам понадобится ключевой плагин vue-server-renderer. Этот подключаемый модуль изначально использовался для рендеринга на стороне сервера, но здесь мы в основном используем его функцию обработки файлов .vue в строки html и css для завершения внедрения каркасных экранов.
Инъекция скелетного экрана
Сначала создайте новый файл template.html в общей папке, и его код такой же, как код файла index.html, но вам нужно добавить его в div#app.<!--vue-ssr-outlet-->Заполнитель:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="./favicon.ico">
<title>医生工作台</title>
</head>
<body>
<noscript>
<strong>We're sorry but yz_doctors doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"><!--vue-ssr-outlet--></div>
<!-- built files will be auto injected -->
</body>
</html>
Затем нам также нужно создать новый файл webpack.skeleton.conf.js в корневом каталоге с целью построения скелетного экрана.
const path = require('path');
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
target: 'node',
entry: {
skeleton: './src/skeleton.entry.js',
},
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: '[name].js',
libraryTarget: 'commonjs2',
},
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 VueLoaderPlugin(),
new VueSSRServerPlugin({
filename: 'skeleton.json',
}),
],
};
Видно, что конфигурационный файл в принципе такой же, как и обычный конфигурационный файл, главное отличие в том, что его цель: 'node', настраиваются внешние, а в плагины добавляется VueSSSRerverPlugin. В VueSSSRerverPlugin указывается имя файла json его вывода. Затем создайте файл каркаса.json в каталоге /dist, выполнив следующую команду:webpack --config ./webpack.skeleton.conf.jsЗатем создайте в корневом каталоге новый скелет.js, который будет использоваться для вставки скелетного экрана в index.html:
const fs = require('fs');
const { resolve } = require('path');
const htmlMinifier = require('html-minifier');
const createBundleRenderer = require('vue-server-renderer').createBundleRenderer;
// 先把vue的模板文件index.html置换成标准的模板,防止骨架屏污染
let tempData = fs.readFileSync(resolve(__dirname, './public/template.html'), 'utf-8');
fs.writeFileSync('./public/index.html', tempData, 'utf-8');
console.log('模板注入完成');
// 读取`skeleton.json`,以`index.html`为模板写入内容
const renderer = createBundleRenderer(resolve(__dirname, './dist/skeleton.json'), {
template: fs.readFileSync(resolve(__dirname, './public/index.html'), 'utf-8'),
});
// 把上一步模板完成的内容写入(替换)`index.html`
renderer.renderToString({}, (err, html) => {
if (err) {
console.log(err);
return;
}
html = htmlMinifier.minify(html, {
collapseWhitespace: true,
minifyCSS: true,
});
fs.writeFileSync('./public/index.html', html, 'utf-8');
});
console.log('骨架屏注入完成');
Далее просто запуститеnode skeleton.js, вы можете завершить инъекцию скелетного экрана.
чтобыnpm run serveКогда скелетный экран внедряется автоматически, он позволяет избежать запуска нескольких команд, которые необходимоpackage.jsonдобавить команду в"preserve": "webpack --config ./webpack.skeleton.conf.js && node skeleton.js", вставить"serve"перед командой.
Суммировать
Цель создания нового файла template.html состоит в том, чтобы содержать файл шаблона в чистоте, потому что каждый раз, когда завершается внедрение каркасного экрана, содержимое файла index.html изменяется.<!--vue-ssr-outlet-->Заполнитель был заменен кодом каркасного экрана. После повторного изменения каркасного экрана внедрение каркасного экрана не может быть завершено. Поэтому при внедрении скелетного экрана сначала замените файл index.html содержимым шаблона. html, чтобы избежать каждый раз.При изменении экрана скелета вам необходимо вручную изменить файл index.html и запустить команду, чтобы реализовать автоматическую инъекцию экрана скелета.