最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue項目中使用骨架屏的方法

 更新時間:2021年05月20日 09:15:49   作者:賞花賞景賞時光  
在頁面加載數(shù)據(jù)之前,有一段空白時間,要么用loading加載,要么就用骨架屏,本文主要介紹了vue項目中使用骨架屏的方法,感興趣的可以了解一下

現(xiàn)在的應(yīng)用開發(fā),基本上都是前后端分離的,前端主流框架有SPA、MPA等,那么解決頁面渲染、白屏?xí)r間成為首要關(guān)注的點

webpack可以按需加載,減小首屏需要加載代碼的體積;

使用CDN技術(shù)、靜態(tài)代碼等緩存技術(shù),可以減小加載渲染的時長

問題:但是首頁依然存在加載、渲染等待時長的問題。那么如何從視覺效果上減小首屏白屏的時間呢?

骨架屏:舉個例子:其實就是在模版文件中id=app容器下面寫想要展示的效果,在new Vue(option)之后,該id下的內(nèi)容就被替換了( 這時候,可能Vue編譯生成的內(nèi)容還沒有掛載。因為new Vue的時候會進(jìn)行一系列的初始化,這也需要耗費時間的)。這樣就可以從視覺上減小白屏的時間

骨架屏的實現(xiàn)方式

1、直接在模版文件id=app容器下面,寫進(jìn)想要展示的效果html

2、直接在模板文件id=app容器下面,用圖片展示

3、使用vue ssr提供的webpack插件

4、自動生成并且自動插入靜態(tài)骨架屏

方式1和方式2存在的缺陷:針對不同入口,展示的效果都一樣,導(dǎo)致不能靈活的針對不同的入口,展示不同的樣式

方式3可以針對不同的入口展示不同的效果。(實質(zhì)也是先通過ssr生成一個json文件,然后將json文件內(nèi)容注入到模板文件的id=app容器下)

方案一、直接在模版文件id=app容器下面,寫進(jìn)想要展示的效果html

在根目錄的模版文件內(nèi)寫進(jìn)內(nèi)容,如紅色圈出來的地方

在瀏覽器打開項目

在調(diào)用new Vue之前的展示效果(只是做了個簡單效果,不喜勿噴):

可以看到elements中id=app的容器下內(nèi)容,就是我們寫進(jìn)的骨架屏效果內(nèi)容

在看下調(diào)了new Vue之后的效果,id=app容器下的內(nèi)容被vue編譯生成的內(nèi)容替換了

方案二、直接在模板文件id=app容器下面,用圖片展示(這個就不做展示了)

方案三、使用vue ssr提供的webpack插件:即用.vue文件完成骨架屏

在方案一的基礎(chǔ)上,將骨架屏的代碼抽離出來,不在模版文件里面書寫代碼,而是在vue文件里面書寫效果代碼,這樣便于維護(hù)

1、在根目錄下建一個skeleton文件夾,在該目錄下創(chuàng)建文件App.vue文件(根組件,類似Vue項目的App.vue)、home.skeleton.vue(首頁骨架屏展示效果的代碼,類似Vue項目寫的路由頁面)、skeleton-entry.js(入口文件類似Vue項目的入口文件)、plugin/server-plugin.js(vue-server-renderer包提供了server-plugin插件,從里面將代碼拷貝出來)

home.skeleton.vue(首頁骨架屏展示效果的代碼)

<template>
  <div class="skeleton-home">
    <div>加載中...</div>
  </div>
</template>
 
<style>
.skeleton-home {
  width: 100vw;
  height: 100vh;
  background-color: #eaeaea;
}
</style>

App.vue(根組件)

<template>
  <div id="app">
    <!-- 根組件 -->
    <home style="display:none" id="homeSkeleton"></home>
  </div>
</template>
<script>
import home from './home.skeleton.vue'
export default{
  components: {
    home
  }
}
</script>
<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
*{
  padding: 0;
  margin: 0;
}
</style>

skeleton-entry.js(入口文件)

// 入口文件
import Vue from 'vue'
import App from './App.vue'
let skeleton = new Vue({
  render(h) {
    return h(App)
  }
})
export default skeleton

plugin/server-plugin.js(vue-server-renderer包提供了server-plugin插件)

'use strict';
 
/*  */
 
var isJS = function (file) { return /\.js(\?[^.]+)?$/.test(file); };
 
var ref = require('chalk');
var red = ref.red;
var yellow = ref.yellow;
 
var prefix = "[vue-server-renderer-webpack-plugin]";
var warn = exports.warn = function (msg) { return console.error(red((prefix + " " + msg + "\n"))); };
var tip = exports.tip = function (msg) { return console.log(yellow((prefix + " " + msg + "\n"))); };
 
