最近公司来了个新项目,之前Vue项目都是用Vue CLI2搭建的,现在准备用Vue CLI3搭建,谨以此文记录实战过程,如果觉得此文对您有帮助,帮忙点个赞,谢谢。持续更新中…………
一、安装Vue CLI3
- 首先你要卸载Vue CLI2,用命令
npm uninstall vue-cli -g
卸载; - 输入命令
npm install -g @vue/cli
安装Vue CLI3; - 安装完成后,输入命令
vue --version
,查看Vue CLI的版本号是否是3.0以上,是代表安装成功。
二、搭建Vue项目
- 新建文件夹,注意文件名字最好不要用中文,按下图操作;
- 输入命令
vue create flow_manage_platform
,flow_manage_platform
为项目名称; - 按上下键选择Manually select features(手动选择功能)项,default (babel, eslint)(默认安装);
- 按上下键和回车键选择要安装的功能;
- 使用路由器的历史模式,回车进入下一步;
- 选择CSS预处理语言,选择less,回车进入下一步;
- 选择In dedicated config files,将Babel、PostCSS等配置独立在package.json文件外;
- 是否保存安装配置,直接回车进入下一步;
- 如果出现下图就是开始进行下载Vue项目了;
- 如果下载很慢,是网络问题,可以让电脑连你的手机网络;
三、清洁Vue项目
通过Vue CLI搭建的Vue项目中有很多无用的文件和代码,需要对其做一次清洁。
1、初始化
- 下载完成后,首先打开package.json文件,将
改成"scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build" },
因为在Vue CLI2中使用"scripts": { "dev": "vue-cli-service serve", "build": "vue-cli-service build" },
npm run dev
命令启动项目。 - 使用
npm install
安装依赖,安装成功后,执行npm run dev
,执行成功后在浏览器打开 http://localhost:8080/ ,页面展示如下图所示,说明Vue项目已经搭建成功。
2、清洁public文件下的index.html文件
清洁后如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
</head>
<body>
<div id="app"></div>
</body>
</html>
3、清洁router.js文件
清洁后如下:
import Vue from 'vue'
import Router from 'vue-router';
Vue.use(Router)
function load(component) {
return resolve => require([`./views/${component}`], resolve);
}
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: load('home')
},
]
})
4、清洁App.vue文件
清洁后如下:
<template>
<div>
<router-view/>
</div>
</template>
5、清洁views文件夹
删除views文件夹中的About.vue和Home.vue文件,
新建home.vue文件.内容如下:
<template>
<div>
欢迎使用Vue项目
</div>
</template>
6、清洁components文件夹
删除components文件夹中的HelloWorld.vue文件。
7、清洁assets文件夹
删除assets文件夹夹中的logo.png文。
8、清洁完毕
重新执行npm run dev
,执行成功后在浏览器打开 http://localhost:8080/ ,页面展示如下图所示,说明Vue项目已经清洁成功。
四、配置Vue项目
清洁完毕后,但其还是不满足我们项目开发的要求,需要我们进一步配置。
1、新建api文件夹
在src文件夹下新建api文件夹,主要放置axios的配置文件axios.js和接口文件。
2、新建mixins文件夹
在src文件夹下新建mixins文件夹,主要放置Vue混入文件。
在minxins文件夹下,新建index.js文件,主要放置全局混入的内容,
export default {
data() {
return {
}
},
created(){
alert('全局混乱引入成功')
},
methods: {
}
}
在main.js 引入全局混入,
import mixins from './mixins';
Vue.mixin(mixins);
在浏览器页面可看到弹窗全局混乱引入成功
,说明引入成功,
返回minxins/index.js文件中将
created(){
alert('全局混乱引入成功')
},
删除!
3、新建service文件夹
在src文件夹下新建service文件夹,主要放置公共方法、配置文件。
4、配置assets文件夹
- 在assets文件夹下新建css文件夹,主要放置样式文件;
- 在assets文件夹下新建images文件夹,主要放置可以编译的图片文件。
5、新建router文件夹
在src文件夹下新建router文件夹,
删除src文件夹下的router.js文件,
在router文件夹中,新建index.js和routes.js文件,
index.js内容:
import Vue from 'vue';
import Router from 'vue-router';
import routes from './routes';
Vue.use(Router);
// 路由配置
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
} else {
return {x: 0, y: 0};
}
}
});
router.beforeEach((to, from, next) => {
next();
});
router.afterEach((to, from, next) => {
window.scrollTo(0, 0);
});
export default router;
routes.js内容:
function load(component) {
return resolve => require([`views/${component}`], resolve);
}
const routes = [
{
path: '/',
name: 'home',
component: load('home'),
meta: {
title: '首页'
}
},
{
path: '*',
redirect: {
path: '/'
}
}
];
export default routes;
6、新建store文件夹
在src文件夹下新建store文件夹,放置Vuex的内容,
删除src文件夹下的store.js文件,
在store文件夹下新建module文件夹,
在module文件夹下新建demo.js文件,
const state = {
moduleTip: '欢迎使用Vuex模块',
};
const getters = {
moduleTip: state => state.moduleTip,
};
const mutations = {
SET_MODULETIP(state, data) {
state.moduleTip = data;
},
};
const actions = {};
export default {
state,
getters,
mutations,
actions
}
在store文件夹下新建index.js文件,
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production';
import demo from './module/demo';
const store = new Vuex.Store({
strict: debug,
state: {
tip: '欢迎使用Vuex',
},
getters: {
tip: state => state.tip,
},
mutations: {
SET_TIP(state, data) {
state.tip = data;
},
},
actions: {
},
modules: {
demo,
}
});
export default store;
在minxins/index.js文件写入,
import { mapGetters } from 'vuex';
export default {
data() {
return {
}
},
computed: {
...mapGetters(['tip','moduleTip'])
},
mounted(){
},
methods: {
}
}
在views/home.vue文件写入,
<template>
<div>
欢迎使用Vue项目
{{tip}}
{{moduleTip}}
</div>
</template>
在浏览器页面上显示:
欢迎使用Vue项目 欢迎使用Vuex 欢迎使用Vuex模块
说明全局Vuex和模块Vuex配置成功。
7、配置文件别名
在Vue CLI3中,项目的webpack配置是要在根目录下新建vue.config.js来配置。
在vue.config.js文件中配置内容如下:
const path = require('path');
function resolve(dir) {
return path.resolve(__dirname, dir)
}
module.exports = {
configureWebpack: {
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'assets': resolve('src/assets'),
'css':resolve('src/assets/css'),
'images':resolve('src/assets/images'),
'views': resolve('src/views'),
'components':resolve('src/components'),
'api':resolve('src/api'),
'mixins':resolve('src/mixins'),
'store': resolve('src/store'),
'service':resolve('src/service'),
}
}
},
}
8、关闭source map
关闭source map有两个好处
- 减少打包编译的时间;
- 避免在生产环境中用F12开发者工具在Sources中看到源码。
在vue.config.js文件中配置内容如下:
module.exports = {
productionSourceMap: false,
}
9、配置devServer项
-
固定端口
有时候后端设置跨域白名单时候要固定端口,前端也要配合固定端口,
port: 8036,
-
开启热更新
hot: true,
-
固定打开浏览器
open: 'Google Chrome',
在vue.config.js文件中配置内容如下:
module.exports = {
devServer:{
port: 8036,
hot: true,
open: 'Google Chrome'
}
}
四、Reset CSS样式
在src/assets/css文件夹下新建base.less文件,
文件内容如下: base.less
在main.js文件写入
import 'css/base/base.less';
五、引入Element-Ui组件库
-
安装依赖包
执行
npm i element-ui -save
命令 -
引入样式
在main.js中
new Vue
前插入以下代码import 'element-ui/lib/theme-chalk/index.css';
-
完整引入Element-Ui组件库(二选一)
如果Element-Ui中的大部分组件,项目中都有使用到,建议完整引入
在main.js中
new Vue
前插入以下代码import ElementUI from 'element-ui'; Vue.use(ElementUI);
-
按需引入Element-Ui组件库(二选一)
以引入Button按钮组件为例
-
在main.js中
new Vue
前插入以下代码//注册element-ui组件 import { Button, } from 'element-ui'; const components = [ Button, ]; for (let k of components) { Vue.use(k); }
-
在src/views/home.vue文件写入
<template> <div> 欢迎使用Vue项目 {{tip}} {{moduleTip}} <el-button>饿了吗Button组件</el-button> </div> </template>
-
如果在浏览器页面上出现如以下图片,则说明按需引入成功
-
5. 自定义主题(批量改变element组件样式)
-
因为element的样式是用sass写的,所以要先安装sass 和 sass-loader两个插件,执行
npm i sass sass-loader -D
命令; -
在src/assets/css/base文件夹中,新建element_theme.scss 和 element_var.scss(主题样式各种变量);
-
在main.js中写入
import 'css/base/element_theme.scss';
-
在src/views/home.vue文件写入
<template> <div> 欢迎使用Vue项目 {{tip}} {{moduleTip}} <el-button type="primary">饿了吗Button组件</el-button> </div> </template>
-
按F12打开开发者工具,审查元素可以看下图所示
- 在element_var.scss文件中搜索
#4574d0
,可以看到下图所示,将其替换成$--color-primary: red !default;
- 浏览器页面展示所下图所示,即自定义主题成功
六、安装Jquery Js库
虽然Vue是以数据操作DOM。但是在某些情况下用Jquery还是比较方便的,比如获取某元素的高度,动态变化表格的高度使其固定头部。
- 执行命令
npm i Jquery -save
- 在vue.config.js文件中新增代码:
const webpack = require('webpack'); module.exports = { configureWebpack: { plugins: [ new webpack.ProvidePlugin({ $:"jquery", jQuery:"jquery", "windows.jQuery":"jquery" }) ] }, }
- 在main.js文件中新增代码:
import $ from 'jquery';
- 在src/views/home.vue文件中新增代码做验证:
<template> <div class="p-wrap"> 欢迎使用Vue项目 {{tip}} {{moduleTip}} <el-button type="primary">饿了吗Button组件</el-button> </div> </template> <script> export default { mounted(){ $(".p-wrap").click(function(){ alert('Jquery安装成功') }); } } </script>
- 点击浏览器页面文字部分弹出“Jquery安装成功”的弹窗,说明Jquery Js库安装成功
七、关于less-loader的坑
在对应less-loader的版本为4.1.0时,安装less的版本应该为2.7.3,不然会出现
ERROR in ./src/home/index.less
(./node_modules/_css-loader@1.0.0@css-loader!./
node_modules/_less-loader@4.1.0@less-loader/dist/cjs.js!./src/home/index.less)
Module build failed (from ./node_modules/_less-loader@4.1.0@less-loader/dist/cjs.js):
报错
八、安装js-cookie 插件
- 这个插件主要用于浏览器cookie的存储、获取、移除,最常用是存储登录成功后后端返回的token。
- 执行命令
npm i js-cookie --save
- 在src/service文件下新建cookie.js文件,在文件中写入
import Cookies from 'js-cookie'; const TokenKey = 'token'; export function getToken() { return Cookies.get(TokenKey); } export function setToken(token, time) { return Cookies.set(TokenKey, token, { expires: time, path: '/' }); } export function removeToken() { return Cookies.remove(TokenKey); }
九、配置axios
-
执行命令
npm i axios -save
-
在src/api文件夹下新建axios.js文件
-
在axios.js配置axios
-
创建新的axios实例,
axios.create([config])
,主要配置
timeout
指定请求超时的毫秒数(0 表示无超时时间)headers
自定义请求头,这部分配置要和后端一致,否则后端会接收不到你的参数baseURL
配置后端的请求地址,将自动加在url
前面,使url
可用相对地址import axios from 'axios'; const service = axios.create({ timeout: 60000, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', "X-Requested-With": "XMLHttpRequest", }, baseURL: 'xxx', });
上面配置,前端传给后端的数据格式为Form格式或JSON格式,例:
//Form格式 let data = new URLSearchParams(); data.append("page", currentPage); //JSON格式 let obj = new Object; obj.page=currentPage;
如果后端使JAVA,一般使用Form格式
但是要传二进制数据给后端时,要用FormData格式,例:
let data = new FormData(); data.append("page", currentPage);
那么还要创建一个新的axios实例
const serviceForm = axios.create({ timeout: 60000, headers: { 'Content-Type': 'multipart/form-data; charset=UTF-8', "X-Requested-With": "XMLHttpRequest", }, baseURL: 'xxx', });
-
配置http request 拦截器
在请求被 then 或 catch 处理前拦截它们
axios.interceptors.request.use(function (config) { // 在发送请求之前做些什么 return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); });
一般项目中都是在这里给请求头部带上token,按如下配置
import { getToken } from 'service/cookie'; //http request 拦截器 在发送请求之前做些什么 let request = function (config) { const token = getToken(); if (token) { // 判断是否存在token,如果存在的话,则每个http header都加上token config.headers.token = token; } return config; };
以上
config.headers.token
中token是后端告知要在头部添加token的参数,后端也要配置headers允许带token的参数,否则会造成跨域。再写个请求错误时候拦截
//http request 拦截器 在请求错误时做些什么 let request_err = function (err) { return Promise.reject(err); };
给每个实例使用这些request拦截器
service.interceptors.request.use(request, request_err); serviceForm.interceptors.request.use(request, request_err);
-
配置http response 拦截器
在响应被 then 或 catch 处理前拦截它们。
// 添加响应拦截器 axios.interceptors.response.use(function (response) { // 对响应数据做点什么 return response; }, function (error) { // 对响应错误做点什么 return Promise.reject(error); });
一般项目中都是在这里给返回数据做预处理和对报错批量处理,类似提示。
响应成功前做拦截处理
import { Message } from 'element-ui'; let response = function (res) { const data = res.data; const message = `${data.code}--${data.msg}` || '未知错误' if (res.status == 200) { if (data.code == 200) { return data; } else { Message({ message: message, type: 'error', }) } } };
以上
data.code
、data.msg
这些都是要和后端协商响应失败前拦截处理
let response_err = function (err) { if (err.response) { const data = err.response.data; const message = `${data.code}--${data.msg}` || '未知错误' Message({ message: message, type: 'error', }) } return Promise.reject(err); };
给每个实例使用这些response拦截器
service.interceptors.response.use(response, response_err); serviceForm.interceptors.response.use(response, response_err);
最后对外暴露axios的两个实例
有两种方法
一种是直接挂在window对象下,这样写可以在其它文件中直接使用service和serviceForm
window.service = service; window.serviceForm = serviceForm;
一种是用export导出,这样写在其它文件中使用要先
import {service,serviceForm} from 'api/axios'
export {service,serviceForm}
-
在main.js文件中引入axios配置文件
import 'api/axios'
-
在src/api文件夹下新建demo.js文件,在里面实例post、get、get带参数的请求写法
/* get请求 */ export function get() { return service.get('api/get'); } /* get请求带参数 */ export function get2(data) { return service.get('api/get2', { params: data }); } /* post请求带参数 */ export function post(data) { return service.post('api/post', data); }
-
在src/views/home.vue中使用
import * as API from 'api/demo'; export default { methods: { get() { API.get().then(res => { }).catch(err => { }) }, get2() { let data =new URLSearchParams; data.append('param',1) API.get2(data).then(res => { }).catch(err => { }) }, post() { let data =new URLSearchParams; data.append('param',1) API.post(data).then(res => { }).catch(err => { }) } } }
-
最后
附上项目地址