准備工作
需求由來: 當項目越來越大的時候提高項目運行編譯速度、壓縮代碼體積、項目維護、bug修復......等等成為不得不考慮而且不得不做的問題。
又或者后面其他同事接手你的模塊,或者改你的bug時避免人家看的眼痛以及心里千百句mamaipi...問候。
並且一個好的開發思路也能大大提高開發效率,以及檢驗自己。
進入正題:
在本地用 vue-cli
新建一個項目,這個步驟vue的官網上有,我就不再說了。
這里展示一下我的項目架構目錄 這次主要講紅字具體實現部分
├── build // 項目build腳本 ├── config // 項目配置目錄 ├── dist // 項目輸出部署目錄,執行 npm run build后生成 ├── src // 生產目錄 │ ├── assets // 靜態資源,包含圖片等 │ ├── components // 項目公用組件,例如Header、Footer組件等 │ ├── mock // 接口mock文件目錄 │ └── index.js // mock接口集合文件 │ ├── pages // 頁面目錄 │ │ ├── Demo // Demo模塊,必須用大寫開頭 │ │ │ ├── components // Demo模塊專用組件 組件建議全部首字母大寫 │ │ │ ├── style // Demo模塊專用css │ │ │ ├── services // Demo模塊服務,可以包含相應方法類 │ │ │ ├── interface.js // Demo模塊接口結合文件 │ │ │ └── index.vue // Demo模塊頁面入口 │ │ └── Other // 其他頁面目錄 │ ├── router // 路由配置文件,如果路由太多了,可以拆分 │ ├── services // 項目公用配置服務 │ │ │ ├── ajax.js // 所有接口請求公共配置 可以和 request.js 合並一起 不嫌代碼太長的話 │ │ │ ├── request.js // (需求有則添加) 為所有接口設置公共請求頭 │ │ │ ├── prompt.js // 全局的提示 例如:接口錯誤提示、保存成功提示、操作錯誤提示等等... │ │ │ ├── validate.js // 全局表單校驗具體封裝可參照element-ui form表單模塊 │ ├── App.vue // 組件入口 │ ├── config.js // 項目配置文件 例如:權限校驗,cookie設置、access_token獲取等等... │ ├── interface.js // 項目公共接口文件 │ └── main.js // Webpack 預編譯主入口 ├── style // 項目公用style ├── static // 靜態文件目錄,保留 │ └── i18n // 國際化目錄,每一個目錄為一種語言 │ ├── zh // 中文目錄 │ │ └── index.json // 配置文件 │ └── en // 英文目錄 ├── index.html // 項目入口文件,一般不用改動 ├── package.json // 項目配置 ├── README.md // 項目說明 ├── CHANGE_LOG.md // 項目更新歷史文檔 └── test // 測試目錄
services/aiax.js文件
/** * ajax 模塊,可以將 axios 替換成 $.ajax 等 */ import axios from 'axios'; import globalConfig from '../config' import { Notification } from 'element-ui' // 注: 具體設置具體判斷 根據公司項目需求 以及 接口需求 現在以我公司為例 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 // 因為相同環境下的所有接口前綴肯定是一樣的 window.localStorage.gatewayDomain 為前綴域名 倘若后面更改域名之類的 只需改一個地方就行了 就不用說每個調接口的地方都去改 維護便捷 // 若想了解分環境打包以及分環境設置 公共域名、前綴等 請看以往博文 https://www.cnblogs.com/ljx20180807/p/9456489.html config.url = window.localStorage.gatewayDomain + config.url // 登錄時設置 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 響應攔截器 axios.interceptors.response.use(function (response) { // 這里是當接口請求服務器成功響應的情況 解構賦值出需要的數據 const {status, data} = response; if (status === 200) { // 如果不出現錯誤,直接向回調函數內輸出 data 狀態200 if (data.error === 'SUCCESS') { // 成功不用提示 return data } else { // 若出現錯誤則彈窗錯誤提示 if (data.message) { Notification({ title: '錯誤', message: data.message, type: 'error', customClass: 'el-error-msg', duration: 2000 }) } return data } } else { return response; } }, function (error) { // 這里是當接口請求失敗的情況 (例如服務器沒響應、后台代碼問題之類的) (具體的響應判斷根據你后台返回狀態碼結構) 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 // 自動跳轉返回登錄頁重新獲取access_token } }) } else { // 這是請求url不對的情況 console.log('404 error %o' + error); } } // Do something with response error 對響應錯誤做點什么 return Promise.reject(error.message); }); }; export default { init }
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 }
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: 多參數情況 獲取列表 * @param data 參數 * @returns {*} */ function getImageList(data) { return axios.get(INTERFACE.GET_IMAGE_LIST, { params: data }).catch(function (error) { window.Alert(error); }); } /** * 方式2: es6模板語法 獲取基本信息 * @param data 參數 * @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, };
page/Demo/index.vue文件
<script>
// 引入上面的接口文件 import INTERFACE from './interface' export default { data() { return { imageList: [], deleteList: [] } }, created() { // 獲取列表 (調用封裝好的請求) INTERFACE.getImageList().then(data => { if (data && data.data) this.imageList = data.data }) }, methods: { // 確認刪除 handleDelete() { INTERFACE.deleteAgreement(this.deleteList).then(data => { // 操作成功提示 (上面定義好的全局提示) window.Tips('刪除成功!') }) } } } </script>
src/main.js文件
import Vue from 'vue' import ElementUI from 'element-ui' import App from './App' import ajax from '@/services/ajax' // axios 統一配置 ajax.init() // 全局變量 indow.localStorage.gatewayDomain = 'https://dev-api.cn/' window.localStorage.defaultLanguage = 'ZH_CN'
src/App.vue文件
<script> import prompt from '@/services/prompt' export default { name: 'app', mounted() { // 全局錯誤初始化 prompt.init.call(this) } } </script>
以上就是pc端的項目配置化、請求統一管理內容了。有疑問的地方留言看到后會第一時間回復,或可改進的地方歡迎指導, 下面介紹vuex管理版本。
移動端結合Vuex 統一管理請求 stroe/actions.js文件
import Vue from 'vue' // 全局域名 const apiUrlBase = window.apiUrlBase const API_URL = { GET_APPLICENT: `${apiUrlBase}/app/v1/apply/dictionaries` } const actions = { /** * 獲取投保人數據字典 */ 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
.vue文件里調用
this.$store.dispatch(`${storeName}/getApplicent`) .then((data) => { console.log(data) })
這就可以啦。
本文為原創 轉載請注明出處 。