国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

用vue構(gòu)建多頁面應(yīng)用的示例代碼

2019-11-19 15:22:23
字體:
供稿:網(wǎng)友

最近一直在研究使用vue做出來一些東西,但都是SPA的單頁面應(yīng)用,但實(shí)際工作中,單頁面并不一定符合業(yè)務(wù)需求,所以這篇我就來說說怎么開發(fā)多頁面的Vue應(yīng)用,以及在這個(gè)過程會遇到的問題。

這是我放在GitHub上的項(xiàng)目,里面有整個(gè)配置文件,可以參看一下:multiple-vue-page

準(zhǔn)備工作

在本地用vue-cli新建一個(gè)項(xiàng)目,這個(gè)步驟vue的官網(wǎng)上有,我就不再說了。

這里有一個(gè)地方需要改一下,在執(zhí)行npm install命令之前,在package.json里添加一個(gè)依賴,后面會用到。

修改webpack配置

這里展示一下我的項(xiàng)目目錄

├── README.md├── build│  ├── build.js│  ├── check-versions.js│  ├── dev-client.js│  ├── dev-server.js│  ├── utils.js│  ├── vue-loader.conf.js│  ├── webpack.base.conf.js│  ├── webpack.dev.conf.js│  └── webpack.prod.conf.js├── config│  ├── dev.env.js│  ├── index.js│  └── prod.env.js├── package.json├── src│  ├── assets│  │  └── logo.png│  ├── components│  │  ├── Hello.vue│  │  └── cell.vue│  └── pages│    ├── cell│    │  ├── cell.html│    │  ├── cell.js│    │  └── cell.vue│    └── index│      ├── index.html│      ├── index.js│      ├── index.vue│      └── router│        └── index.js└── static

在這一步里我們需要改動的文件都在build文件下,分別是:

  • utils.js
  • webpack.base.conf.js
  • webpack.dev.conf.js
  • webpack.prod.conf.js

我就按照順序放出完整的文件內(nèi)容,然后在做修改或添加的位置用注釋符標(biāo)注出來:

utils.js文件

// utils.js文件var path = require('path')var config = require('../config')var ExtractTextPlugin = require('extract-text-webpack-plugin')exports.assetsPath = function (_path) {  var assetsSubDirectory = process.env.NODE_ENV === 'production' ?    config.build.assetsSubDirectory :    config.dev.assetsSubDirectory  return path.posix.join(assetsSubDirectory, _path)}exports.cssLoaders = function (options) {  options = options || {}  var cssLoader = {    loader: 'css-loader',    options: {      minimize: process.env.NODE_ENV === 'production',      sourceMap: options.sourceMap    }  }  // generate loader string to be used with extract text plugin  function generateLoaders(loader, loaderOptions) {    var loaders = [cssLoader]    if (loader) {      loaders.push({        loader: loader + '-loader',        options: Object.assign({}, loaderOptions, {          sourceMap: options.sourceMap        })      })    }    // Extract CSS when that option is specified    // (which is the case during production build)    if (options.extract) {      return ExtractTextPlugin.extract({        use: loaders,        fallback: 'vue-style-loader'      })    } else {      return ['vue-style-loader'].concat(loaders)    }  }  // https://vue-loader.vuejs.org/en/configurations/extract-css.html  return {    css: generateLoaders(),    postcss: generateLoaders(),    less: generateLoaders('less'),    sass: generateLoaders('sass', { indentedSyntax: true }),    scss: generateLoaders('sass'),    stylus: generateLoaders('stylus'),    styl: generateLoaders('stylus')  }}// Generate loaders for standalone style files (outside of .vue)exports.styleLoaders = function (options) {  var output = []  var loaders = exports.cssLoaders(options)  for (var extension in loaders) {    var loader = loaders[extension]    output.push({      test: new RegExp('//.' + extension + '$'),      use: loader    })  }  return output}/* 這里是添加的部分 ---------------------------- 開始 */// glob是webpack安裝時(shí)依賴的一個(gè)第三方模塊,還模塊允許你使用 *等符號, 例如lib/*.js就是獲取lib文件夾下的所有js后綴名的文件var glob = require('glob')// 頁面模板var HtmlWebpackPlugin = require('html-webpack-plugin')// 取得相應(yīng)的頁面路徑,因?yàn)橹暗呐渲茫允莝rc文件夾下的pages文件夾var PAGE_PATH = path.resolve(__dirname, '../src/pages')// 用于做相應(yīng)的merge處理var merge = require('webpack-merge')//多入口配置// 通過glob模塊讀取pages文件夾下的所有對應(yīng)文件夾下的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文件夾下的對應(yīng)的html后綴文件,然后放入數(shù)組中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',      // 頁面模板需要加對應(yīng)的js腳本,如果不加這行則每個(gè)頁面都會引入所有的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}/* 這里是添加的部分 ---------------------------- 結(jié)束 */

