1.我要做一个考试系统,大部分页面是左右布局,但“考试中”的页面我需要做成上下结构,因此,需要把单页应用改为多页应用,实现在不同页面框架下的布局。
2.同时,我从A.html下的组件“考试列表”跳转到B.html下的“考试中”组件,需要实现夸页面的组件间跳转。
先说第一个问题:
1.首先安装glob
2.修改build目录下的
//+添加以下部分
// glob是webpack安装时依赖的一个第三方模块,还模块允许你使用 *等符号, 例如lib/*.js就是获取lib文件夹下的所有js后缀名的文件
var glob = require('glob')
// 页面模板
var HtmlWebpackPlugin = require('html-webpack-plugin')
// 取得相应的页面路径,因为之前的配置,所以是src文件夹下的pages文件夹
var PAGE_PATH = path.resolve(__dirname, '../src/pages')
// 用于做相应的merge处理
var merge = require('webpack-merge')
//多入口配置
// 通过glob模块读取pages文件夹下的所有对应文件夹下的js后缀文件,如果该文件存在
// 那么就作为入口处理
exports.entries = function () {
var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
var map = {}
entryFiles.forEach((filePath) => {
var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
map[filename] = filePath
})
return map
}
//多页面输出配置
// 与上面的多页面入口配置相同,读取pages文件夹下的对应的html后缀文件,然后放入数组中
exports.htmlPlugin = function () {
let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
let arr = []
entryHtml.forEach((filePath) => {
let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
let conf = {
// 模板来源
template: filePath,
// 文件名称
filename: filename + '.html',
// 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本
chunks: ['manifest', 'vendor', filename],
inject: true
}
if (process.env.NODE_ENV === 'production') {
conf = merge(conf, {
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
})
}
arr.push(new HtmlWebpackPlugin(conf))
})
return arr
}
module.exports = {
/* 修改部分 ---------------- 开始 */
entry: utils.entries(),
/* 修改部分 ---------------- 结束 */
concat(utils.htmlPlugin()),附加一个utils中的函数来处理
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
/* new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),*/
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
].concat(utils.htmlPlugin())
})
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? {safe: true, map: {inline: false}}
: {safe: true}
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
/* new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
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'
}),*/
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
].concat(utils.htmlPlugin())
以上配置完成。
3.新建router文件:
import Vue from 'vue'
import Router from 'vue-router'
import ExamDetails from '@/components/ExamDetails'
import HistoryDetails from '@/components/HistoryDetails'
Vue.use(Router)
const routes = [
{
path: '/', name: 'ExamDetails', component: ExamDetails,
},
{path: '/history', name: 'HistoryDetails', component: HistoryDetails},
]
const vueRouter = new Router({
// path: '/exam',
mode: 'history',//去掉#,
base: './exam',//这个配置也很重要,否则会出现页面空白情况
routes,
})
export default vueRouter
4.将其注入跟组件
完成,我这里只是记录一下,具体参考https://segmentfault.com/a/1190000011265006?utm_source=tag-newest
现在来说第二个问题,现在要从A.html的组件“考试列表”跳转到B.html的ExamDetails,我使用标签跳转
1.如果你的B页面只有一个组件,或者都是嵌套组件,不包含并列切换组件,你在router.js页面将B.html,redirect一下就可以了,但这种情况通常很少
const routes = [
{
path: '/B.html',redirect:'/',
},
{
path: '/', name: 'ExamDetails', component: ExamDetails,
},
{path: '/history', name: 'HistoryDetails', component: HistoryDetails},
]
2.现在来解决我的问题,要从A的ExamList到B的ExamDetails,还要从A的HistoryList到B的HistoryDetails,采用导航守卫解决:
在router.js中采用beforeEach函数,根据跳转目标的fullPath,next重定向到不同的目标。
特别注意:采用next("*")必须有一个next()函数作为出口,否则将进入死循环。
原理是:此函数,如果遇到next("*")执行完就会返回再次执行此函数,如果没有遇到next()就不会继续往下执行。