準備工作
需求由來: 當項目越來越大的時候提高項目運行編譯速度古话、壓縮代碼體積雏吭、項目維護、bug修復(fù)......等等成為不得不考慮而且不得不做的問題陪踩。
又或者后面其他同事接手你的模塊杖们,或者改你的bug時避免人家看的眼痛以及心里千百句mamaipi...問候。
并且一個好的開發(fā)思路也能大大提高開發(fā)效率肩狂,以及檢驗自己摘完。
進入正題:
在本地用 vue-cli 新建一個項目,這個步驟參照vue的官網(wǎng)傻谁。
這里展示一下我的項目架構(gòu)目錄 這次主要講紅字具體實現(xiàn)部分
1孝治、項目地圖
├── build // 項目build腳本
├── config // 項目配置目錄
├── dist // 項目輸出部署目錄,執(zhí)行 npm run build后生成
├── src // 生產(chǎn)目錄
│ ├── assets // 靜態(tài)資源栅螟,包含圖片等
│ ├── components // 項目公用組件荆秦,例如Header营罢、Footer組件等
│ ├── mock // 接口mock文件目錄
│ └── index.js // mock接口集合文件
│ ├── pages // 頁面目錄
│ │ ├── Demo // Demo模塊悔叽,必須用大寫開頭
│ │ │ ├── components // Demo模塊專用組件 組件建議全部首字母大寫
│ │ │ ├── style // Demo模塊專用css
│ │ │ ├── services // Demo模塊服務(wù),可以包含相應(yīng)方法類
│ │ │ ├── interface.js // Demo模塊接口結(jié)合文件
│ │ │ └── index.vue // Demo模塊頁面入口
│ │ └── Other // 其他頁面目錄
│ ├── router // 路由配置文件显拜,如果路由太多了吃媒,可以拆分
│ ├── services // 項目公用配置服務(wù)
│ │ │ ├── ajax.js // 所有接口請求公共配置 可以和 request.js 合并一起 不嫌代碼太長的話
│ │ │ ├── request.js // (需求有則添加) 為所有接口設(shè)置公共請求頭
│ │ │ ├── prompt.js // 全局的提示 例如:接口錯誤提示瓤介、保存成功提示、操作錯誤提示等等...
│ │ │ ├── validate.js // 全局表單校驗具體封裝可參照element-ui form表單模塊
│ ├── App.vue // 組件入口
│ ├── config.js // 項目配置文件 例如:權(quán)限校驗赘那,cookie設(shè)置刑桑、access_token獲取等等...
│ ├── interface.js // 項目公共接口文件
│ └── main.js // Webpack 預(yù)編譯主入口
├── style // 項目公用style
├── static // 靜態(tài)文件目錄,保留
│ └── i18n // 國際化目錄募舟,每一個目錄為一種語言
│ ├── zh // 中文目錄
│ │ └── index.json // 配置文件
│ └── en // 英文目錄
├── index.html // 項目入口文件祠斧,一般不用改動
├── package.json // 項目配置
├── README.md // 項目說明
├── CHANGE_LOG.md // 項目更新歷史文檔
└── test // 測試目錄
2、services/aiax.js文件
/**
* ajax 模塊拱礁,可以將 axios 替換成 $.ajax 等
*/
import axios from 'axios';
import globalConfig from '../config'
import { Notification } from 'element-ui'
// 注: 具體設(shè)置具體判斷 根據(jù)公司項目需求 以及 接口需求 現(xiàn)在以我公司為例
const init = function () {
// 添加 axios 請求攔截器為所有請求加上前綴 琢锋、 access_token (我公司所有接口都比要有 access_token才能訪問)
// 有對 axios 不是很了解的 可以看看 axios 官方文檔 https://www.kancloud.cn/yunye/axios/234845
axios.interceptors.request.use(function (config) {
// 為所有接口加上前綴 例 https://www.kancloud.cn/yunye/axios/234845 前綴為 https://www.kancloud.cn
// 因為相同環(huán)境下的所有接口前綴肯定是一樣的 window.localStorage.gatewayDomain 為前綴域名 倘若后面更改域名之類的 只需改一個地方就行了 就不用說每個調(diào)接口的地方都去改 維護便捷
// 若想了解分環(huán)境打包以及分環(huán)境設(shè)置 公共域名、前綴等 請看以往博文 https://www.cnblogs.com/ljx20180807/p/9456489.html
config.url = window.localStorage.gatewayDomain + config.url
// 登錄時設(shè)置 cookies
var cookies = globalConfig.getCookies()
if (config.url.indexOf('?') < 0) {
config.url += '?'
}
// 為所有接口加上 access_token
config.url += ('access_token=' + cookies['access_token'])
if (!config.data) config.data = {}
return config;
}, function (err) {
// 錯誤處理
return Promise.reject(err)
})
// 添加 axios 響應(yīng)攔截器
axios.interceptors.response.use(function (response) {
// 這里是當接口請求服務(wù)器成功響應(yīng)的情況 解構(gòu)賦值出需要的數(shù)據(jù)
const {status, data} = response;
if (status === 200) {
// 如果不出現(xiàn)錯誤呢灶,直接向回調(diào)函數(shù)內(nèi)輸出 data 狀態(tài)200
if (data.error === 'SUCCESS') {
// 成功不用提示
return data
} else {
// 若出現(xiàn)錯誤則彈窗錯誤提示
if (data.message) {
Notification({
title: '錯誤',
message: data.message,
type: 'error',
customClass: 'el-error-msg',
duration: 2000
})
}
return data
}
} else {
return response;
}
}, function (error) {
// 這里是當接口請求失敗的情況 (例如服務(wù)器沒響應(yīng)吴超、后臺代碼問題之類的) (具體的響應(yīng)判斷根據(jù)你后臺返回狀態(tài)碼結(jié)構(gòu))
const {response} = error;
// 這里處理錯誤的 http code
if (!response || response.status === 404) {
if (!response) { // access_token 失效的情況 彈窗提示
Notification({
title: '錯誤',
message: 'access_token已失效請重新登錄',
type: 'error',
customClass: 'el-error-msg',
duration: 1500,
onClose() {
window.location.href = window.localStorage.loginUrl // 自動跳轉(zhuǎn)返回登錄頁重新獲取access_token
}
})
} else {
// 這是請求url不對的情況
console.log('404 error %o' + error);
}
}
// Do something with response error 對響應(yīng)錯誤做點什么
return Promise.reject(error.message);
});
};
export default {
init
}
3、services/prompt.js文件
const init = function () {
const _this = this;
// 建議為了方便使用鸯乃,這里可以包裝window.Alert 具體怎么使用往下看
window.Alert = function (msg, duration = 3000) {
// 錯誤提示
_this.$notify({
title: '錯誤',
message: msg,
type: 'error',
customClass: 'el-error-msg',
duration
});
}
// 成功提示
window.Tips = function (msg, duration = 3000) {
_this.$notify({
title: '成功',
message: msg,
type: 'success',
duration
});
}
// 警告提示
window.Warning = function (msg, duration = 3000) {
_this.$notify({
title: '警告',
message: msg,
type: 'warning',
duration
});
}
// 全局延時器
window.SetTimeout = function (path, queryObject) {
setTimeout(_ => {
_this.$router.push({
path: path,
query: queryObject
});
}, 500)
}
};
export default {
init
}
3鲸阻、page/Demo/interface.js文件 (pc端不建議用vuex 具體看需求吧 vuex管理版本 往下看)
import axios from 'axios';
const ajax = {
// 獲取影像件上傳列表
GET_IMAGE_LIST: 'images?'
};
// 提取公共部分
const API_PATH_PRE_FIX = 'apply/v1/';
// 增加接口模塊前綴
let INTERFACE = {};
for (let key in ajax) {
INTERFACE[key] = API_PATH_PRE_FIX + ajax[key];
}
/**
* 方式1: 多參數(shù)情況 獲取列表
* @param data 參數(shù)
* @returns {*}
*/
function getImageList(data) {
return axios.get(INTERFACE.GET_IMAGE_LIST, {
params: data
}).catch(function (error) {
window.Alert(error);
});
}
/**
* 方式2: es6模板語法 獲取基本信息
* @param data 參數(shù)
* @returns {*}
*/
function getContrantInfo(API_PATH_PRE_FIX, agreementId) {
return axios.get(`${API_PATH_PRE_FIX}/middle/agreement/basic?agreementId=${agreementId}&`).catch(function (error) {
window.Alert(error);
});
}
export default {
getImageList,
getContrantInfo,
};
4、page/Demo/index.vue文件
<script>
// 引入上面的接口文件
import INTERFACE from './interface'
export default {
data() {
return {
imageList: [],
deleteList: []
}
},
created() {
// 獲取列表 (調(diào)用封裝好的請求)
INTERFACE.getImageList().then(data => {
if (data && data.data) this.imageList = data.data
})
},
methods: {
// 確認刪除
handleDelete() {
INTERFACE.deleteAgreement(this.deleteList).then(data => {
// 操作成功提示 (上面定義好的全局提示)
window.Tips('刪除成功!')
})
}
}
}
</script>
5、src/main.js文件
import Vue from 'vue'
import ElementUI from 'element-ui'
import App from './App'
import ajax from '@/services/ajax'
// axios 統(tǒng)一配置
ajax.init()
// 全局變量
indow.localStorage.gatewayDomain = 'https://dev-api.cn/'
window.localStorage.defaultLanguage = 'ZH_CN'
6鸟悴、src/App.vue文件
<script>
import prompt from '@/services/prompt'
export default {
name: 'app',
mounted() {
// 全局錯誤初始化
prompt.init.call(this)
}
}
</script>
以上就是pc端的項目配置化陈辱、請求統(tǒng)一管理內(nèi)容了。有疑問的地方留言看到后會第一時間回復(fù)遣臼,或可改進的地方歡迎指導(dǎo)性置, 下面介紹vuex管理版本。
7揍堰、移動端結(jié)合Vuex 統(tǒng)一管理請求 stroe/actions.js文件
import Vue from 'vue'
// 全局域名
const apiUrlBase = window.apiUrlBase
const API_URL = {
GET_APPLICENT: `${apiUrlBase}/app/v1/apply/dictionaries`
}
const actions = {
/**
* 獲取投保人數(shù)據(jù)字典
*/
actions.getApplicent = ({ state }) => {
return new Promise((resolve, reject) => {
Vue.http.get(`${API_URL.GET_APPLICENT}?access_token=${state.accessToken}`).then((ret) => {
resolve(ret.body)
}).catch((err) => {
reject(err)
})
})
}
}
export default actions
8鹏浅、.vue文件里調(diào)用
this.$store.dispatch(`${storeName}/getApplicent`)
.then((data) => {
console.log(data)
})
這就可以啦。