webpack.base.conf.js 文件

// webpack.base.conf.js 文件var path = require('path')var utils = require('./utils')var config = require('../config')var vueLoaderConfig = require('./vue-loader.conf')function resolve(dir) { return path.join(__dirname, '..', dir)}module.exports = { /* 修改部分 ---------------- 開始 */ entry: utils.entries(), /* 修改部分 ---------------- 結(jié)束 */ output: {  path: config.build.assetsRoot,  filename: '[name].js',  publicPath: process.env.NODE_ENV === 'production' ?   config.build.assetsPublicPath :   config.dev.assetsPublicPath }, resolve: {  extensions: ['.js', '.vue', '.json'],  alias: {   'vue$': 'vue/dist/vue.esm.js',   '@': resolve('src'),   'pages': resolve('src/pages'),   'components': resolve('src/components')  } }, module: {  rules: [{   test: //.vue$/,   loader: 'vue-loader',   options: vueLoaderConfig  },  {   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: //.(woff2?|eot|ttf|otf)(/?.*)?$/,   loader: 'url-loader',   options: {    limit: 10000,    name: utils.assetsPath('fonts/[name].[hash:7].[ext]')   }  }  ] }}

webpack.dev.conf.js 文件

var utils = require('./utils')var webpack = require('webpack')var config = require('../config')var merge = require('webpack-merge')var baseWebpackConfig = require('./webpack.base.conf')var HtmlWebpackPlugin = require('html-webpack-plugin')var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')// add hot-reload related code to entry chunksObject.keys(baseWebpackConfig.entry).forEach(function (name) { baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])})module.exports = merge(baseWebpackConfig, { module: {  rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) }, // cheap-module-eval-source-map is faster for development devtool: '#cheap-module-eval-source-map', plugins: [  new webpack.DefinePlugin({   'process.env': config.dev.env  }),  // https://github.com/glenjamin/webpack-hot-middleware#installation--usage  new webpack.HotModuleReplacementPlugin(),  new webpack.NoEmitOnErrorsPlugin(),  // https://github.com/ampedandwired/html-webpack-plugin  /* 注釋這個(gè)區(qū)域的文件 ------------- 開始 */  // new HtmlWebpackPlugin({  //  filename: 'index.html',  //  template: 'index.html',  //  inject: true  // }),  /* 注釋這個(gè)區(qū)域的文件 ------------- 結(jié)束 */  new FriendlyErrorsPlugin()  /* 添加 .concat(utils.htmlPlugin()) ------------------ */ ].concat(utils.htmlPlugin())})

webpack.prod.conf.js 文件