var validate = function (compiler) {
  if (compiler.options.target !== 'node') {
    warn('webpack config `target` should be "node".');
  }
 
  if (compiler.options.output && compiler.options.output.libraryTarget !== 'commonjs2') {
    warn('webpack config `output.libraryTarget` should be "commonjs2".');
  }
 
  if (!compiler.options.externals) {
    tip(
      'It is recommended to externalize dependencies in the server build for ' +
      'better build performance.'
    );
  }
};
 
var VueSSRServerPlugin = function VueSSRServerPlugin (options) {
  if ( options === void 0 ) options = {};
 
  this.options = Object.assign({
    filename: 'vue-ssr-server-bundle.json'
  }, options);
};
 
VueSSRServerPlugin.prototype.apply = function apply (compiler) {
    var this$1 = this;
 
  validate(compiler);
 
  compiler.plugin('emit', function (compilation, cb) {
    var stats = compilation.getStats().toJson();
    var entryName = Object.keys(stats.entrypoints)[0];
    var entryAssets = stats.entrypoints[entryName].assets.filter(isJS);
 
    if (entryAssets.length > 1) {
      throw new Error(
        "Server-side bundle should have one single entry file. " +
        "Avoid using CommonsChunkPlugin in the server config."
      )
    }
 
    var entry = entryAssets[0];
    if (!entry || typeof entry !== 'string') {
      throw new Error(
        ("Entry \"" + entryName + "\" not found. Did you specify the correct entry option?")
      )
    }
 
    var bundle = {
      entry: entry,
      files: {},
      maps: {}
    };
 
    stats.assets.forEach(function (asset) {
      if (asset.name.match(/\.js$/)) {
        bundle.files[asset.name] = compilation.assets[asset.name].source();
      } else if (asset.name.match(/\.js\.map$/)) {
        bundle.maps[asset.name.replace(/\.map$/, '')] = JSON.parse(compilation.assets[asset.name].source());
      }
      // do not emit anything else for server
      delete compilation.assets[asset.name];
    });
 
    var json = JSON.stringify(bundle, null, 2);
    var filename = this$1.options.filename;
 
    compilation.assets[filename] = {
      source: function () { return json; },
      size: function () { return json.length; }
    };
 
    cb();
  });
};
 
module.exports = VueSSRServerPlugin;

2、新建一個骨架屏構(gòu)建配置文件:build/webpack.skeleton.conf.js,這個文件配合vue-server-renderer插件,將App.vue內(nèi)容構(gòu)建成單個json格式的文件

'use strict'
 
const path = require('path')
const nodeExternals = require('webpack-node-externals')
const VueSSRServerPlugin = require('../skeleton/plugin/server-plugin')
 
module.exports = {
  // 這允許 webpack 以 Node 適用方式(Node-appropriate fashion)處理動態(tài)導(dǎo)入(dynamic import),
  // 并且還會在編譯 Vue 組件時,
  // 告知 `vue-loader` 輸送面向服務(wù)器代碼(server-oriented code)。
  target: 'node',
 
  // 對 bundle renderer 提供 source map 支持
  devtool: 'source-map',
 
  // 將 entry 指向應(yīng)用程序的 server entry 文件
  entry: path.resolve(__dirname, '../skeleton/skeleton-entry.js'),
 
  output: {
    path: path.resolve(__dirname, '../skeleton'),  // 生成的文件的目錄
    publicPath: '/skeleton/',
    filename: '[name].js',
    libraryTarget: 'commonjs2' // 此處告知 server bundle 使用 Node 風(fēng)格導(dǎo)出模塊(Node-style exports)
  },
 
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          compilerOptions: {
            preserveWhitespace: false
          }
        }
      },
      {
        test: /\.css$/,
        use: ['vue-style-loader', 'css-loader']
      }
    ]
  },
 
  performance: {
    hints: false
  },
 
  // https://webpack.js.org/configuration/externals/#function
  // https://github.com/liady/webpack-node-externals
  // 外置化應(yīng)用程序依賴模塊。可以使服務(wù)器構(gòu)建速度更快,
  // 并生成較小的 bundle 文件。
  externals: nodeExternals({
    // 不要外置化 webpack 需要處理的依賴模塊。
    // 你可以在這里添加更多的文件類型。例如,未處理 *.vue 原始文件,
    // 你還應(yīng)該將修改 `global`(例如 polyfill)的依賴模塊列入白名單
    allowlist: /\.css$/
  }),
 
  // 這是將服務(wù)器的整個輸出
  // 構(gòu)建為單個 JSON 文件的插件。
  // 不配置filename,則默認(rèn)文件名為 `vue-ssr-server-bundle.json`
  plugins: [
    new VueSSRServerPlugin({
      filename: 'skeleton.json'
    })
  ]
}

3、使用webpack-cli運(yùn)行文件webpack.skeleton.conf.js,生成skeleton.json文件,放置在文件夾skeleton下

在package.json文件里面書寫運(yùn)行命令:create-skeleton

  "scripts": {
    "create-skeleton": "webpack --progress --config build/webpack.skeleton.conf.js",
    "fill-skeleton": "node ./skeleton/skeleton.js"
  }

