前言:博主工作后第一个移动端项目,也是博主参考以前的项目瑟瑟发抖从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到底是如何运行的,可以看
第八步:vuex写好后,就是业务逻辑的调试,调试成功后,就要打包发版了。
开发环境,生产环境和正式环境下,服务器域名不同,需要我们配置不同的全局变量。
第五步的第四小步中,我们配置了本地的服务器地址变量,在这我们在单独去配置生产环境和正式环境下的就好。
跟.env.development一样,配置 .env.staging文件用来放测试环境的服务器地址变量和 .env.production来放正式环境的服务器地址。
.env.staging
.env.production
最后就是打包部署上线了。