var path = require('path')var utils = require('./utils')var webpack = require('webpack')var config = require('../config')var merge = require('webpack-merge')var baseWebpackConfig = require('./webpack.base.conf')var CopyWebpackPlugin = require('copy-webpack-plugin')var HtmlWebpackPlugin = require('html-webpack-plugin')var ExtractTextPlugin = require('extract-text-webpack-plugin')var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')var env = config.build.envvar webpackConfig = merge(baseWebpackConfig, { module: {  rules: utils.styleLoaders({   sourceMap: config.build.productionSourceMap,   extract: true  }) }, devtool: config.build.productionSourceMap ? '#source-map' : false, output: {  path: config.build.assetsRoot,  filename: utils.assetsPath('js/[name].[chunkhash].js'),  chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, plugins: [  // http://vuejs.github.io/vue-loader/en/workflow/production.html  new webpack.DefinePlugin({   'process.env': env  }),  new webpack.optimize.UglifyJsPlugin({   compress: {    warnings: false   },   sourceMap: true  }),  // extract css into its own file  new ExtractTextPlugin({   filename: utils.assetsPath('css/[name].[contenthash].css')  }),  // Compress extracted CSS. We are using this plugin so that possible  // duplicated CSS from different components can be deduped.  new OptimizeCSSPlugin({   cssProcessorOptions: {    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  /* 注釋這個(gè)區(qū)域的內(nèi)容 ---------------------- 開始 */  // 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'  // }),  /* 注釋這個(gè)區(qū)域的內(nèi)容 ---------------------- 結(jié)束 */  // split vendor js into its own file  new webpack.optimize.CommonsChunkPlugin({   name: 'vendor',   minChunks: function (module, count) {    // 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',   chunks: ['vendor']  }),  // copy custom static assets  new CopyWebpackPlugin([{   from: path.resolve(__dirname, '../static'),   to: config.build.assetsSubDirectory,   ignore: ['.*']  }])  /* 該位置添加 .concat(utils.htmlPlugin()) ------------------- */ ].concat(utils.htmlPlugin())})if (config.build.productionGzip) { var CompressionWebpackPlugin = require('compression-webpack-plugin') webpackConfig.plugins.push(  new CompressionWebpackPlugin({   asset: '[path].gz[query]',   algorithm: 'gzip',   test: new RegExp(    '//.(' +    config.build.productionGzipExtensions.join('|') +    ')$'   ),   threshold: 10240,   minRatio: 0.8  }) )}if (config.build.bundleAnalyzerReport) { var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin())}module.exports = webpackConfig

至此,webpack的配置就結(jié)束了。

但是還沒完啦,下面繼續(xù)。

文件結(jié)構(gòu)

├── src│  ├── assets│  │  └── logo.png│  ├── components│  │  ├── Hello.vue│  │  └── cell.vue│  └── pages│    ├── cell│    │  ├── cell.html│    │  ├── cell.js│    │  └── cell.vue│    └── index│      ├── index.html│      ├── index.js│      ├── index.vue│      └── router│        └── index.js

src就是我所使用的工程文件了,assets,components,pages分別是靜態(tài)資源文件、組件文件、頁面文件。

前兩個(gè)就不多說,主要是頁面文件里,我目前是按照項(xiàng)目的模塊分的文件夾,你也可以按照你自己的需求調(diào)整。然后在每個(gè)模塊里又有三個(gè)內(nèi)容:vue文件,js文件和html文件。這三個(gè)文件的作用就相當(dāng)于做spa單頁面應(yīng)用時(shí),根目錄的index.html頁面模板,src文件下的main.js和app.vue的功能。

原先,入口文件只有一個(gè)main.js,但現(xiàn)在由于是多頁面,因此入口頁面多了,我目前就是兩個(gè):index和cell,之后如果打包,就會在dist文件下生成兩個(gè)HTML文件:index.html和cell.html(可以參考一下單頁面應(yīng)用時(shí),打包只會生成一個(gè)index.html,區(qū)別在這里)。

cell文件下的三個(gè)文件,就是一般模式的配置,參考index的就可以,但并不完全相同。

特別注意的地方

cell.js

在這個(gè)文件里,按照寫法,應(yīng)該是這樣的吧:

