前言:博主工作后第一個移動端項目,也是博主參考以前的項目瑟瑟發抖從0到1建起來的項目,特此記錄一下,過程並不會面面俱到,僅針對本次項目而已。
第一步:vue項目搭建,可參考各大vue項目搭建教程,在這里博主偷懶,直接用了HbuilderX自帶的一鍵創建。
第二步:項目建立后,先做一些初始化工作,首當其沖是git init,方便管理代碼,然后npm下載一些vue常用的包,設置.gitignore文件忽略一些不必往遠程倉庫上傳的文件,如node_modules。
vue的基本包:vue-router(路由跳轉),vuex(自帶),axios(用來封裝請求)UI庫(本次項目是移動端,所以用了vant),sass-loader(用來支持sass)
第三步:基本配置結束后,開始做移動端配置,清空樣式,設置移動端樣式適配,不許用戶放大界面啥啥啥的,此類博客多得是,找找看差不多了。
這一步,重置全局樣式可單獨在寫一個文件里,然后在main.js里引入,樣式配置在public下的index.html書寫<meta>標簽即可。
第四步:根據設計圖划分組件,配置路由,這都是最基礎的知識,不提了。
第五步:靜態頁面畫的差不多了,各頁面之間跳轉關系也做好了,接下來就要做請求配置之類的了。
五(一):封裝axios請求,自行百度axios官網。
五(二):首先先設置一個過濾器,博主需要對所有請求進行攔截,在請求頭里添加用戶的token,如下圖
五(三):接下來就可以封裝get,post等之類的請求函數了,博主將他們放在Http這個對象里,並對外暴露,到時候請求的時候,只需將Http引入,使用Http.post()函數就可以了。
1 export const Http = { 2 /** 3 * get請求 4 * @param url 5 * @param param 6 * @param isLoading 7 */ 8 get: function (url, param = {}, isLoading = false) { 9 return new Promise((resolve, reject) => { 10 if (isLoading) { 11 var loadingInstance = Loading.service({ 12 text: "拼命加載中" 13 }); 14 } 15 axios.get(url, param).then(response => { 16 if (isLoading) { 17 loadingInstance.close(); 18 } 19 var result = response; 20 if (result.status === 200 || result.status === 201 || result.status === 208) { 21 resolve(result.data); 22 } else { 23 Notify({ 24 message: '系統異常', 25 type: 'warning' 26 }); 27 } 28 reject(result); 29 }).catch(reason => { 30 if(reason.response&&reason.response.status === 500){ 31 Notify(reason.toString()) 32 reject(reason); 33 return 34 } 35 if(reason.response&&reason.response.status === 401){ 36 Notify(reason.response.data.message) 37 reject(reason); 38 return 39 } 40 try { 41 reject(reason.response.data) 42 } 43 catch(e){ 44 Notify(reason.toString()) 45 } 46 }) 47 }) 48 49 }, 50 /** 51 * post請求 52 * @param url 53 * @param param 54 * @param isLoading 55 */ 56 post: function (url, param = {}, isLoading = false) { 57 return new Promise((resolve, reject) => { 58 if (isLoading) { 59 var loadingInstance = Loading.service({ 60 text: "拼命加載中" 61 }); 62 } 63 axios.post(url, param).then(response => { 64 if (isLoading) { 65 loadingInstance.close(); 66 } 67 var result = response.data; 68 69 if (response.status === 201 || response.status === 200) { 70 resolve(result); 71 } else { 72 Notify({ 73 showClose: true, 74 message: '系統異常', 75 type: 'error' 76 }); 77 reject(result); 78 } 79 }).catch(reason => { 80 console.error(reason); 81 if (reason.response.status === 401) { 82 Notify('認證信息失效,請重新登錄') 83 return 84 } 85 if(reason.response&&reason.response.status === 500){ 86 Notify(reason.toString()) 87 reject(reason); 88 } 89 try { 90 reject(reason.response.data) 91 } 92 catch(e){ 93 Notify(reason.toString()) 94 } 95 }) 96 }) 97 98 }, 99 delete: function name(url, param = {}, isLoading = false) { 100 if (isLoading) { 101 var loadingInstance = Loading.service({ 102 text: "拼命加載中" 103 }); 104 } 105 return new Promise((resolve, reject) => { 106 axios.delete(url, param) 107 .then(function (response) { 108 if (response.status === 204) { 109 resolve(response.data); 110 } else { 111 reject(response.data); 112 } 113 }) 114 .catch(function (reason) { 115 if(reason.response&&reason.response.status === 500){ 116 Notify(reason.toString()) 117 reject(reason); 118 return 119 } 120 try { 121 reject(reason.response.data) 122 } 123 catch(e){ 124 Notify(reason.toString()) 125 } 126 }); 127 }) 128 }, 129 put: function name(url, param = '', isLoading = false) { 130 //debugger 131 if (isLoading) { 132 var loadingInstance = Loading.service({ 133 text: "拼命加載中" 134 }); 135 } 136 return new Promise((resolve, reject) => { 137 138 axios.put(url, param) 139 .then(function (response) { 140 if (response.status === 204 || response.status === 200) { 141 resolve(response.data) 142 } else { 143 reject(response.data) 144 } 145 }) 146 .catch(function (reason) { 147 if(reason.response&&reason.response.status === 500){ 148 Notify(reason.toString()) 149 reject(reason); 150 return 151 } 152 try { 153 reject(reason.response.data) 154 } 155 catch(e){ 156 Notify(reason.toString()) 157 } 158 }); 159 }) 160 }, 161 patch: function name(url, param = '', isLoading = false) { 162 //debugger 163 if (isLoading) { 164 var loadingInstance = Loading.service({ 165 text: "拼命加載中" 166 }); 167 } 168 return new Promise((resolve, reject) => { 169 170 axios.patch(url, param) 171 .then(function (response) { 172 if (response.status === 201 || response.status === 204||response.status === 200) { 173 resolve(response.data) 174 } else { 175 reject(response.data) 176 } 177 }) 178 .catch(function (reason) { 179 if(reason.response&&reason.response.status === 500){ 180 Notify(reason.toString()) 181 reject(reason); 182 return 183 } 184 try { 185 reject(reason.response.data) 186 } 187 catch(e){ 188 Notify(reason.toString()) 189 } 190 }); 191 }) 192 } 193 } 194 195 export default Http
五(四):請求函數有了,還差接口,封裝一個api接口文件,真正請求的時候,Http.請求方式(Api.接口)即可,這時,服務器地址應該也有了,在項目根目錄下配置一個.env.development文件,配置服務器地址的全局變量。
目錄如下圖:
在.env.development中書服務器地址的全局變量,變量需大寫VUE_APP開頭
第六步:配置代理
靜態頁面和請求函數准備好后,就准備和后端交互了,這時候八成會出現跨域問題。在項目根目錄下配置vue.config.js文件,沒有的話自己在編輯器創建一個就好,加載項目是會自動載入相關配置。
下列代碼的24行輸入自己項目的服務器地址,25行的changeOrigin設置為true,表示允許跨域即可。
1 module.exports = { 2 3 publicPath: "./", 4 outputDir: "dist", 5 assetsDir: "static", 6 lintOnSave: false, 7 productionSourceMap: false, 8 devServer: { 9 port: port, 10 open: true, 11 overlay: { 12 warnings: false, 13 errors: true 14 }, 15 proxy: { 16 [process.env.VUE_APP_BASE_API]: { 17 target: `http://localhost:${port}`, 18 changeOrigin: true, 19 pathRewrite: { 20 ["^" + process.env.VUE_APP_BASE_API]: "" 21 } 22 }, 23 "/api": { 24 target: process.env.VUE_APP_API, 25 changeOrigin: true 26 } 27 }, 28 }, 29 configureWebpack: { 30 name: name, 31 resolve: { 32 alias: { 33 "@": resolve("src") 34 } 35 } 36 }, 37 };
第七步 配置vuex
可以與后端正常交互后,意味着可以用數據渲染頁面,開始書寫請求接口后的邏輯處理,這時,博主的項目需要用到vuex,有的項目不需要可以跳過這一步。
七(一):src文件下創建store文件,用來配置vuex,關於vuex的配置博客也很多,可以搜搜看,多看幾個模模糊糊就知道大概是什么情況了。
首先,在store文件里創建一個index.js作為vuex的入口,然后在main.js 引入,即可使用vuex
store/index.js代碼如下圖
main.js里引入
七(二):在store里寫actions.js、getters.js 、mutations.js文件,分別暴露出actions、getters、mutations,vuex支持模塊化,支持每個模塊有自己的vuex,博主的項目是第一版,雖然只有一個模塊,為了以后好擴展迭代,博主依舊選擇了設立了modules文件。
通過調用actions里的方法,通過mutations改變state里的數據。頁面中通過this.$store.dispatch調用actions里的方法,actions里通過commit調用mutations。
為了方便vuex到底是如何運行的,可以看https://www.cnblogs.com/songzxblog/p/12713346.html
第八步:vuex寫好后,就是業務邏輯的調試,調試成功后,就要打包發版了。
開發環境,生產環境和正式環境下,服務器域名不同,需要我們配置不同的全局變量。
第五步的第四小步中,我們配置了本地的服務器地址變量,在這我們在單獨去配置生產環境和正式環境下的就好。
跟.env.development一樣,配置 .env.staging文件用來放測試環境的服務器地址變量和 .env.production來放正式環境的服務器地址。
.env.staging
.env.production
最后就是打包部署上線了。