使用vue构建项目,项目结构清晰会提升开发效率,熟悉项目的各类配置一样会让开发效率更高,本篇幅不长,纯属分享,但愿帮助小白提升开发效率,也欢迎大神讨论指正html
my-vue-test:.
│ .browserslistrc
│ .env.production
│ .eslintrc.js
│ .gitignore
│ babel.config.js
│ package-lock.json
│ package.json
│ README.md
│ vue.config.js
│ yarn-error.log
│ yarn.lock
│
├─public
│ favicon.ico
│ index.html
│
└─src
├─apis //接口文件根据页面或实例模块化
│ index.js
│ login.js
│
├─components //工具组件
│ └─header
│ index.less
│ index.vue
│
├─config //配置(环境变量配置不一样passid等)
│ env.js
│ index.js
│
├─contant //常量
│ index.js
│
├─images //图片
│ logo.png
│
├─pages //多页面vue项目,不一样的实例
│ ├─index //主实例
│ │ │ index.js
│ │ │ index.vue
│ │ │ main.js
│ │ │ router.js
│ │ │ store.js
│ │ │
│ │ ├─components //业务组件
│ │ └─pages //此实例中的各个路由
│ │ ├─amenu
│ │ │ index.vue
│ │ │
│ │ └─bmenu
│ │ index.vue
│ │
│ └─login //另外一个实例
│ index.js
│ index.vue
│ main.js
│
├─scripts //包含各类经常使用配置,工具函数
│ │ map.js
│ │
│ └─utils
│ helper.js
│
├─store //vuex仓库
│ │ index.js
│ │
│ ├─index
│ │ actions.js
│ │ getters.js
│ │ index.js
│ │ mutation-types.js
│ │ mutations.js
│ │ state.js
│ │
│ └─user
│ actions.js
│ getters.js
│ index.js
│ mutation-types.js
│ mutations.js
│ state.js
│
└─styles //样式统一配置
│ components.less
│
├─animation
│ index.less
│ slide.less
│
├─base
│ index.less
│ style.less
│ var.less
│ widget.less
│
└─common
index.less
reset.less
style.less
transition.less
复制代码
vue.config.js一般是一份写好后能够不断复制,可是会用不如会写,须要知道里面的原理,多页面使用nodejs来配置多个入口,代码更加优雅,下面是一份经常使用的vue.config.js配置,附注释vue
const path = require("path")
const fs = require("fs")
/**
* @readdirSync fs模块,用于读取文件夹下全部的文件/文件夹,返回数组,fs.readdir的同步版本
* @resolve path模块,用于拼接文件路径
* @existsSync fs模块,判断路径是否存在,返回布尔值
*/
const dirs = fs.readdirSync(path.resolve(process.cwd(), "src/pages"))
const pages = dirs.reduce((config,dirname)=>{
const filePath = `src/pages/${dirname}/main.js`
const tplPath = path.resolve(process.cwd(), `./public/${dirname}.html`)
if(fs.existsSync(tplPath)){
config[dirname] = filePath
}else{
config[dirname] = {
entry:filePath,//page的入口
template:'public/index.html',//模板的来源
filename:`${dirname}.html`//在dist/xx.html输出
}
}
return config
},{})
// 多页面 pages 使用的模版默认为 public/[dir-name].html,若是找不到该模版,默认使用 public/index.html
/**
* publicPath: 应用会默认部署在根路径,使用publicPath能够定义部署在子路径,pages模式不要使用相对路径
* productionSourceMap: 为true 则打包会生成.map文件
* contentBase: 告诉服务器从那个目录提取静态文件
* compress: 一切服务都启用 gzip 压缩
* historyApiFallback: 当使用 HTML5 History API 时,任意的 404 响应均可能须要被替代为 index.html
* disableHostCheck: 绕过主机检查
* devServer.proxy.changeOrigin: 默认状况下,代理时会保留主机标头的来源,您能够将changeOrigin设置为true来覆盖此行为
* devServer.proxy.secure: 默认状况下,不接受运行在 HTTPS 上,且使用了无效证书的后端服务器,设置为false表示接受
* chainWebpack: webpack的链式操做
* configureWebpack:多是个对象,也多是个函数,主要是经过webpack-merge合并到配置里
* configureWebpack.resolve: 至关于合并内容到webpack原来的resolve[https://webpack.docschina.org/configuration/resolve/#resolve]
* configureWebpack.resolve.alias: 建立 import 或 require 的别名,来确保模块引入变得更简单
*/
module.exports = {
publicPath: process.env.VUE_APP_MODE === "production" ? "/prod/" : "/",
pages,
outputDir:process.env.VUE_APP_MODE === "production"? path.resolve(`${process.cwd()}/dist-prod/`):path.resolve(`${process.cwd()}/dist-beta/`),
productionSourceMap:process.env.VUE_APP_MODE === "beta",
devServer:{
port:3434,
host: "127.0.0.1",
contentBase: "./dist",
compress:true,
historyApiFallback:true,
disableHostCheck: true,
proxy:{
"/": {
target: "http://10.122.122.10:8070",
changeOrigin: true,
secure: false,
// pathRewrite: {"^/sjjc" : ""}
},
}
},
chainWebpack: config => {
config.module
.rule("images")
.use("url-loader")
.tap(args => {
return {
limit: 4096,
fallback: {
loader: "file-loader",
options: {
name: "images/[name].[hash:8].[ext]",
},
},
};
});
config.module
.rule("svg")
.use("file-loader")
.tap(args => {
return {
name: "images/[name].[hash:8].[ext]",
};
});
},
configureWebpack: {
resolve:{
alias:{
"@_src": path.resolve(__dirname,"src/")
}
}
}
}
复制代码
在根目录下配置.env文件,能够设置环境变量(可设置多个)node
.env.produciton
和.env.development
全局变量仅除NODE_ENV
和BASE_URL
这两个保留变量外,其他自定义变量都需使用VUE_APP
开头。webpack
VUE_APP_MODE=beta
注意点:.env
文件里不容许存在注释git
/**
* .env.produciton内部写法
*/
NODE_ENV=production
VUE_APP_MODE=production
复制代码
使用store模块化配合路由守卫,能够实现不一样路由在页面上的不一样配置,例如特定路由须要展现不一样的样式,特定路由不须要头部,不须要侧边导航栏等,这些能够在
router.js
中配置路由守卫,利用store定义各个属性,实例化前经过mapstate
拿到配置,实现不一样路由不一样样式的效果github
// @_src/store/index.js
import Vuex from "vuex";
import Vue from "vue";
import index from "./index/index.js";
import user from "./user";
Vue.use(Vuex);
const stores = {
"index": index,
user,
};
export const storeCreator = (moduleNames) => {
const names = Array.isArray(moduleNames) ? moduleNames : [moduleNames];
const modules = names.reduce((all, name) => {
if (stores[name]) {
all[name] = stores[name];
}
return all;
}, {});
return new Vuex.Store({
modules: {
...modules
}
});
};
复制代码
import { storeCreator} from "@_src/store"
export default storeCreator(["index","user"])
复制代码
import Vue from "vue"
import VueRouter from "vue-router"
import store from "./store";
export const routes = [
//初始进入重定向至父级通用事项页面
{
path: "/",
redirect: "/a-menu",
name: "home"
},
{
name: "菜单A",
path: "/a-menu",
component: () => import("./pages/amenu/index.vue"),
meta: { title: "菜单A",icon:"xxx", menuCode: "xxx"}
},
{
name: "菜单B",
path: "/b-menu",
component: () => import("./pages/bmenu/index.vue"),
meta: { title: "菜单A",icon:"xxx", menuCode: "xxx"}
},
]
// header的title的颜色是否为白色路由
const writeTitleRoutes = [
{
path: "/b-menu",
name: "菜单B",
},
];
Vue.use(VueRouter);
const router = new VueRouter({
routes
});
//配置路由导航守卫
router.beforeEach((to,from,next)=>{
let writeTitle=false
for(let i=0;i<writeTitleRoutes.length;i++){
const pathReg = new RegExp(writeTitleRoutes[i].path);
if (pathReg.test(to.path)) {
writeTitle = true;
break;
}
}
if (store.state.index.writeTitle !== writeTitle) {
store.commit("index/SET_TITLE", writeTitle);
}
next();
})
export default router;
复制代码