一、环境装备
装 Node.js、切换 npm 源、装 @vue/cli 啥的,就不写了
二、使用 Vue CLI 3.0 创建 Vue项目
vue create Project_Name
运行命令后,根据提示进行配置,配置完成后等待项目初始化完成即可。
三、添加插件
Vue CLI 使用了一套基于插件的架构,可以简单的使用 vue add
命令添加插件,也可以使用 vue ui
命令在图形界面上管理插件。我们可以通过插件的形式引入我们需要的模块或者库,许多库都有官方的或者第三方实现的插件。我常用的插件有 Element UI 和 axios。
引入 Element UI
vue add element
在项目目录下运行命令后,需要选择是按需引入还是全局引入,按需引入需要在 src/plugins/element.js 中手动添加你需要的组件,像这样:
import Vue from 'vue'
import { Button, Table, TableColumn, Pagination } from 'element-ui'
import { Message, MessageBox } from 'element-ui';
Vue.use(Button);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(Pagination);
Vue.prototype.$message = Message;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$prompt = MessageBox.prompt;
引入 Axios
vue add axios
运行命令安装插件,插件会安装 axios 并在 src/plugins 下生成一个 axios.js 文件,其作用是配置 axios(url、超时、跨域)、设置拦截器以及将配置好的 axios 实例挂到 Vue 原型下。
如果需要设置或修改 axios 的拦截器,就在 axios.js里改就好,比如需要添加一个 401跳转到登录
的拦截器:
_axios.interceptors.response.use(
function(response) {
// Do something with response data
return response;
},
function(error) {
// Do something with response error
if (error.response) {
if (error.response.status === 401) {
router.push({ name: 'login' });
}
}
return Promise.reject(error);
}
);
插件默认配置的 axios 通过 挂载到 Vue 原型 暴露出来。可以在 Vue 实例中可以通过 this.axios
或 this.$axios
来使用。如果喜欢其他别名(比如我习惯了 Angular 的 $http)也可以在 axios.js 里改:
Plugin.install = function(Vue, options) {
Vue.axios = _axios;
Object.defineProperties(Vue.prototype, {
axios: {
get() {
return _axios;
}
},
$axios: {
get() {
return _axios;
}
},
$http: {
get() {
return _axios;
}
}
});
};
插件还将 axios 添加到了 window 对象上,这种写法感觉不太优雅,而且写在 Plugin.install 里的 IDE 不知道执行顺序,虽然能用但是 IDE 会标红很不爽,所以我改成 export 了。
另外我喜欢用 async/await 处理异步,但是 axios 返回的是 Promise,需要 try/catch 处理异常,太丑了,所以我又封装了一个异常处理函数,采用类似 Golang风格的错误返回方式。
// 封装异常处理
function request(options) {
return _axios(options)
.then(resp => [null, resp])
.catch(err => [err, null]);
}
export { _axios as axios, request};
接口请求就可以这么写
// result.api.js
import { request } from '@/plugins/axios';
export default {
list: (params) => request({
method: 'get',
url: `/api/result/`,
params
})
}
// Result.vue
import resultApi from './result.api';
async getResult() {
let params = {};
let [err, resp] = await resultApi.list(params);
if (!err) {
// 请求成功
} else {
// 请求失败
}
}
四、Webpack 和 devServer 配置
vue.config.js
const path = require('path');
const router = require(path.join(process.cwd(), 'router.config.js')); // 假数据配置
const proxy = require(path.join(process.cwd(), 'proxy.config.js')); // 代理配置
const UglifyPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '' : '/',
outputDir: process.env.NODE_ENV === 'production' ? 'dist' : 'dev',
lintOnSave: 'error',
productionSourceMap: false,
chainWebpack: config => {
config.plugins.delete('progress'); // 打包进度,不想看
config.plugins.delete('prefetch');
config.plugins.delete('preload');
},
configureWebpack: config => {
if (process.env.NODE_ENV === 'development') // 开发调试需要 source-map
config.devtool = 'source-map';
config.optimization = {
minimize: process.env.NODE_ENV === 'production', // 生产环境开启压缩
minimizer: [new UglifyPlugin({
uglifyOptions: {
warnings: false,
compress: {
drop_console: true,
drop_debugger: false,
pure_funcs: ['console.log'] // 过滤掉 console.log
},
sourceMap: false,
parallel: true
}
})],
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: `vendor`,
priority: 10,
chunks: 'all'
}
}
}
};
},
css: {
extract: true,
sourceMap: false,
loaderOptions: {
scss: {
prependData: `@import "./src/styles.scss";`
}
},
modules: false
},
parallel: require('os').cpus().length > 1,
pwa: {},
devServer: { // 开发服务器配置
host: '127.0.0.1',
port: 80,
https: false,
hot: true,
hotOnly: false,
proxy: JSON.stringify(proxy) === '{}' ? null : proxy,
before: router,
overlay: {
warnings: true,
errors: true
},
open: true
},
pluginOptions: {}
};
代理配置
开发服务器代理配置,可用于本地联调
// proxy.config.js
module.exports = {
'/user': {
secure: false,
target: 'http://192.168.1.191:8080',
logLevel: 'debug'
}
};
使用 devServer 作 mock server
前端开发与自测时经常需要用到模拟数据或者假数据,可以用 mock.js 但是在 dev-tools 里看不到请求,还可以直接用 devServer 当 mock server。devServer 中的 before 配置类似自定义中间件,可以用来实现 mock server。
// router.config.js
const bodyParser = require('body-parser');
module.exports = app => {
const parseJson = bodyParser.json({type:'application/json'});
// 解决部分post请求content length出错问题
app.use((req, res, next) => {
req.getBody = () => {
return new Promise(resolve => {
parseJson(req, res, error => {
resolve(req.body);
});
});
};
next();
});
app.use(bodyParser.urlencoded({extended: false}));
app.use('/mock', require('./mock'));
};
上面的 mock 是项目根目录下的一个目录,里面存放假数据以及实现接口处理的 index.js,这里就不展开了。当某个接口要用到模拟数据进行测试时,只需要给接口 url 加上 /mock
前缀就好了。