前言:博主工作后第一个移动端项目,也是博主参考以前的项目瑟瑟发抖从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
最后就是打包部署上线了。