亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Vue動態加載異步組件的方法

2019-11-19 12:29:28
字體:
來源:轉載
供稿:網友

背景:

目前我們項目都是按組件劃分的,然后各個組件之間封裝成產品。目前都是采用iframe直接嵌套頁面。項目中我們還是會碰到一些通用的組件跟業務之間有通信,這種情況下iframe并不是最好的選擇,iframe存在跨域的問題,當然是postMessage還是可以通信的,但也并非是最好的。目前有這么一個場景:門戶需要制作通用的首頁和數據概覽頁面,首頁和數據概覽頁面通過小部件來自由拼接。業務組件在制作的時候只需要提供各個模塊小部件的url就可以了,可是如果小部件之間還存在聯系呢?那么iframe是不好的。目前采用Vue動態加載異步組件的方式來實現小組件之間的通信。當然門戶也要提供一個通信的基線:Vue事件總線(空的Vue實例對象)。

內容:

使用過vue的都應該知道vue的動態加載組件components:

Vue通過is來綁定需要加載的組件。那么我們現在需要的就是如何打包組件,如果通過復制業務組件內部的代碼,那么這種就需要把依賴全部找齊,并復制過去(很多情況下會漏下某個圖片或css等),這種方式是比較low的,不方便維護。因此我們需要通過webpack來打包單個vue文件成js,這邊一個vue打包成一個js,不需壓代碼分割,css分離。因為component加載時只需要加載一個文件即可。打包文件配置如下:

首先在package.json加入打包命令:

"scripts": {  ...  "build-outCMP": "node build/build-out-components.js" },

Build-out-components.js文件:

