├── .browserslistrc
├── babel.config.js
├── public
└── favicon.ico
├── postcss.config.js
├── src
├── assets
│ └── logo.png
├── pages
│ ├── index
│ │ ├── App.vue
│ │ ├── index.js
│ │ ├── views
│ │ │ └── index.vue
│ │ ├── router.js
│ │ └── index.html
│ ├── page1
│ │ ├── index.js
│ │ ├── views
│ │ │ ├── page1-2.vue
│ │ │ └── page1-1.vue
│ │ ├── App.vue
│ │ ├── router.js
│ │ └── index.html
│ └── page2
│ │ ├── index.js
│ │ ├── views
│ │ ├── page2-2.vue
│ │ └── page2-1.vue
│ │ ├── App.vue
│ │ ├── router.js
│ │ └── index.html
└── components
│ └── HelloWorld.vue
├── .gitignore
├── .eslintrc.js
├── vue.config.js
├── package.json
└── README.md
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/app"]
3 | };
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gcddblue/multi-pages/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gcddblue/multi-pages/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/pages/index/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/pages/index/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 |
5 | Vue.config.productionTip = false
6 |
7 | new Vue({
8 | router,
9 | render: h => h(App)
10 | }).$mount('#app')
11 |
--------------------------------------------------------------------------------
/src/pages/page1/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 |
5 | Vue.config.productionTip = false
6 |
7 | new Vue({
8 | router,
9 | render: h => h(App)
10 | }).$mount('#app')
11 |
--------------------------------------------------------------------------------
/src/pages/page1/views/page1-2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
我是page1-2
4 |
跳转至page1-1
5 |
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/pages/page2/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 |
5 | Vue.config.productionTip = false
6 |
7 | new Vue({
8 | router,
9 | render: h => h(App)
10 | }).$mount('#app')
11 |
--------------------------------------------------------------------------------
/src/pages/page2/views/page2-2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
我是page2-2
4 |
page2-1
5 |
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/pages/page2/views/page2-1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
我是page2-1
4 |
page2-2
5 |
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/pages/page1/views/page1-1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
我是page1-1
4 |
跳转至page1-2
5 |
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/pages/index/views/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/pages/page2/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/src/pages/page1/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 我是page1首页返回首页
5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/src/pages/index/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import home from './views/index.vue'
4 |
5 | Vue.use(Router)
6 |
7 | export default new Router({
8 | routes: [
9 | {
10 | path: '/',
11 | name: 'home',
12 | component: home
13 | }
14 | ]
15 | })
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ['plugin:vue/essential', '@vue/prettier'],
7 | rules: {
8 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
9 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
10 | 'prettier/prettier': [
11 | 'error',
12 | {
13 | semi: false,
14 | singleQuote: true
15 | }
16 | ]
17 | },
18 | parserOptions: {
19 | parser: 'babel-eslint'
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const glob = require('glob')
2 |
3 | function getEntry(url) {
4 | let entrys = {}
5 | glob.sync(url).forEach(item => {
6 | // splice(-3)取数组后三项
7 | let urlArr = item.split('/').splice(-3)
8 | entrys[urlArr[1]] = {
9 | entry: 'src/pages/' + urlArr[1] + '/' + 'index.js',
10 | template: 'src/pages/' + urlArr[1] + '/' + 'index.html',
11 | filename: urlArr[1] + '.html',
12 | title: 'pages-' + urlArr[1]
13 | }
14 | })
15 | return entrys
16 | }
17 | let pages = getEntry('./src/pages/**?/*.html')
18 | module.exports = {
19 | pages
20 | }
21 |
--------------------------------------------------------------------------------
/src/pages/page1/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 |
6 | export default new Router({
7 | routes: [
8 | {
9 | path: '/',
10 | name: 'home',
11 | component: () => import('./views/page1-1.vue')
12 | },
13 | {
14 | path: '/page1-2',
15 | // route level code-splitting
16 | // this generates a separate chunk (about.[hash].js) for this route
17 | // which is lazy-loaded when the route is visited.
18 | component: () =>
19 | import(/* webpackChunkName: "about" */ './views/page1-2.vue')
20 | }
21 | ]
22 | })
23 |
--------------------------------------------------------------------------------
/src/pages/page2/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 |
6 | export default new Router({
7 | routes: [
8 | {
9 | path: '/',
10 | name: 'home',
11 | component: () => import('./views/page2-1.vue')
12 | },
13 | {
14 | path: '/page2-2',
15 | // route level code-splitting
16 | // this generates a separate chunk (about.[hash].js) for this route
17 | // which is lazy-loaded when the route is visited.
18 | component: () =>
19 | import(/* webpackChunkName: "about" */ './views/page2-2.vue')
20 | }
21 | ]
22 | })
23 |
--------------------------------------------------------------------------------
/src/pages/index/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | multi-index
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/pages/page1/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | multi-page1
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/pages/page2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | multi-page2
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multi-pages",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "core-js": "^2.6.5",
12 | "vue": "^2.6.10",
13 | "vue-router": "^3.0.3"
14 | },
15 | "devDependencies": {
16 | "@vue/cli-plugin-babel": "^3.11.0",
17 | "@vue/cli-plugin-eslint": "^3.11.0",
18 | "@vue/cli-service": "^3.11.0",
19 | "@vue/eslint-config-prettier": "^5.0.0",
20 | "babel-eslint": "^10.0.1",
21 | "eslint": "^5.16.0",
22 | "eslint-plugin-prettier": "^3.1.0",
23 | "eslint-plugin-vue": "^5.0.0",
24 | "glob": "^7.1.4",
25 | "prettier": "^1.18.2",
26 | "sass": "^1.18.0",
27 | "sass-loader": "^7.1.0",
28 | "vue-template-compiler": "^2.6.10"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 使用vue cli3配置多页项目
2 |
3 | > 我们在使用vue cli3脚手架构建页面时,大多都是单页应用(这其中的优势我就不多说了),但是在某些场景,我们需要构建多页应用,例如我们我们应用中有很多小型h5页面,或者多种活动页,这些页面互相之间没有什么关联,如果每个活动页面都构建一个应用,那也是不切实际的,所以我们需要使用vue脚手架构建多页应用,其中在vue-cli2.x版本配置多页需要修改的地方还是挺繁琐,不过好在cli3版本增加了pages属性,配置起来相当轻松。
4 | >
5 | > 项目源码地址 [multi-pages](https://github.com/gcddblue/multi-pages)
6 |
7 | #### 创建多页应用
8 |
9 | 首先 `vue create multi-pages` 初始化名为 `multi-pages` 的项目,我们删除views文件夹,新建一个名为`pages` 的文件夹,并创建 `index` 、 `page1` 、 `page2` 文件夹如下:
10 |
11 | 
12 |
13 | 这里index代表了项目首页,page1、page2在这里可以理解为需要构建的其他页面,我们可以在各自的页面文件下创建属于他们的入口文件index.js(相当于单页应用的main.js) router路由、组件components、vuex、axios等等,我们就把他们每个理解为独立的单页应用。
14 |
15 | #### 配置vue.config.js
16 |
17 | 在项目中创建 `vue.config.js` 文件来配置我们的多页应用。话不多说,整干货:
18 |
19 | ```
20 | const glob = require('glob')
21 |
22 | function getEntry(url) {
23 | let entrys = {}
24 | glob.sync(url).forEach(item => {
25 | // splice(-3)取数组后三项
26 | let urlArr = item.split('/').splice(-3)
27 | entrys[urlArr[1]] = {
28 | entry: 'src/pages/' + urlArr[1] + '/' + 'index.js',
29 | template: 'src/pages/' + urlArr[1] + '/' + 'index.html',
30 | filename: urlArr[1] + '.html',
31 | title: 'pages-' + urlArr[1]
32 | }
33 | })
34 | return entrys
35 | }
36 | let pages = getEntry('./src/pages/**?/*.html')
37 | module.exports = {
38 | pages
39 | }
40 | ```
41 |
42 | 这里主要用到 `glob` 模块来处理多页路径,这样做的好处就是不用再pages添加后文件,再来vue.config.js中添加pages对象属性,当页面多时,这是相当繁琐的,所以我们需要借助 `glob` 模块,调用glob.sync(url)返回匹配到的路径数组,有关路径匹配规则,如下:
43 |
44 | ```
45 | 1、* :匹配单个路径部分中的0个或多个字符。
46 |
47 | 2、?:匹配路径中某部分1个字符。
48 |
49 | 3、[...] :匹配一个字符的范围,类似于一个正则表达式的范围。如果范围的第一个字符是!或者,它匹配任何不在范围内的字符。
50 |
51 | 4、!(模式1|模式2|模式3):匹配与所提供的任何模式不匹配的任何内容。和正则表达式的!一样。
52 |
53 | 5、?(模式1|模式2|模式3):匹配所提供的模式的零或一个事件。
54 |
55 | 6、+(模式1|模式2|模式3):匹配所提供的模式的一个或多个事件。
56 |
57 | 7、*(a|b|c) :匹配所提供的模式的零个或多个事件。
58 |
59 | 8、@(pattern|pat*|pat?erN):匹配所提供的模式之一。
60 |
61 | 9、**:如果**在一个路径的部分,他会匹配零个或多个目录和子目录中搜索匹配。
62 | ```
63 |
64 | 更多 [glob相关介绍请点击查看](https://www.cnblogs.com/waitforyou/p/7044171.html)
65 |
66 | 运行 `npm run serve` 输入 `http:localhost:8080` 跑动程序:
67 |
68 |
69 |
70 | 
71 |
72 | 点击page1 、page2 都会重新请求刷新页面,最后 `npm run build` 打包程序:
73 |
74 | 
75 |
76 | 至此vue cli3多页面配置就简单实现了,大家可以依照这个例子,在实际项目中构建更多功能!
77 |
78 | > 想学习并实践开发vue项目的同学,可以关注我的个人后台管理spa页面,项目地址 [vue-admin-webapp](https://github.com/gcddblue/vue-admin-webapp) 欢迎star,fork
79 |
80 |
--------------------------------------------------------------------------------
/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
10 |
11 |
Installed CLI Plugins
12 |
30 |
Essential Links
31 |
54 |
Ecosystem
55 |
86 |
87 |
88 |
89 |
97 |
98 |
99 |
115 |
--------------------------------------------------------------------------------