系列文章:
Vue响应式原理系列(硬核)
最近终于完成了自己的第一个Vue项目,是一个简单的后台管理系统,业务模块很少,主要是实现了一些自己想做的功能。在做项目期间踩了很多坑,体会到了前端对于非科班转行同学深深的恶意,因此想把自己的经验总结为几篇文章,希望能够帮到和我一样的同学。
这是本系列的第一篇文章,主要介绍项目的基础结构(本项目采用vue-cli4.0
)
├── public
├── src
│ ├── api
│ ├── assets
│ ├── components
│ ├── config
│ ├── plugins
│ ├── router
│ ├── store
│ ├── utils
│ ├── views
│ ├── App.vue
│ ├── main.js
│ └── permission.js
├── package.json
├── vue.config.js
├── .env.development
└── .env.production
项目的整体结构和很多vue实战课程中的差不多,我将针对本项目中不同的地方,以及很多初学者比较困惑的点进行讲解
components
components
├── aaa.vue
├── bbb
├── ccc
├── ddd
└── index.js
我们的components
文件夹可能有很多模块,文件,可以使用一个index.js
作为统一导入入口
export { default as AAAA } from './aaaa'
导入时就不需要指定文件夹了,只需要
import AAAA from 'src/components'
plugins
plugins
├── components // 公共组件
│ ├── modules
│ └── index.js
├── directives // 自定义全局指令
│ ├── directives.js
│ └── index.js
├── filters // 自定义全局过滤器
│ ├── filters.js
│ └──index.js
├── mixins.js // 自定义minxin
└── index.js
插件安装
// 以mixins.js为例
export default function(Vue) {
Vue.mixin({
// ...
})
}
// plugins/index.js
import installDirectives from './directives'
import installFilters from './filters'
import installMixins from './mixins'
import registerComponents from './components'
export default {
install (Vue) {
installDirectives(Vue)
installFilters(Vue)
installMixins(Vue)
registerComponents(Vue)
}
}
自动化注册
自动化也是前端工程化的一部分,因此本项目plugins
中的模块均采用了自动化组册的方式,无需手动引入,需要增加内容时只需要在注册表中添加即可
mixins
比较简答,只需要像上面演示的写法即可
directives & filters
以filters
为例,目录结构如下
filters
├── filters.js // 注册表
└── index.js // 注册器
filters.js
是一张过滤器注册表,该文件需要导出一个对象
const filters = {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
export default filters
而index.js
是一个自动化的注册器
import filters from './filters' // 导入过滤器注册表
export default function (Vue) {
// 过滤该注册表对象,并进行全局过滤器的注册
Object.keys(filters).forEach(key => Vue.filter(key, filters[key]))
}
通过这种方式,当需要添加过滤器时,只需要在注册表filters.js
中添加对应方法即可,自定义指令的注册方式与过滤器注册方式相同
components
目录结构如下
components
├── modules // 组件文件夹,公共组件放在这里
└── index.js // 注册器
全局组件的自动注册需要用到webpack
提供的require.context
这个api
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
function installer (Vue) {
// 获取目标文件夹下的所有 .vue 文件的路径
const context = require.context(
'./modules',
true,
/\.vue$/
)
context.keys().forEach(filePath => {
// 由文件路径获取组件对象
const config = context(filePath)
let componentName = filePath.replace(/^.*\/+(.*)\.vue/, '$1')
componentName = upperFirst(camelCase(componentName))
// 组件全局注册
Vue.component(componentName, config.default || config)
})
}
export default installer
通过这种方式,在增加全局的基础组件时只需要在src/plugins/components/modules
下添加vue组件
即可,并且可以嵌套多层文件夹
router
对于路由文件来说,同样可以使用自动注册全局组件的方式,这样可以将路由分为多个模块,减少路由文件的代码量,提高代码的可读性,添加页面时也比较方便。这样做有一个问题,就是根据路由生成菜单栏时会有一个顺序的问题,但是可以在meta
中添加一个sort
字段,来确定该路由在菜单栏的顺序,大家可以根据实际情况酌情选择。
多环境
相信很多前端新手和我一样,在遇到这部分内容时很头痛,不知道环境变量是什么意思,下面,我将讲解一下为什么采用环境变量,以及环境变量的配置方法
为什么要使用环境变量
简单来说,一个项目可以分为两个阶段:开发和上线。开发阶段和上线阶段会有不同的配置,举个简单的例子,比如开发阶段,我们可以使用mock
来模拟数据,因此我们在使用axios
发起请求时会使用mock
的接口地址,而项目上线后会使用公司后台提供的实际接口,那么难道说我们的项目在上线前,还要修改代码中的接口地址吗?这显然是不现实的。因此,针对这个问题,我们可以采用不同的环境变量来标识项目所处的环境,比如production
表示生产环境,development
表示开发环境,test
表示测试环境等等。我们通过环境变量来获取项目所处的环境,从而采用当前环境的接口地址等配置。
环境变量的设置
在package.json
的scripts
字段中,可能会有这段脚本代码
"scripts": {
"dev": "vue-cli-service serve",
},
当我们使用npm run dev
运行这段脚本时,我们的项目会运行在开发环境下,这是因为该脚本默认环境为开发环境,我们可以通过--mode
来指定环境
"scripts": {
"dev": "vue-cli-service serve --mode development",
},
同样,我们还可以定义其他环境的脚本
"scripts": {
"dev": "vue-cli-service serve --mode development",
"build": "vue-cli-service build --mode production"
},
现在,我们的项目能够运行在不同的环境下了,但是,我们如何在代码里获取环境变量呢?答案是process.env.NODE_ENV
,通过这个api
,我们就能得到项目所处的环境了。
问题又来了,我们虽然能知道项目所处环境了,但是我们如何根据运行环境来进行不同的配置呢?vue-cli
为我们提供了一个方式,就是通过在项目根目录下放置.env
文件。
├── public
├── src
├── package.json
├── vue.config.js
├── .env.development // development 环境的配置
└── .env.production // production 环境的配置
在.env
文件中,我们可以用key=value
的方式来定义环境变量
NODE_ENV=development
Foo=bar
这里有一个点需要注意,在本地开发中,我们的代码是运行在nodejs
环境下的,所以我们能用process.env
来获取相应的变量,比如process.env.Foo
。但是,我们的代码实际上是要跑在用户浏览器上的,而浏览器并没有process.env
。针对这个问题,vue-cli
为我们提供了解决方法,在变量前加上VUE_APP_
前缀,这样,我们就可以在客户端代码中访问该变量了,比如
NODE_ENV=development
VUE_APP_BASE_URL=/dev-api
VUE_APP_TIMEOUT=1000
VUE_APP_TITLE=开发版
然后,我们就可以在config/index.js
中引入对应的变量了
export const BASEURL = process.env.VUE_APP_BASE_URL
export const TIMEOUT = process.env.VUE_APP_TIMEOUT
export const TITLE = process.env.VUE_APP_TITLE
vue.config.js
基础配置
跨域配置
跨域也是很多新手同学会比较头疼的一个问题,我们可以采用webpack-dev-server
提供的代理解决跨域问题。
devServer: {
host: 'localhost',
port: 9999,
proxy: {
// 你的BASE_URL
'/api': {
// 你的接口地址
target: 'xxxx',
changeOrigin: true,
pathRewrite: {
'^./api': ''
}
}
}
设置别名
可以使用chainWebpack
来设置路径别名,提高开发效率:
chainWebpack: (config) => {
config.resolve.alias
// 可根据实际情况自行设置
.set('@', path.resolve(__dirname, 'src'))
.set('@assets', path.resolve(__dirname, 'src/assets'))