最近公司來了個新項目,以前Vue項目都是用Vue CLI2搭建的,如今準備用Vue CLI3搭建,謹以此文記錄實戰過程,若是以爲此文對您有幫助,幫忙點個贊,謝謝。持續更新中…………css
npm uninstall vue-cli -g
卸載;npm install -g @vue/cli
安裝Vue CLI3;vue --version
,查看Vue CLI的版本號是不是3.0以上,是表明安裝成功。vue create flow_manage_platform
,flow_manage_platform
爲項目名稱;經過Vue CLI搭建的Vue項目中有不少無用的文件和代碼,須要對其作一次清潔。html
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
複製代碼
改爲"scripts": {
"dev": "vue-cli-service serve",
"build": "vue-cli-service build"
},
複製代碼
由於在Vue CLI2中使用npm run dev
命令啓動項目。npm install
安裝依賴,安裝成功後,執行npm run dev
,執行成功後在瀏覽器打開 http://localhost:8080/ ,頁面展現以下圖所示,說明Vue項目已經搭建成功。清潔後以下:前端
<!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>
複製代碼
清潔後以下:vue
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')
},
]
})
複製代碼
清潔後以下:node
<template>
<div>
<router-view/>
</div>
</template>
複製代碼
刪除views文件夾中的About.vue和Home.vue文件,jquery
新建home.vue文件.內容以下:webpack
<template>
<div>
歡迎使用Vue項目
</div>
</template>
複製代碼
刪除components文件夾中的HelloWorld.vue文件。ios
刪除assets文件夾夾中的logo.png文。git
從新執行npm run dev
,執行成功後在瀏覽器打開 http://localhost:8080/ ,頁面展現以下圖所示,說明Vue項目已經清潔成功。github
清潔完畢後,但其仍是不知足咱們項目開發的要求,須要咱們進一步配置。
在src文件夾下新建api文件夾,主要放置axios的配置文件axios.js和接口文件。
在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('全局混亂引入成功')
},
複製代碼
刪除!
在src文件夾下新建service文件夾,主要放置公共方法、配置文件。
在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;
複製代碼
在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配置成功。
在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'),
}
}
},
}
複製代碼
關閉source map有兩個好處
在vue.config.js文件中配置內容以下:
module.exports = {
productionSourceMap: false,
}
複製代碼
固定端口
有時候後端設置跨域白名單時候要固定端口,前端也要配合固定端口,port: 8036,
開啓熱更新
hot: true,
固定打開瀏覽器
open: 'Google Chrome',
在vue.config.js文件中配置內容以下:
module.exports = {
devServer:{
port: 8036,
hot: true,
open: 'Google Chrome'
}
}
複製代碼
在src/assets/css文件夾下新建base.less文件,
文件內容以下: base.less
在main.js文件寫入
import 'css/base/base.less';
複製代碼
安裝依賴包
執行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>
複製代碼
若是在瀏覽器頁面上出現如如下圖片,則說明按需引入成功
由於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打開開發者工具,審查元素能夠看下圖所示
#4574d0
,能夠看到下圖所示,將其替換成$--color-primary: red !default;
雖然Vue是以數據操做DOM。可是在某些狀況下用Jquery仍是比較方便的,好比獲取某元素的高度,動態變化表格的高度使其固定頭部。
npm i Jquery -save
const webpack = require('webpack');
module.exports = {
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
$:"jquery",
jQuery:"jquery",
"windows.jQuery":"jquery"
})
]
},
}
複製代碼
import $ from 'jquery';
複製代碼
<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>
複製代碼
在對應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):
複製代碼
報錯
npm i js-cookie --save
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);
}
複製代碼
執行命令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 => {
})
}
}
}
複製代碼
附上項目地址