在控制臺上運(yùn)行命令:

npm run create-skeleton

文件夾skeleton下就會多出skelleton.json文件

4、將生成的skeleton.json內(nèi)容注入到根目錄下的index.html(模版文件)

1)在文件夾skeleton下新建skeleton.js

// 將生成的skeleton.json的內(nèi)容填充到模板文件中
const fs = require('fs')
const { resolve } = require('path')
const createBundleRenderer = require('vue-server-renderer').createBundleRenderer
 
// 讀取skeleton.json,以skeleton/index.html為模版寫入內(nèi)容
const renderer = createBundleRenderer(resolve(__dirname, '../skeleton/skeleton.json'), {
  template: fs.readFileSync(resolve(__dirname, '../skeleton/index.html'), 'utf-8')
})
// 把上一步模版完成的內(nèi)容寫入根目錄下的模版文件'index.html'
renderer.renderToString({}, (err, html) => {
  if (err) {
    return console.log(err)
  }
  console.log('render complete!')
  fs.writeFileSync('index.html', html, 'utf-8')
})

2)添加運(yùn)行命令:fill-skeleton

"fill-skeleton": "node ./skeleton/skeleton.js"

3)在控制臺上運(yùn)行該命令,則skeleton.json文件內(nèi)容被填充至根目錄下的模板文件index.html了

參考文章:

利用Vue SSR 做骨架屏注入:https://www.cnblogs.com/goloving/p/11397371.html

在Vue中實現(xiàn)骨架屏:http://www.360doc.com/content/20/0709/11/21412_923150401.shtml

Vue ssr渲染踩過的坑:https://blog.csdn.net/chen801090/article/details/105974987/

到此這篇關(guān)于vue項目中使用骨架屏的方法的文章就介紹到這了,更多相關(guān)vue 骨架屏內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue中如何實現(xiàn)輪播圖的示例代碼

    Vue中如何實現(xiàn)輪播圖的示例代碼

    本篇文章主要介紹了Vue中如何實現(xiàn)輪播圖的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • Vue3+Tsx給路由加切換動畫時的踩坑及解決

    Vue3+Tsx給路由加切換動畫時的踩坑及解決

    這篇文章主要介紹了Vue3+Tsx給路由加切換動畫時的踩坑及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Vuex 快速入門(簡單易懂)

    Vuex 快速入門(簡單易懂)

    這篇文章主要介紹了Vuex 快速入門(簡單易懂),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 淺談mvvm-simple雙向綁定簡單實現(xiàn)

    淺談mvvm-simple雙向綁定簡單實現(xiàn)

    本篇文章主要介紹了淺談mvvm-simple雙向綁定簡單實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • vue axios用法教程詳解

    vue axios用法教程詳解

    axios是vue-resource后出現(xiàn)的Vue請求數(shù)據(jù)的插件。下面我們通過本文給大家介紹vue axios用法教程詳解,感興趣的朋友一起看看吧
    2017-07-07
  • vue實現(xiàn)拖拽窗口功能

    vue實現(xiàn)拖拽窗口功能

    這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)拖拽窗口功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Vue表單控件數(shù)據(jù)綁定方法詳解

    Vue表單控件數(shù)據(jù)綁定方法詳解

    本文將詳細(xì)介紹Vue表單控件數(shù)據(jù)綁定方法,需要的朋友可以參考下
    2020-02-02
  • vue動畫打包后失效問題的解決方法

    vue動畫打包后失效問題的解決方法

    這篇文章主要介紹了vue動畫打包后失效問題的解決方法,在文中給大家提到了vue-cli 打包后自定義動畫未執(zhí)行的解決方法,需要的朋友可以參考下
    2018-09-09
  • Vue filter 過濾器、以及在table中的使用介紹

    Vue filter 過濾器、以及在table中的使用介紹

    這篇文章主要介紹了Vue filter 過濾器、以及在table中的使用介紹,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 解決ant design vue 表格a-table二次封裝,slots渲染的問題

    解決ant design vue 表格a-table二次封裝,slots渲染的問題

    這篇文章主要介紹了解決ant design vue 表格a-table二次封裝,slots渲染的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10

最新評論

盐津县| 林口县| 云安县| 昌邑市| 淮南市| 凌海市| 临沧市| 乐平市| 安康市| 瓦房店市| 涪陵区| 东乌珠穆沁旗| 兴业县| 白山市| 克什克腾旗| 枣庄市| 绵竹市| 永登县| 黑水县| 镇巴县| 顺义区| 陈巴尔虎旗| 丰台区| 新昌县| 淄博市| 偃师市| 郴州市| 饶平县| 华宁县| 金沙县| 宾川县| 县级市| 温泉县| 区。| 玛多县| 本溪| 萨嘎县| 宜君县| 松原市| 冷水江市| 临澧县|