Skip to content

Latest commit

 

History

History
188 lines (158 loc) · 5.46 KB

skeleton.md

File metadata and controls

188 lines (158 loc) · 5.46 KB

Skeleton

骨架屏的作用主要是在网络请求较慢时,提供基础占位,当数据加载完成,恢复数据展示。
这样给用户一种很自然的过渡,不会造成页面长时间白屏或者闪烁等情况。
常见的骨架屏实现方案有ssr服务端渲染和prerender两种解决方案

优势:

  • 写于HTML文件中,独立于Vue框架,节省了JS加载时间+JS全局环境创建的执行时间的时间
  • 只在主页面根据页面结构独立编写,预先展示页面结构,进行视觉暂留,提供更好的交互感官
  • 只在页面结构变化时进行修改,维护成本相对较低

方案

侵入业务手写代码

手写HTML、CSS的方式为目标页定制骨架屏,直接在写业务代码的时候编写骨架屏代码,该代码作为业务代码的一部分

缺点:

  • 与业务代码耦合程度高
  • 后续维护成本略高:每次修改骨架屏代码都相当于在修改业务代码

非侵入业务式手写代码

手写骨架屏代码,使用预渲染(插件),通过webpack注入的方式注入到项目源码中

优点:

  • 骨架屏代码和业务代码解耦
  • 后续维护成本降低

缺点:

  • webpack有一定的配置成本

vue-server-renderer

使用 vue-server-renderer 这个本来用于服务端渲染的插件,用来把写的.vue文件处理为HTML,插入到页面模板的挂载点中,完成骨架屏的注入
Vue页面骨架屏注入实践

prerender-spa-plugin

Vue单页面骨架屏实践

vue-skeleton-webpack-plugin

vue-skeleton-webpack-plugin,一款通过预渲染手动书写的代码生成相应的骨架屏插件 为vue项目添加骨架屏

非侵入业务式自动代码

JavaScript操作DOM的方式结合 Puppeteer 自动生成网页骨架屏
一种自动化生成骨架屏的方案 - eleme

page-skeleton-webpack-plugin

饿了么内部的生成骨架页面的工具:page-skeleton-webpack-plugin

淘宝特价版

一个前端非侵入式骨架屏自动生成方案

参考

一种自动化生成骨架屏的方案 - eleme 一个前端非侵入式骨架屏自动生成方案 - 淘宝特价版 用纯 DOM 的方式结合 Puppeteer 自动生成网页骨架屏

vue-skeleton-webpack-plugin & vue-cli3 spa 多个skeleton

npm install vue-skeleton-webpack-plugin

目录结构

.
├── public
├── package.json
├── vue.config.js               # 配置
└── src
     ├── App.vue
     ├── assets
     ├── components
     │   └── HelloWorld.vue
     ├── main.js
     ├── router
     │   └── index.js
     ├── skeleton               # 新建
     │   ├── entry-skeleton.js  # 新建
     │   ├── skeleton1.vue      # 新建
     │   └── skeleton2.vue      # 新建
     └── views
         ├── About.vue
         └── Home.vue
<!-- skeleton1.vue -->
<template>
  <div class="skeleton">this is skeleton 1</div>
</template>

<style>
.skeleton {
  display: flex;
  font-size: 2rem;
  padding: 5px;
  animation: skeleton-blink .5s ease-in-out
    infinite;
}

@keyframes skeleton-blink {
  50% {
    opacity: 0.6;
  }
}
</style>
<!-- skeleton2.vue -->
<template>
  <div class="skeleton">
    this is skeleton 2
  </div>
</template>
// src/skeleton/entry-skeleton.js
import Vue from 'vue';
import Skeleton1 from './skeleton1.vue';
import Skeleton2 from './skeleton2.vue';

export default new Vue({
  components: {
    Skeleton1,
    Skeleton2,
  },

  template: `
       <div style='height: 100%;'>
           <skeleton1 id="skeleton1" style="display:none"/>
           <skeleton2 id="skeleton2" style="display:none"/>
       </div>
    `
});
// vue.config.js
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin');
const path = require('path')

module.exports = {
  configureWebpack: {
    plugins: [
      new SkeletonWebpackPlugin({
        webpackConfig: {
          entry: {
            app: path.join(__dirname, './src/skeleton/entry-skeleton.js'),//这里为上面的entry-skeleton.js
          }
        },
        minimize: true,
        quiet: true,
        router: {
          mode: 'hash',
          routes: [
            {
              path: '/', //和router.js中的路径一样就行
              skeletonId: 'skeleton1' //之前的id
            },
            {
              path: '/about',
              skeletonId: 'skeleton2'
            }
          ]
        }
      }),
    ]
  },
  //此插件需要css分离
  css: {
    // 是否使用css分离插件 ExtractTextPlugin
    extract: true,
    // 开启 CSS source maps?
    sourceMap: false,
    // css预设器配置项
    loaderOptions: {},
    // 启用 CSS modules for all css / pre-processor files.
    requireModuleExtension: true
  },
  // ...
}