前言
公司做的後臺管理系統,越做越龐大,而且系統之間還需要經常的來回嵌套頁面,單頁面已經不太順手了。
所以我把vue+elementui+webpack單頁面改爲多頁面的經驗在這裏嘮叨嘮叨,這裏作展示的是一個簡單的後臺管理系統,利用iframe模擬的路由跳轉,很簡單也很容易上手,可以把這個項目下載到本地,然後把你們的頁面慢慢移進去,希望能幫到一些小夥伴。
建議,把項目下載下來跑起來,結合着項目看這篇文章,不然會蒙。
gitHub:歡迎各位star
在線預覽:網站不太穩定,最好下載到本地
效果預覽:
思路
一.普遍的實現方案:
1.手動改造webpack,配置多個入口,配置多個出口;
2.每個目錄下邊都有個.html文件來承載實例,.js文件引入Vue等等模塊,.vue頁面來書寫邏輯等,如圖:
二.改進的方案
1.用node自帶的模塊fs來動態的匹配目錄,動態的生成入口文件,動態的生成打包出口文件;
2.我們寫一個公共的html文件來承載實例,寫一個公共的js來引入各種依賴,根據動態傳入.vue文件模塊生成實例
如圖:
3.解釋一下template下的config.js:
因爲我們現在只用config.js來去引入各種依賴,就像單頁面的mian.js一樣,不同的是,
需要被掛載的vue文件是動態的,所以我們用localStorage來傳遞,我們在頁面目錄下邊只用寫一個.vue文件,一個.js文件,
這個.js文件裏只用寫上當前對應的.vue文件所在的目錄,不用在每個js裏寫那麼多引入的依賴
文件目錄下的js:
let baseUrl = "china/china"
localStorage.setItem('baseUrl', baseUrl)
template/config.js
// 如果你想用自己創建的實例,在自己單獨的js文件里加上:let baseUrl="noNeed" / localStorage.setItem('baseUrl',baseUrl)
let baseMounted = localStorage.getItem('baseUrl')
console.log(baseMounted)
import '../src/style/index.scss' //公用樣式
if (baseMounted === 'noNeed') {
// 組件自己創建了實,將不會再引入下邊的資源
throw new Error("當前組件自己創建了實例,不會引用公用方法、實例");
}
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
// 動態捕獲要掛載實例的.vue文件的路徑
var App = resolve => require.ensure([], () => resolve(require("../src/views/" + baseMounted + ".vue")));
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
總結:就是你每次切換頁面的時候,會先加載自己目錄下的js文件,js裏用localStorage存儲.vue的路徑(當然你也可以寫成'noNeed',這樣你自己就得在js裏去引入各種依賴了),
再去引用template/config.js的時候,利用localStorage告訴掛載實例的模板是哪個。
三.最重要的webpack配置
webpack的複雜程度我就不累贅了(我自己也是個入門選手),這個需要自己花時間去看,我就直接講下實現的結果。
主要的實現邏輯就是下邊的這個js文件,出處我翻不到了,不知道是哪位大神研究出來的,
這個js文件主要實現了webpack匹配出入口文件的功能,
一開始,我也是研究了研究裏邊的方法,然後在原版的基礎上改造了好幾版,實現了現在的效果,
主要改了公共模板html和js,以及js的加載順序。
build下的這三個文件都要改成multipage-helper.js裏的方法
multipage-helper.js:
var path = require('path')
var fs = require("fs")
const resolve = (p) => path.resolve(__dirname, "..", p)
var HtmlWebpackPlugin = require('html-webpack-plugin')
const templatePath = resolve("template/index.html")
const templateJs = "./template/config.js"
var moduleList //緩存多頁面模塊列表
var moduleRootPath = './src/views' //模塊根目錄(這個可以根據自己的需求命名)
/**
* 獲取js入口數組
*/
exports.getEntries = function getEntries() {
//緩存js入口數組
var entries = {}
//初始化模塊列表
this.getModuleList()
//變量模塊列表
moduleList.forEach(function(module) {
if (module.moduleID != "" && module.moduleJS != "") {
entries[module.moduleID] = module.moduleJS
}
})
entries.app=templateJs
console.log("*********************************** entries ***********************************")
console.log(entries)
return entries
}
/**
* 獲取多頁面模塊列表
* @returns {模塊的信息集合}
*/
exports.getModuleList = function getModuleList() {
//判斷是否爲空,不爲空則直接返回
if (moduleList) {
return moduleList
} else { //爲空則讀取列表
moduleList = new Array();
readDirSync(moduleRootPath, "")
console.log("*********************************** moduleList ***********************************")
console.log(moduleList)
return moduleList
}
}
/**
* 獲取dev的Html模板集合
* @returns {dev的Html模板集合}
*/
exports.getDevHtmlWebpackPluginList = function getDevHtmlWebpackPluginList() {
console.log("*********************************** devHtmlWebpackPluginList ***********************************")
//緩存dev的Html模板集合
var devHtmlWebpackPluginList = []
//獲取多頁面模塊集合
var moduleList = this.getModuleList()
//遍歷生成模塊的HTML模板
moduleList.forEach(function(mod) {
//生成配置
var conf = {
filename: mod.moduleID + ".html",
template: mod.moduleHTML ? mod.moduleHTML : templatePath,
chunks: [mod.moduleID,'app'],
chunksSortMode: 'manual',
inject: true
}
console.log(conf)
//添加HtmlWebpackPlugin對象
devHtmlWebpackPluginList.push(new HtmlWebpackPlugin(conf))
})
return devHtmlWebpackPluginList
}
/**
* 獲取prod的Html模板集合
* @returns {prod的Html模板集合}
*/
exports.getProdHtmlWebpackPluginList = function getProdHtmlWebpackPluginList() {
console.log("*********************************** prodHtmlWebpackPluginList ***********************************")
//緩存dev的Html模板集合
var prodHtmlWebpackPluginList = []
//獲取多頁面模塊集合
var moduleList = this.getModuleList()
//遍歷生成模塊的HTML模板
moduleList.forEach(function(mod) {
//生成配置
var conf = {
filename: mod.moduleID + ".html",
template: mod.moduleHTML ? mod.moduleHTML : templatePath,
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency',
chunks: ['manifest', 'vendor', mod.moduleID,'app'],
chunksSortMode: 'manual'
}
console.log(conf)
//添加HtmlWebpackPlugin對象
prodHtmlWebpackPluginList.push(new HtmlWebpackPlugin(conf))
})
return prodHtmlWebpackPluginList
}
/**
* 深度遍歷目錄,並整理多頁面模塊
* @param path 需要變量的路徑
* @param moduleName 模塊名稱
*/
function readDirSync(path, moduleName) {
//緩存模塊對象
var module = { moduleID: "", moduleHTML: "", moduleJS: "" }
//獲取當前模塊ID
var moduleID = path.replace(moduleRootPath + "/", "")
if (path == moduleRootPath) {
moduleID = ""
}
module.moduleID = moduleID
//獲取目錄下所有文件及文件夾
var pa = fs.readdirSync(path)
pa.forEach(function(ele, index) {
var info = fs.statSync(path + "/" + ele)
if (info.isDirectory()) {
// console.log("dir: "+ele)
readDirSync(path + "/" + ele, ele)
} else {
//判斷當前模塊的html是否存在
if (moduleName+".html" == ele){
module.moduleHTML = path+"/"+ele
}
// module.moduleHTML = templatePath
//判斷當前模塊的js是否存在
if (moduleName + ".js" == ele) {
module.moduleJS = path + "/" + ele
}
// console.log("file: "+ele)
}
})
//判斷模塊是否真實(可能只是個分級目錄)
if ((module.moduleID != "" && module.moduleHTML != "") || (module.moduleID != "" && module.moduleJS != "")) {
moduleList.push(module)
}
}
鄙人的webpack正在學習中,所以可能有些細節講的不會太清楚,但能用,希望大家的指正,也希望能幫到大家,嘻嘻嘻。