Vue项目-手机app瑞幸咖啡详解(全网最细) 从脚手架搭建到前后端数据交互(

代码 代码 2295 人阅读 | 0 人回复

<
SPA项目-瑞幸咖啡



道假话,正在写那篇专客之前,我念了好久要没有要写,写的话无疑是一项事情量宏大的任务,可是抚躬自问,那也是一次总结提拔的时机,特别关于像我如许新进门的菜,,没有新脚来讲。
好了,没有道空话了,以下将开端总结脚机使用瑞幸咖啡项目标完成(只完成了部门页里及功用),途经的年夜佬能够滑走了!
1、项目介绍

1.1、根本状况

本次项目利用vue框架完成,采取前后端共同的方法(即前端完成页里及数据衬着),后端供给接心(数据处置)。
瑞幸咖啡APP是一款咖啡类的购物APP,商品以咖啡类为主,营业流程从APP的登录到参加购物车,到付出胜利。
因为程度有限,仅完成了部门页里战功用,因为是多人合作,完成的结果各有不同。
1.2、完成的功用

1.2.1、静态页里完成

以下是部门静态页里结果
  1. 尾页
复造代码
145450r7xkkw2q3t3m5v2k.jpg

  1. 菜单页
复造代码
145450hcyccgaoflv7vhko.jpg

  1. 商品详情页
复造代码
145451ruj0ybbgjhggebq0.jpg

  1. 我的页里
复造代码
145451dfb99388ffs8af89.jpg

  1. 定单页
复造代码
145451bxtp5bd88ezgttgp.jpg

别的另有购物车页里,所在页里,新删所在页里,小我私家材料页里,确认定单页里,打消定单页里等等,页里太多,便纷歧一枚举了。
1.2.2、静态结果完成(接心)

做为一个完整的项目,必需得有前后端交互功用,假如另有新进坑的没有懂前后端交互,我能够简朴介绍下。
前端:静态页里,经由过程接心背后端收回恳求,拿到静态数据衬着正在页里,一句话总结,前端做的便是用户看获得的部门;
后端:领受前端收去的恳求,从数据库中查询数据,并返回给前端,也便是道,后端做的是用户看没有到的部门。
正在本次项目中,共完成了以下静态结果(我卖力的部门)
  1. 尾页经由过程商品范例获得对应范例的商品
  2. 尾页面击图片获得该商品的具体疑息
  3. 详情页获得该商品的一切批评疑息
  4. 详情页将该商品参加购物车
  5. 购物车页里面击结算创立定单
  6. 定单页面击商品增加批评疑息
复造代码
1.3、项目利用到的相干妙技

起首,经由过程拆建足脚架创立项目开辟情况;
正在项目开辟中,利用了mock数据,正在出有后端接心的状况下模仿完成衬着;
利用了axios背后端收收恳求,仍是用了阻拦器,那是正在收收恳求时照顾token疑息的;’
正在举办页里跳转时,因为我们做的是SPA(单页里使用),需求用路由跳转,静态路由传参等‘;
和路由捍卫,以此去判定用户能否登录(可否显现页里),懒减载妙技能够前进页里减载机能;
正在APP里经常会有一些表单考证大概遮罩层的规划,我们正在项目中引进了第三圆组件(Vant等);
正在举办组件通讯时,借用到了vueX去保留齐局数据,利用起去十分便利;
正在倡议恳求时,因为前后端别离,必将形成跨域的成绩,我们利用反背代办署理去处理跨域;
到最初,到项目团体的挨包。
以上相干妙技根本皆属于vue系列妙技,(能够参考我之前的专客, vue进门系列)我们正在项目中或多或少皆利用到。
2、项目标营业流程(完成)

第一次做vue项目,有许多瑕疵,当前有时机会完美一下,出去的年夜佬也能够正在批评区指点指点,自己尽对谦虚受教,刚进坑的小火伴也能够交流交流!
2.1、登录

登录那一部门没有是我写的,可是根本完成仍是明白的。因为本APP是出有注册页里,(仿佛年夜部门APP皆是间接登录),以是只完成了登录的功用。
2.1.1、登录的流程

  1. 1,用户输动手机号,前端停止脚机号格局考证;
  2. 2,若格局正当,用户面击获得考证码;
  3. 3,前端收恳求,后端返回考证码;
  4. 4,用户输进考证码,并面击登录;
  5. 5,若考证码准确,后端返回登录胜利疑息,同时返回token疑息;
  6. 6,前端领受token疑息,并保留正在当地(我们保留正在cookie里)
复造代码


  • 获得考证码,并考证脚机格局
  1. export default {
  2.          name: "Centent1",
  3.          data(){
  4.            return {
  5.              tel:&#39;&#39;,
  6.              code:&#39;&#39;
  7.            }
  8.          },
  9.          methods: {
  10.            fn() {
  11.            //获得考证码
  12.              axios({
  13.                url: "/api/user/sendtel",
  14.                params: {
  15.                  tel: this.tel,
  16.                },
  17.                // method:&#39;get&#39;,  默许是get恳求
  18.              })
  19.              .then((res) => {
  20.                  if(res.data.code=="1"){
  21.                    // console.log(res.data);
  22.                    console.log(&#39;收收胜利&#39;);
  23.                    this.$store.state.code = res.data.data
  24.                  }else{
  25.                    console.log(&#39;收收失利&#39;);
  26.                  }
  27.              })
  28.            },
  29.            testphone() {
  30.              var phone = this.tel;
  31.              this.$store.state.tel = this.tel
  32.              if (!/^1[3456789]\d{9}$/.test(phone)) {
  33.                 Toast.fail(&#39;脚机号有误!&#39;);
  34.                return false;
  35.              }else{
  36.                 Toast.success(&#39;脚机号可用!&#39;);
  37.              }
  38.            },
  39.          },
  40. };
复造代码
考证脚机号格局有误:
145452e5uwou5yw4g5jy04.jpg



  • 登录胜利,并保留token疑息
  1. export default {
  2.   name: "Centent2",
  3.   methods: {
  4.     fn() {
  5.       console.log(this.$store.state.tel);
  6.       axios({
  7.         url: "/api/user/login",
  8.         params: {
  9.           tel: this.$store.state.tel,
  10.           code: this.$store.state.code,
  11.         },
  12.         // method:&#39;get&#39;,  默许是get恳求
  13.       }).then((res) => {
  14.           if(res.data.code==&#39;1&#39;){
  15.             // console.log(res.data.data);
  16.             let date = new Date();
  17.             date.setDate(date.getDate()+7)
  18.             document.cookie = `token=${res.data.data};expires=${date}`;
  19.             console.log(document.cookie);
  20.             this.$router.push(&#39;/index&#39;)
  21.           }else{
  22.             console.log(&#39;登录失利&#39;);
  23.           }
  24.       });
  25.     },
  26.   },
  27. };
复造代码
获得到考证码,输进考证码
145452o4wsk5fhy1ysmrtr.jpg

留意:因为项目中利用了路由捍卫,部门页里如商品详情页,定单页正在已登录形态时(即当地出有token疑息) 没法会见。


  • 已登录时阅读器的cookie
145452hz6zn8e8oexpj08n.jpg



  • 登录胜利后阅读器的cookie
145452z37m5n5j2yy1y7wn.jpg

2.2、尾页

尾页那部门是我写的,以是我会道的更详细一面。
起首我们要明白,尾页是能够间接会见,也便是没有受token的影响,而且正在初次登录胜利后,也会跳转到尾页。
尾页的静态页眼前里曾经看过了,静态结果只要一个:面击商品范例获得对应的商品(轮播图便没有道了吧,swiper组件完成的,有喜好能够研讨研讨,上面我放上源码仅供参考)
2.2.1、尾页轮播图源码

  1. <template>
  2.     <div class="swiper-container">
  3.         <div class="swiper-wrapper">
  4.             <div class="swiper-slide"><img src="../assets/images/11.webp" alt=""></div>
  5.             <div class="swiper-slide"><img src="../assets/images/22.webp" alt=""></div>
  6.             <div class="swiper-slide"><img src="../assets/images/33.jpg" alt=""></div>
  7.             <div class="swiper-slide"><img src="../assets/images/44.webp" alt=""></div>
  8.             <div class="swiper-slide"><img src="../assets/images/55.webp" alt=""></div>
  9.             <div class="swiper-slide"><img src="../assets/images/66.webp" alt=""></div>
  10.         </div>
  11.         <!-- 假如需求分页器 -->
  12.         <div class="swiper-pagination">
  13.         </div>
  14.   </div>
  15. </template>
  16. <script>
  17. import Swiper from "swiper";
  18. import "swiper/css/swiper.css";
  19. export default {
  20.     name:"banner",
  21.     mounted(){     
  22.         new Swiper (&#39;.swiper-container&#39;, {                  
  23.             speed:800,
  24.             autoplay:true,
  25.             
  26.             // 假如需求分页器
  27.             pagination: {
  28.                 el: &#39;.swiper-pagination&#39;,
  29.             },
  30.         })      
  31.     }   
  32. }
  33. </script>
  34. <style scoped>
  35.     .swiper-container{
  36.         width: 100%;
  37.         height: 2.42rem;
  38.         position: relative;
  39.     }
  40.     .swiper-container img{
  41.         width: 100%;
  42.         height: 100%;
  43.     }
  44.     .swiper-pagination{
  45.         position: absolute;
  46.         bottom: 0.7rem;
  47.     }
  48. </style>
复造代码
2.2.2、面击商品分类获得商品

145454xh5acjcuz9bbpbrh.jpg

我们能够看到,尾页统共有4个分类,后端同窗帮我们正在数据库存好了,从左往左商品范例对应typeId为 4,5,6,7
那一起的完成方法有许多,如静态组件,组件通讯等等,我保举利用vueX,实的谁用谁道好!
完成思绪:
  1. 1,尾页默许减载第一种分类,那便正在减载页里时收收typeId为4
  2. 的恳求,获得数据并衬着;
  3. 2,面击其他分类时,再收收一次恳求,获得对应范例的商品;
  4. 3,模板衬着时的值皆去自vueX中的state,以是不消担忧
  5. 默许第一种的数据会战面击别的分类时数据反复。(我
  6. 便碰到过那个成绩,其时用静态组件做的)。
复造代码


  • 详细完成步伐(间接上源码)
  1. //store/index.js(vueX)中的代码
  2. import vueX from &#39;vuex&#39;
  3. import Vue from &#39;vue&#39;
  4. import axios from &#39;../utils/request.js&#39;
  5. Vue.use(vueX)
  6. export default new vueX.Store({
  7.     state: {
  8.         shopinfo: [],
  9.         tel: &#39;&#39;,
  10.         code: &#39;&#39;,
  11.         isshow: false,
  12.         orderInfo: ["局部", "坐等可与", "预定定单"],
  13.         outerInfo: ["门店自提", "收货上门", "瑞即购"],
  14.         isLoading: false,
  15.     },
  16.     mutations: {
  17.         //state:store中的state
  18.         change(state, payload) {
  19.             state.shopinfo = payload.data
  20.                 // console.log(state.shopinfo);
  21.         },
  22.         changeload(state, payload) {
  23.             // console.log(payload);
  24.             state.isshow = payload
  25.         },
  26.         changeIsLoading(state, payload) {
  27.             state.isLoading = payload.isLoading;
  28.         }
  29.     },
  30.     actions: {
  31.         //context:store工具
  32.         change1(context) {
  33.             axios({
  34.                     url: "/api/goods/findGoodsByType",
  35.                     params: {
  36.                         typeId: 4,
  37.                     }
  38.                 })
  39.                 .then(res => {
  40.                     console.log(res.data.data);
  41.                     context.commit(&#39;change&#39;, { //将恳求成果传给mutations
  42.                         data: res.data.data
  43.                     })
  44.                 })
  45.         },
  46.         change2(context, payload) {
  47.             // console.log(payload);
  48.             axios({
  49.                     url: "/api/goods/findGoodsByType",
  50.                     params: {
  51.                         typeId: payload,
  52.                     }
  53.                 })
  54.                 .then(res => {
  55.                     context.commit(&#39;change&#39;, { //将恳求成果传给mutations
  56.                         data: res.data.data
  57.                     })
  58.                 })
  59.         },
  60.     }
  61. })
复造代码
  1. //导航组件中的代码
  2. export default {
  3.     data(){
  4.         return {
  5.             shoplist:this.$store.state.shopinfo,
  6.         }
  7.     },
  8.     //收收恳求,获得数据
  9.     created(){
  10.         //组件里派收action
  11.         this.$store.dispatch(&#39;change1&#39;)
  12.         console.log(this.shoplist);
  13.     },
  14.     methods:{
  15.         tiao(id){
  16.             this.$router.push(&#39;/info/&#39;+id)
  17.         },
  18.          toshopcart(){
  19.             this.$router.push(&#39;/Shop&#39;)
  20.         }
  21.     }
  22. }
复造代码
面击结果图(没有会做gif图…)…
145454ereccz5hz9c9ccr5.jpg

(vueX的装置及利用能够参考我的专客
2.3、详情页(商品详情)

那个也是我写的,哈哈!
前里我们道了,面击尾页中的商品获得商品的详细疑息,经由过程静态路由传参,将商品的id(没有是范例id)传到详情页,再收收恳求。
完成思绪:
  1. 1,尾页面击商品,将商品id经由过程路由传参通报到详情页;
  2. 2,详情页领受id值,倡议恳求,获得数据,衬着。
复造代码
  1. //面击商品,获得商品详情
  2. import axios from &#39;../utils/request.js&#39;
  3. export default {
  4.     data(){
  5.         return {
  6.             shopinfo:[]
  7.         }
  8.     },
  9.     created(){  
  10.         axios({
  11.             url:&#39;/api/goods/findGoodsByGid&#39;,
  12.             params:{
  13.                 id:this.$route.params.id
  14.             }
  15.         })
  16.         .then(res=>{
  17.             if(res.data.code==&#39;1&#39;){
  18.                 // console.log(&#39;查询胜利&#39;);
  19.                 this.shopinfo = res.data.data
  20.                 // console.log(this.shopinfo);
  21.             }else{
  22.                 console.log(&#39;查询失利&#39;);
  23.             }
  24.         })
  25.     }
  26. }
复造代码
获得id为15的商品疑息
145454w4npsghw0rjtiktt.jpg

2.4、详情页(获得批评)

获得批评也是正在详情页,以是共用一个商品id,获得批评也需求传商品id。(那个该当皆能明白吧!)
完成思绪:
  1. 1,领受传去的商品id值;
  2. 2,收恳求,获得批评疑息。
复造代码


  • 获得商品的批评疑息
  1. import axios from &#39;axios&#39;;
  2. export default {
  3.     data(){
  4.         return {
  5.             comminfo:[]
  6.         }
  7.     },
  8.     created(){
  9.         axios({
  10.             url:"/api/comment/findCommentsByGid",
  11.             params:{
  12.                 gid:this.$route.params.id
  13.             }
  14.         })
  15.         .then(res=>{
  16.             // console.log(res.data);
  17.             this.comminfo = res.data.data
  18.         })
  19.     }
  20. }
复造代码
获得到的部门批评疑息:
145455cvn8cc6cmzisb8kc.jpg

是欠好偶批评疑息哪去的,往下看便明白了!
2.5、详情页(参加购物车)

一样是正在详情页,那里我用了一个vant组件,结合本人脚敲的代码。
先看结果图:(面击页里原本的参加购物车,弹出遮罩层)
145455dxbfln5352i94b25.jpg

遮罩层里的疑息战获得商品详情的代码相似,我便没有揭出源码了。
参加购物车完成思绪:
  1. 1,拿到传去的id值;
  2. 2,用户修正商品数目,获得相干参数,收恳求。
复造代码
参加购物车源码:
  1. jia() {
  2.       axios({
  3.         url:&#39;/api/cart/addCart&#39;,
  4.         method:&#39;post&#39;,
  5.         data:{
  6.           "gid": 12,
  7.           "number": 3,
  8.           "price": 2,
  9.           "total": 45,
  10.           "uid": 4
  11.         }
  12.       })
  13.       .then(res=>{
  14.         if(res.data.code==&#39;1&#39;){
  15.           console.log(res.data);
  16.           Toast.success("参加胜利!");
  17.         }else{
  18.           Toast.fail("参加失利!");
  19.         }
  20.      })
复造代码
如图为参加购物车胜利结果图:
145455u9v3wj8j8xgqgwmq.jpg

此时,数据库中购物车对应的表便有相干数据了。
2.6、菜单页

菜单页相干功用没有是我卖力的,以是我会道的出有那末详细,不外仍是会附上源码的。
菜单页,也便是各类咖啡大概奶茶下单,检察详情等一系列操纵。
2.6.1、商品的显现(典范菜单)

菜单页的商品是正在页里减载时衬着的,默许是第一种,面击其他范例时显现对应商品,完成思绪战尾页的分歧。
  1. created() {
  2.     Axios({
  3.       url: "/api/goods/findGoodsByHot",
  4.     }).then((res) => {
  5.       this.goods = res.data.data;
  6.     });
  7.     Axios({
  8.       url: "/api/goods/findGoodsByType",
  9.       params: {
  10.         typeId: 2,
  11.       },
  12.     }).then((res) => {
  13.       this.goods1 = res.data.data;
  14.     });
  15.     Axios({
  16.       url: "/api/goods/findGoodsByType",
  17.       params: {
  18.         typeId: 3,
  19.       },
  20.     }).then((res) => {
  21.       this.goods2 = res.data.data;
  22.     });
  23.   },
  24.   methods: {
  25.     ding(index) {
  26.       this.$router.push("/Detail/" + index);
  27.     },
  28.   },
复造代码
面击其他分类时结果图:
145455fnypipqf3i3klmfs.jpg

2.6.2、商品的显现(瑞纳冰季)

那一部门是一个瀑布流规划,完成思绪比较简朴,获得商品数据,按瀑布流的规划衬着。
  1. import Axios from "../untils/request";
  2. export default {
  3. name:"Pu",
  4. data(){
  5.     return {
  6.         goods:[],typeId:0,
  7.     }
  8. },created(){
  9.      Axios({
  10.       url: "/api/goods/findGoodsByType",
  11.          params:{
  12.                         typeId:8
  13.                 }
  14.     }).then((res) => {
  15.         this.goods=res.data.data;
  16.     });
  17. }
  18. }
复造代码
结果图:(以下图片的排列方法便是瀑布流,穿插的觉得)
145456lfqfi55dl5dhf8zg.jpg

2.6.3、显现商品详情

战主页面击图片跳转到详情页一样,思绪我便没有写了,皆是把商品id传已往,然后收恳求,获得数据再衬着。
附上源代码:
  1. export default {
  2. name:"Dinfo",
  3.   data() {
  4.     return {
  5.       shopinfo: [],
  6.     };
  7.   },
  8.   created() {
  9.     Axios({
  10.       url: "/api/goods/findGoodsByGid",
  11.       params: {
  12.         id: this.$route.params.id,
  13.       },
  14.     }).then((res) => {
  15.       this.shopinfo = res.data.data;     
  16.     });
  17.   },
  18. };
复造代码
差别的是,两个详情页规划有面不同。
145456l3qqsyqslpgsk3va.jpg

2.7、所在页

所在页是从菜单页跳转已往的,菜单页有个配收方法(自提/中收)仔细的同窗大要看到了。面击中收时,会跳到所在页,能够举办新删所在等操纵。
2.7.1、显现所在

完成思绪:
  1. 1,拿到用户对应的id值;
  2. 2,收恳求,获得地点疑息;
  3. 3,衬着到页里。
复造代码
  1. created() {
  2.     Axios({
  3.       url: "/api/addr/selectAddrByUserId/1",
  4.     }).then((res) => {
  5.       res.data.data.forEach((item) => {
  6.         this.list.push({
  7.           id: item.id,
  8.           name: item.userName,
  9.           tel: item.tel,
  10.           address: item.detailAddr + item.houseNumber,
  11.           isDefault:
  12.             item.defaultAddr == 1
  13.               ? (this.isDefault = true)
  14.               : (this.isDefault = false),
  15.         });
  16.       });
  17.     });
  18.   },
复造代码
获得所在疑息结果图:
145456eutogomouom8omo9.jpg

2.7.2、增加所在

既然能够查,固然也能够减,不能不道到场到项目标每位同窗皆很给力啊。面个赞。
完成思绪:
  1. 1,增加地点为post恳求,参数较多;
  2. 2,收恳求。
复造代码
  1. methods: {
  2.     onSave(con) {
  3.       Toast.success("保留胜利");
  4.       this.$router.push("./Outering");
  5.        Axios({
  6.       url: "/api/addr/addAddr",
  7.       method: "POST",
  8.       data: {
  9.         defaultAddr:1,
  10.         detailAddr: con.province+con.city+con.county,
  11.         houseNumber: con.addressDetail,
  12.         id:con.id,
  13.         label: "家",
  14.         sex: 1,
  15.         tel: con.tel,
  16.         userId: 1,
  17.         userName: con.name,
  18.       },
  19.     }).then((res) => {
  20.       console.log("res.data",res.data);
  21.     });
复造代码
增加所在:
145457c3svjvhnz2zmeqmn.jpg

2.8、定单页

定单页便是正在定单创立出去后,查询出去的结果。定单的创立是正在购物车面击结算创立的(前里提到过)。
完成思绪:
  1. 1,拿到用户id;
  2. 2,按照用户id查询一切定单疑息,再衬着。
复造代码


  • 查询定单
  1. created(){
  2.     Axios({
  3.       url:"/api/order/selectOrdersByUid/4"
  4.     }).then(res=>{
  5.       this.order=res.data.data;
  6.       this.desc=res.data.data[0].orderDetailResps;
  7.     })
  8. },
复造代码
145457lx2oeedqucuu72uz.jpg

留意:定单只要创立胜利后才气够查询。
2.9、增加批评页

增加批评是正在商品完成付出后才气够批评,信赖各人皆没有生疏,出有哪款电商APP会让您购置商品之前批评吧。
因为本页里出有增加批评页里(大概道我们出找到),以是我本人简简朴单减了个页里(粗陋版)
145457o1a7tozoot2ap8l7.jpg

写的没有好看(做为前端开辟人员…),次要适用便止。
增加批评完成思绪:
  1. 1,从定单页传去商品id和用户id,再获得文本框里输进的内乱容;
  2. 2,接纳post恳求,增加批评。(如今明白为何会有那末多批评疑息了吧!)
复造代码
  1. methods:{
  2.     back(){
  3.         this.$router.back();
  4.     },
  5.     addcomm(){
  6.       // console.log(this.txt);
  7.       axios({
  8.           url:&#39;/api/comment/addComment&#39;,
  9.           method:&#39;post&#39;,
  10.           data:{
  11.               gid:this.$route.params.id,
  12.               uid:9,
  13.               comment:this.txt
  14.           }
  15.       })
  16.       .then(res=>{
  17.           if(res.data.code==&#39;1&#39;){
  18.             Toast.success(&#39;公布胜利!&#39;);
  19.             //浑空文本框
  20.             console.log(this.txt);
  21.             this.txt = &#39;&#39;
  22.           }else{
  23.             Toast.fail(&#39;公布失利!&#39;);
  24.           }
  25.       })
  26.     }
  27.   }
复造代码
增加胜利的批评便会正在详情页显现啦!
============================================
明天的内乱容便先到那女吧,写了快一天了,后背的内乱容我会补上的!面个存眷,等待下后背的出色内乱容吧!
后绝篇戳我浏览!

免责声明:假如进犯了您的权益,请联络站少,我们会实时删除侵权内乱容,感谢协作!
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请您发送邮箱:Cdnjson@163.com提供相关证明,我们将积极配合您!
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。
回复 关闭延时

使用道具 举报

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则