vue-cli多页面项目创建

vue-cli多页面项目创建

1.创建vue项目

由于将vue-cli升级到了3.0,于是此次多页面创建将基于vue-cli3.0,
首先创建项目命令由:

vue init webpack demo

变成了:

vue create demo

如果非要使用第一种命令怎么办?
在这里插入图片描述
输入上方的命令就可以使用第一种创建项目啦!
我这里用的是第二种命令,按下回车后出现了这样的错误:
在这里插入图片描述
大意就是vue的版本和vue-template-compiler版本不一致,需要升级,请记住一定要是 全局 升级

npm i -g vue

升级后我们接着再进行一次创建命令,终于成功了
在这里插入图片描述
这里出现了两个可以选择的路线:
default: 是默认模板,回车后直接创建模板项目
Manually 可以自定义一些配置,自由组合项目中所需的功能
在这里插入插入图片描述
选择自己需要的功能回车进入下一步:
在这里插入图片描述
上面我选择添加了 Router 所以这里会问我需不需要使用 history 模式,选择是然后进行下一步,
进行选择css预处理,根据自己需要选择之后回车下一步,
选择Linter / Formatter规范类型:Pick a linter / formatter config
选择ESLint + Prettier回车下一步,
选择语法检查:Pick additional lint features
我选择的Lint on save(保存就检查)回车下一步,
选择选择单元测试:选择单元测试

Mocha + Chai //mocha灵活,只提供简单的测试结构,如果需要其他功能需要添加其他库/插件完成。必须在全局环境中安装
Jest //安装配置简单,容易上手。内置Istanbul,可以查看到测试覆盖率,相较于Mocha:配置简洁、测试代码简洁、易于和babel集成、内置丰富的expect

选择后回车下一步,会问你 ,把babel,postcss,eslint这些配置文件放哪

   ?Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? (Use arrow keys)
  In dedicated config files // 独立文件放置
  In package.json // 放package.json里

在这里需要注意的是当最后一步的时候会提示你要不要保存该配置为模板,选择是后自定义一个名字,以后就可以使用这一套配置为默认模板快速创建项目了,就是前面的第一条**default:**默认配置选项。

  ? Save this as a preset for future projects? (y/N) //是否保存该配置为模板=

选择后回车等待项目创建完成,进入项目目录,运行npm run serve。
在这里插入图片描述
具体目录结构是这个样子哒!可以看到跟2.0区别还是很大的
在这里插入图片描述

2.多页面应用配置

在项目目录下创建 vue.config.js 文件
在这里插入图片描述

vue.config.js

由于多页面配置内容过多,把它单独放到了./build/pages.js文件里


/** 获取多页的入口脚本和模板 */
const pages = require('./build/pages.js').getPagesVue();
console.log('pages: ', pages.pages);
console.log('rewrites: ', pages.rewrites);
console.log("VUE_APP_MODE: ", process.env.VUE_APP_MODE);

module.exports = {
  devServer: {
    open: true,
    port: 8080,
    disableHostCheck: process.env.NODE_ENV !== 'production',
    // host: '0.0.0.0',
    // https: false,
    // hotOnly: false,
    // proxy: null,
    // proxy: {
    //   "/api": {
    //     target: "http://127.0.0.1:8080/", // 域名
    //     ws: true, // 是否启用websockets
    //     changOrigin: true, //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
    //     pathRewrite: {
    //       "^/api": "/"
    //     }
    //   }
    // },
    before: app => {
      // handle fallback for HTML5 history API
      app.use(require("connect-history-api-fallback")({
        rewrites: pages.rewrites
      }));
    }
  },
  pages: pages.pages
}

page.js:

const path = require("path");
// const debug = process.env.NODE_ENV !== 'production'
const glob = require("glob");
const fs = require("fs");
const Title = require("./title.js"); //这里是网站title的配置