import Vue from 'Vue'import cell from './cell.vue'new Vue({  el:'#app',// 這里參考cell.html和cell.vue的根節(jié)點(diǎn)id,保持三者一致  teleplate:'<cell/>',  components:{ cell }})

這個(gè)配置在運(yùn)行時(shí)(npm run dev)會報(bào)錯(cuò)

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
(found in <Root>)

網(wǎng)上的解釋是這樣的:

運(yùn)行時(shí)構(gòu)建不包含模板編譯器,因此不支持 template 選項(xiàng),只能用 render 選項(xiàng),但即使使用運(yùn)行時(shí)構(gòu)建,在單文件組件中也依然可以寫模板,因?yàn)閱挝募M件的模板會在構(gòu)建時(shí)預(yù)編譯為 render 函數(shù)。運(yùn)行時(shí)構(gòu)建比獨(dú)立構(gòu)建要輕量30%,只有 17.14 Kb min+gzip大小。

上面一段是官方api中的解釋。就是說,如果我們想使用template,我們不能直接在客戶端使用npm install之后的vue。
也給出了相應(yīng)的修改方案:

resolve: { alias: { 'vue': 'vue/dist/vue.js' } }

這里是修改package.json的resolve下的vue的配置,很多人反應(yīng)這樣修改之后就好了,但是我按照這個(gè)方法修改之后依然報(bào)錯(cuò)。然后我就想到上面提到的render函數(shù),因此我的修改是針對cell.js文件的。

import Vue from 'Vue'import cell from './cell.vue'/* eslint-disable no-new */new Vue({ el: '#app', render: h => h(cell)})

這里面我用render函數(shù)取代了組件的寫法,在運(yùn)行就沒問題了。

頁面跳轉(zhuǎn)

既然是多頁面,肯定涉及頁面之間的互相跳轉(zhuǎn),就按照我這個(gè)項(xiàng)目舉例,從index.html文件點(diǎn)擊a標(biāo)簽跳轉(zhuǎn)到cell.html。

我最開始寫的是:

 <!-- index.html --><a href='../cell/cell.html'></a>

但這樣寫,不論是在開發(fā)環(huán)境還是最后測試,都會報(bào)404,找不到這個(gè)頁面。

改成這樣既可:

 <!-- index.html --><a href='cell.html'></a>

這樣他就會自己找cell.html這個(gè)文件。

打包后的資源路徑

執(zhí)行npm run build之后,打開相應(yīng)的html文件你是看不到任何東西的,查看原因是找不到相應(yīng)的js文件和css文件。

這時(shí)候的文件結(jié)構(gòu)是這樣的:

├── dist│  ├── js│  ├── css│  ├── index.html│  └── cell.html

查看index.html文件之后會發(fā)現(xiàn)資源的引用路徑是:

/dist/js.........

這樣,如果你的dist文件不是在根目錄下的,就根本找不到資源。

方法當(dāng)然也有啦,如果你不嫌麻煩,就一個(gè)文件一個(gè)文件的修改路徑咯,或者像我一樣偷懶,修改config下的index.js文件。具體的做法是:

build: {  env: require('./prod.env'),  index: path.resolve(__dirname, '../dist/index.html'),  assetsRoot: path.resolve(__dirname, '../dist'),  assetsSubDirectory: 'static',  assetsPublicPath: '/',  productionSourceMap: true,  // Gzip off by default as many popular static hosts such as  // Surge or Netlify already gzip all static assets for you.  // Before setting to `true`, make sure to:  // npm install --save-dev compression-webpack-plugin  productionGzip: false,  productionGzipExtensions: ['js', 'css'],  // Run the build command with an extra argument to  // View the bundle analyzer report after build finishes:  // `npm run build --report`  // Set to `true` or `false` to always turn it on or off  bundleAnalyzerReport: process.env.npm_config_report },

將這里面的

assetsPublicPath: '/',

改成

assetsPublicPath: './',

醬紫,配置文件資源的時(shí)候找到的就是相對路徑下的資源了,在重新npm run build看看吧。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 江山市| 泊头市| 永寿县| 祁阳县| 江永县| 汽车| 江孜县| 宝坻区| 三穗县| 株洲市| 镇坪县| 祁东县| 香格里拉县| 泗阳县| 徐汇区| 涿鹿县| 平山县| 云龙县| 遂川县| 多伦县| 延边| 文登市| 庐江县| 天津市| 三台县| 武清区| 容城县| 东港市| 祁东县| 寿宁县| 桓台县| 工布江达县| 容城县| 四川省| 榕江县| 阿拉善左旗| 凤山市| 射阳县| 扶风县| 资源县| 博罗县|