'use strict'require('./check-versions')()process.env.NODE_ENV = 'production'const ora = require('ora')const path = require('path')const chalk = require('chalk')const webpack = require('webpack')const webpackConfig = require('./webpack.out-components.prod.conf')const spinner = ora('building for sync-components...')spinner.start()webpack(webpackConfig, function (err, stats) { spinner.stop() if (err) throw err process.stdout.write(stats.toString({  colors: true,  modules: false,  children: false,  chunks: false,  chunkModules: false }) + '/n/n') if (stats.hasErrors()) {  console.log(chalk.red(' Build failed with errors./n'))  process.exit(1) } console.log(chalk.cyan(' Build complete./n')) console.log(chalk.yellow(  ' Tip: built files are meant to be served over an HTTP server./n' +  ' Opening index.html over file:// won/'t work./n' ))})

webpack.out-components.prod.conf.js文件配置如下

const webpack = require('webpack');const path = require('path');const utils = require('./utils');const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')const {entry, mkdirsSync} = require('./out-components-tools')function resolve(dir) { return path.join(__dirname, '..', dir)}mkdirsSync(resolve('/static/outComponents'))module.exports = { entry: entry, output: {  path: resolve('/static/outComponents'),  filename: '[name].js', }, resolve: {  extensions: ['.js', '.vue', '.json'],  alias: {   'vue$': 'vue/dist/vue.esm.js',   '@': resolve('src'),  } }, externals: {  vue: 'vue',  axios: 'axios' }, module: {  rules: [   {    test: //.vue$/,    loader: 'vue-loader',    options: {     esModule: false, // vue-loader v13 更新 默認值為 true v12及之前版本為 false, 此項配置影響 vue 自身異步組件寫法以及 webpack 打包結果     loaders: utils.cssLoaders({      sourceMap: true,      extract: false     // css 不做提取     }),     transformToRequire: {      video: 'src',      source: 'src',      img: 'src',      image: 'xlink:href'     }    }   },   {    test: //.js$/,    loader: 'babel-loader',    include: [resolve('src'), resolve('test')]   },   {    test: //.(png|jpe?g|gif|svg)(/?.*)?$/,    loader: 'url-loader',    options: {     limit: 10000,     name: utils.assetsPath('img/[name].[hash:7].[ext]')    }   },   {    test: //.(mp4|webm|ogg|mp3|wav|flac|aac)(/?.*)?$/,    loader: 'url-loader',    options: {     limit: 10000,     name: utils.assetsPath('media/[name].[hash:7].[ext]')    }   },   {    test: //.(woff2?|eot|ttf|otf)(/?.*)?$/,    loader: 'url-loader',    options: {     limit: 10000,     name: utils.assetsPath('fonts/[name].[hash:7].[ext]')    }   }  ] }, plugins: [  new webpack.DefinePlugin({   'process.env.NODE_ENV': '"production"'  }),  // UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify  new webpack.optimize.UglifyJsPlugin({   compress: false,   sourceMap: true  }),  // Compress extracted CSS. We are using this plugin so that possible  // duplicated CSS from different components can be deduped.  new OptimizeCSSPlugin({   cssProcessorOptions: {    safe: true   }  }) ]};

out-components-tools.js文件配置如下:

const glob = require('glob')const fs = require('fs');const path = require('path');// 遍歷要打包的組件let entry = {}var moduleSrcArray = glob.sync('./src/out-components/*')for(var x in moduleSrcArray){ let fileName = (moduleSrcArray[x].split('/')[3]).slice(0, -4) entry[fileName] = moduleSrcArray[x]}// 清理文件function mkdirsSync(dirname) { if (fs.existsSync(dirname)) {  deleteall(dirname)  return true; } else {  if (mkdirsSync(path.dirname(dirname))) {   fs.mkdirSync(dirname);   return true;  } }}// 刪除文件下的文件function deleteall(path) { var files = []; if(fs.existsSync(path)) {  files = fs.readdirSync(path);  files.forEach(function(file, index) {   var curPath = path + "/" + file;   if(fs.statSync(curPath).isDirectory()) { // recurse    deleteall(curPath);   } else { // delete file    fs.unlinkSync(curPath);   }  }); }};exports.entry = entryexports.mkdirsSync = mkdirsSync

build-out-components是打包的入口文件,webpack.out-components.prod.conf.js是webpack打包的配置文件,out-components-tools.js是工具庫,這邊是打包的entry自動獲?。J為src/out-components),還有自動刪除之前打包的文件。

目前的文件目錄為

通過打包生產文件:

在static下outComponents文件夾內的js文件。(最終打包需要打包到dist下面,這邊做測試先打包在static文件下,方便后續動態組件ajax獲取組件使用)

門戶的小部件是通過配置url,和調整布局來生產的。因此業務組件至此已經完成了。只需要提供對門戶暴露的url即可。
接下來就是門戶這邊加載動態組件的實現了。門戶這邊就相對簡單了。看如下圖配置:

門戶通過component的動態組件來實現加載異步組件,通過ajax請求剛才打包的url,然后實例化函數new Function來賦值給mode(new Function之所以分成2部,是因此效驗規則的問題,可忽略)。這樣就實現了動態加載異步組件了。門戶和業務組件可以各個開發,任何業務開發數據概覽,門戶都不需要改代碼,只需要界面上配置url即可。這個異步加載組件已經結束了。這邊門戶需要封裝一封實現異步組件。父級只需要傳入url即可。這邊還有個可以優化的是,可以把mode優先緩存,那么不需要每次都去加載請求。如下:

我們可以看到在門戶的一個數據概覽頁面上加載了多個異步組件,那么異步組件之間也是可能存在通信的,這樣該如何做呢?因為現在已經不是iframe嵌套了,可以通過監聽一個組件,然調用另一個組件的方法,這樣確實可以實現平級組件間的通信,但這樣勢必不可取的,因為一旦這樣做了門戶必須要根據業務來輔助,修改代碼來實現功能。因此這邊借用門戶來生成vue事件總線(空的vue實例)來實現。

門戶代碼如下: 在this.$root上掛在一個事件總線:

 created () {    if (!this.$root.eventBus) {     this.$root.eventBus = new Vue()    }   }

然后業務組件之間就可以根據自己的業務實現通信:

組件一和組件二代碼如下:

 <template>   <div class="test1">    這是一個外部組件a1    <hello-word></hello-word>   </div>    </template>    <script>  import helloWord from '../components/HelloWorld'  export default {   data () {    return {     i: 0    }   },   components: {    helloWord   },   mounted () {    setInterval(() => {     this.i++     if (this.i < 10) {      this.test()     }    }, 1000)   },   methods: {    test () {     this.$root.eventBus.$emit('childEvent', this.i)    }   }  }  </script>
 <template>   <div class="test1">    這也是外部組件哦    <div >     這是a1傳來的{{a1}}    </div>   </div>  </template>    <script>  export default {   data () {    return {     a1: 0    }   },   created () {    this.$root.eventBus.$on('childEvent', this.change)   },   methods: {    change (i) {     this.a1 = i    }   }  }  </script>

業務組件就可以根據this.$root.eventBus和vue上的事件傳遞($emit, $on)來實現相互的通信。

總結:本篇主要借助vue的動態組件和webpack打包單文件來實現動態加載異步組件,通過vue的事件總線掛載在this.$root上來實現平級組件之間的通信。

拓展方向:這個方式不僅僅可以應用在門戶單個頁面上的小部件上,同樣如果某個項目中的頁面文件需要復用時,不想通過代碼的復制,同樣可以再那個文件配置打包單文件配置,打包出的文件在領一個項目中動態加載出來即可。這種模式與通用組件的install模式是有點類似的,只是這個單文件vue不是通用的,但同樣可以達到打包復用頁面。

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91在线无精精品一区二区| 伊人久久免费视频| 国产精品免费看久久久香蕉| 国产亚洲精品成人av久久ww| 国产精品扒开腿做爽爽爽视频| 美女扒开尿口让男人操亚洲视频网站| 久久琪琪电影院| 精品调教chinesegay| 久久亚洲私人国产精品va| 青青草原成人在线视频| 欧美视频裸体精品| 成人疯狂猛交xxx| 久久视频在线直播| 91亚洲精品在线| 欧美性猛交xxxx免费看久久久| 欧美中文在线观看国产| 午夜剧场成人观在线视频免费观看| 国产精品久久77777| 日韩欧美在线中文字幕| 亚洲精品在线视频| 色综合五月天导航| 2019中文字幕免费视频| 成人妇女免费播放久久久| 狠狠久久亚洲欧美专区| 日韩av在线网站| 成人网页在线免费观看| 久久99视频免费| 奇门遁甲1982国语版免费观看高清| 久久全国免费视频| 欧美一级淫片aaaaaaa视频| 欧美日韩国产二区| 国模私拍一区二区三区| 国产噜噜噜噜噜久久久久久久久| 国产在线98福利播放视频| 精品久久久久久亚洲国产300| 亚洲免费精彩视频| 亚洲全黄一级网站| 日韩精品亚洲精品| 久久精品国产亚洲一区二区| 久久这里只有精品99| 国产精品精品视频| 欧美中文在线视频| 91久久国产综合久久91精品网站| 国产免费观看久久黄| 精品视频一区在线视频| 91在线色戒在线| 亚洲一区二区三| 国产成人精品av在线| 国产在线观看精品| 日韩一级黄色av| 日本国产高清不卡| 欧美午夜视频一区二区| 亚洲综合视频1区| 97热在线精品视频在线观看| 欧美日在线观看| 日本欧美一级片| 久久久久免费精品国产| 欧美高清自拍一区| 国产精品入口夜色视频大尺度| 亚洲欧美在线免费观看| 久久精品中文字幕一区| 国产精品久久久久久久久免费| 亚洲精品小视频| 性欧美xxxx视频在线观看| 国产日韩在线播放| 欧美性受xxxx黑人猛交| 欧美人与性动交a欧美精品| 亚洲欧洲视频在线| 国语自产偷拍精品视频偷| 国产精品a久久久久久| 91久久精品日日躁夜夜躁国产| 欧美一级视频一区二区| 91a在线视频| 国产人妖伪娘一区91| 国产精品激情av电影在线观看| www.欧美精品一二三区| 国产精品色视频| 高清一区二区三区四区五区| 日韩中文字幕在线视频播放| 51精品国产黑色丝袜高跟鞋| 福利视频导航一区| 青草青草久热精品视频在线网站| 亚洲精品成人网| 欧美亚洲国产精品| 亚洲成色777777在线观看影院| 欧美日韩中文字幕在线| 日韩精品在线免费观看| 亚洲国产美女精品久久久久∴| 日韩一区二区在线视频| 亚洲韩国日本中文字幕| 国产精品夜间视频香蕉| 精品国产欧美一区二区三区成人| 精品自拍视频在线观看| 久久久日本电影| 黑人巨大精品欧美一区二区三区| 色综合天天狠天天透天天伊人| 精品国产福利视频| 欧美国产第一页| 亚洲激情小视频| 精品国偷自产在线视频99| 成人久久一区二区三区| 97国产成人精品视频| 欧美久久精品午夜青青大伊人| 91免费精品视频| 欧美黄色片视频| 亚洲欧美日韩综合| 欧美另类第一页| 久久久这里只有精品视频| 97视频在线观看免费高清完整版在线观看| 精品偷拍各种wc美女嘘嘘| 亚洲精品在线91| 成人a在线观看| 亚洲黄色在线观看| 久久综合五月天| 久久成人在线视频| 欧美国产日韩一区| 美女啪啪无遮挡免费久久网站| 久国内精品在线| 亚洲色图18p| 亚洲美女激情视频| 热久久这里只有| 4438全国成人免费| 成人免费在线网址| 青草热久免费精品视频| 亚洲第一偷拍网| 欧美成人精品不卡视频在线观看| 国产v综合ⅴ日韩v欧美大片| 亚洲视频综合网| 日韩久久精品电影| 欧美在线视频免费观看| 国产精品一区二区av影院萌芽| 国产自摸综合网| 精品一区二区三区四区在线| 91久久国产婷婷一区二区| 亚洲摸下面视频| 久久人人97超碰精品888| 91豆花精品一区| 国模精品一区二区三区色天香| 毛片精品免费在线观看| 亚洲视频综合网| 亚洲人成电影网| 18性欧美xxxⅹ性满足| 成人免费在线视频网址| 亚洲视频精品在线| 成人中文字幕+乱码+中文字幕| 亚洲区免费影片| 欧美做受高潮1| 精品人伦一区二区三区蜜桃网站| 国产欧美一区二区三区在线| 欧美日韩福利在线观看| 欧美一级片久久久久久久| 亚洲精品一区二区三区婷婷月| 高清视频欧美一级| 国产成人精品久久亚洲高清不卡| 中文字幕亚洲一区二区三区五十路| 国产99视频精品免视看7| 欧美怡春院一区二区三区| 国产精品极品在线| 久久香蕉国产线看观看网| 国产成一区二区| 亚洲成人久久网| 亚洲美女中文字幕| 亚洲综合大片69999| 正在播放国产一区|