/** 获取多页的入口脚本和模板 */
module.exports = {
  // 用html和js文件匹配页面
  getPages: () => {
    const [globPathHtml, globPathJs, pages, tempSet] = [
      ["./src/views/**/*.html", "template"], // 入口模板正则
      ["./src/views/**/*.js", "entry"], // 入口脚本正则
      Object.create(null),
      new Set()
    ];
    const getMultiPageConf = (globPath, keyName) => {
      let [fileList, tempArr, modName] = [glob.sync(globPath), [], null];
      if (fileList.length !== 0) {
        for (let entry of fileList) {
          tempArr = path.dirname(entry, path.extname(entry)).split("/");
          modName = tempArr[tempArr.length - 1];
          if (tempSet.has(modName)) {
            Object.assign(pages[modName], {
              [keyName]: entry,
              filename: `${modName}.html`
            });
          } else {
            Reflect.set(pages, modName, {
              [keyName]: entry
            }) && tempSet.add(modName);
          }

          let title = Title.get(modName);
          if (title) {
            Object.assign(pages[modName], {
              title: title
            });
          }
        }
        return true;
      } else {
        if (keyName === "template") {
          throw new Error("无法获取多页入口模板");
        } else if (keyName === "entry") {
          throw new Error("无法获取多页入口脚本");
        } else {
          throw new Error("无法获取多页信息");
        }
      }
    };
    try {
      while (
        getMultiPageConf(...globPathHtml) &&
        getMultiPageConf(...globPathJs)
      )
        return pages;
    } catch (err) {
      console.log("获取多页数据错误:", err);
    }
  },
  // 用vue文件匹配页面
  getPagesVue: () => {
    const [baseHtml, globPathVue, pages, rewrites, tempSet] = [
      "./public/index.html", // 默认模板
      "./src/views/*/*.vue", // 入口vue正则
      Object.create(null),
      new Array(),
      new Set()
    ];

    const getMultiPageConf = (globPath) => {
      let [fileList, tempArr, modName] = [glob.sync(globPath), [], null];
      if (fileList.length !== 0) {
        for (let entry of fileList) {
          tempArr = path.dirname(entry, path.extname(entry)).split("/");
          modName = tempArr[tempArr.length - 1];
          let template = `./src/views/${modName}/${modName}.html`; // 入口模板
          let entryJs = `./src/views/${modName}/${modName}.js`; // 入口脚本
          if (!fs.existsSync(template)) {
            template = baseHtml;
          }
          if (tempSet.has(modName)) {
            // Object.assign(pages[modName], {
            //   "template": template,
            //   "entry": entryJs,
            //   title: Title.get(modName, true),
            //   filename: `${modName}.html`
            // });
            continue;
          } else {
            Reflect.set(pages, modName, {
              "template": template,
              "entry": entryJs,
              title: Title.get(modName, true),
              filename: `${modName}.html`
            }) && tempSet.add(modName);
          }

          rewrites.push({
            from: new RegExp(`^\/${modName}\$|^\/${modName}\/`), // 正则或者字符串
            to: `/${modName}.html` // 字符串或者函数
          });
        }
        return true;
      } else {
        throw new Error("无法获取多页信息");
      }
    };
    try {
      if (getMultiPageConf(globPathVue)) return {
        pages,
        rewrites
      };
    } catch (err) {
      console.log("获取多页数据错误:", err);
    }
  }
};

title.js

// 配置title
const baseTitle = "嘟嘟嘟"
const spector = "-"
const title = {
  index: "首页"
}

module.exports = {
  get: function (str, force = false) {
    let def = force ? baseTitle : null;
    if (this.hasTitle(str)) {
      let t = title[str];
      return `${t}${spector}${baseTitle}`;
    }
    return def;
  },
  hasTitle: function (str) {
    return title[str] != null;
  }
}

配置完成后,可以将App.vue,main.js,router删除

这里模拟了两个多页面入口,分别是index入口和page1入口
在这里插入图片描述
**index.js,**相当于main.js

import Vue from 'vue'
import App from './index.vue' //这里引入的是当前入口文件夹中根目录 例如index.vue 、page1.vue
import router from './router'
import store from '@/store'

Vue.config.productionTip = false

Vue.use({router});

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app');

index.vue相当于App.vue

<template>
  <div>
      <router-view></router-view>
    index页面
  </div>
</template>

<style lang="scss">
</style>

router.js是当前入口的路由配置

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [{
      path: '*',
      name: 'index',
      meta: {
        title: "主页"
      },
      component: () => import('./index.vue'),
    },
  ]
})

现在我们去启动项目,发现打印出来的已经是两个入口了
在这里插入图片描述
需要注意的是,当index内部的路由需要跳转到page1中的路由的时候,使用 this.$router.push跳转是无效的,可以使用 window.location进行跳转或者a标签

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值