Vue nodejs商城-地址模块

一、地址列表渲染

购物车列表页中点击checkout结账,若已勾选的商品为0,则不可以点击。

src/views/Cart.vue

  1. <a class="btn btn--red" v-bind:class="{'btn--dis':checkedCount==0}" @click="checkOut">Checkout</a>
  2.  
  3. methods:{
  4.     checkOut(){ // 结账
  5.         if(this.checkedCount>0){ // 已勾选的商品种数>0时才可以跳转到地址列表页
  6.             this.$router.push( // 跳转到地址列表页
  7.                 {path:"/address"}
  8.             );
  9.         }
  10.     }
  11. }

 

未勾选时状态:

勾选时状态:

新建地址列表组件src/views/Address.vue,添加路由配置src/router/index.js

  1. import Address from '@/views/Address' // 地址列表
  2. export default new Router({
  3.   routes: [
  4.     {
  5.       path: '/address', // 地址列表路由
  6.       name: 'Address',
  7.       component: Address
  8.     }
  9.   ]
  10. })

 

渲染地址列表

地址列表后端接口:server/routes/users.js

  1. // 查询用户地址接口
  2. router.get("/addressList",function(req,res,next){
  3.     var userId = req.cookies.userId;
  4.     User.findOne({userId:userId},function(err,doc){
  5.         if(err){
  6.             res.json({
  7.                 status:'1',
  8.                 msg:err.message,
  9.                 result:''
  10.             })
  11.         }else{
  12.             res.json({
  13.                 status:'0',
  14.                 msg:'',
  15.                 result:doc.addressList
  16.             })
  17.         }
  18.     })
  19. })

 

地址列表前端调用:src/views/Address.vue

  1. <li v-for="item in addressList">
  2.     <dl>
  3.         <dt>{{item.userName}}</dt>
  4.         <dd class="address">{{item.streetName}}</dd>
  5.         <dd class="tel">{{item.tel}}</dd>
  6.     </dl>
  7.     <div class="addr-opration addr-del">
  8.         <a href="javascript:;" class="addr-del-btn">
  9.             <svg class="icon icon-del"><use xlink:href="#icon-del"></use></svg>
  10.         </a>
  11.     </div>
  12.     <div class="addr-opration addr-set-default">
  13.         <a href="javascript:;" class="addr-set-default-btn"><i>Set default</i></a>
  14.     </div>
  15.     <div class="addr-opration addr-default">Default address</div>
  16. </li>
  17. export default {
  18.     data(){
  19.         return {
  20.           addressList:[] // 地址列表
  21.         }
  22.     },
  23.     mounted(){
  24.       this.init();
  25.     },
  26.     methods:{
  27.       init(){
  28.         axios.get('/users/addressList').then((response) => {
  29.           let res = response.data;
  30.           this.addressList = res.result;
  31.         })
  32.       }
  33.     }
  34. }

二、地址列表切换和展开

限制地址显示3

用计算属性computed对地址列表数据进行处理

  1. <li v-for="item in addressListFilter">
  2.  
  3. export default {
  4.     data(){
  5.         return {
  6.           addressList:[], // 地址列表
  7.           limit:3 // 限制默认显示3个地址
  8.         }
  9.     },
  10.     computed:{
  11.       addressListFilter(){
  12.         return this.addressList.slice(0,this.limit);
  13.       }
  14.     }
  15. }

 

地址展开与收起

展开与收起控制的是显示地址的个数limit,同时图标发生变化

  1. <a class="addr-more-btn up-down-btn" href="javascript:;" @click="expand" v-bind:class="{'open':limit>3}">
  2.   more
  3.   <i class="i-up-down">
  4.     <i class="i-up-down-l"></i>
  5.     <i class="i-up-down-r"></i>
  6.   </i>
  7. </a>
  8. export default{
  9.     expand(){ // 点击more更多
  10.         if(this.limit ==3){
  11.           this.limit = this.addressList.length;
  12.         }else{
  13.           this.limit =3;
  14.         }
  15.     }
  16. }

 


地址选中切换

  1. 定义一个地址选中的索引数据checkIndex,当checkIndex等于所在li索引时,类名check加上;点击地址的时候将点击的li索引赋值给checkIndex
    <li v-for="(item,index) in addressListFilter" v-bind:class="{'check':checkIndex == index}" @click="checkIndex=index"></li>
  2.  
  3. export default {
  4.     data(){
  5.         return {
  6.           checkIndex:0 // 选中的地址索引
  7.         }
  8.     }
  9. }

 

三、设置默认地址

server/models/users.js 先补充地址列表addressList的数据模型

  1. "addressList":[
  2.     {
  3.         "addressId": String,
  4.         "userName": String,
  5.         "streetName": String,
  6.         "postCode": Number,
  7.         "tel": Number,
  8.         "isDefault": Boolean
  9.     }
  10. ]

 

server/routes/users.js设置默认地址接口,前端传要设置的地址的addressId给后端,后端设置isDefault的值

  1. //设置默认地址接口
  2. router.post("/setDefault", function (req,res,next) {
  3.   var userId = req.cookies.userId,
  4.       addressId = req.body.addressId;
  5.   if(!addressId){
  6.     res.json({
  7.       status:'1003',
  8.       msg:'addressId is null',
  9.       result:''
  10.     });
  11.   }else{
  12.     User.findOne({userId:userId}, function (err,doc) {
  13.       if(err){
  14.         res.json({
  15.           status:'1',
  16.           msg:err.message,
  17.           result:''
  18.         });
  19.       }else{
  20.         var addressList = doc.addressList;
  21.         addressList.forEach((item)=>{
  22.           if(item.addressId ==addressId){
  23.              item.isDefault = true;
  24.           }else{
  25.             item.isDefault = false;
  26.           }
  27.         });
  28.  
  29.         doc.save(function (err1,doc1) {
  30.           if(err){
  31.             res.json({
  32.               status:'1',
  33.               msg:err.message,
  34.               result:''
  35.             });
  36.           }else{
  37.               res.json({
  38.                 status:'0',
  39.                 msg:'',
  40.                 result:''
  41.               });
  42.           }
  43.         })
  44.       }
  45.     });
  46.   }
  47. });

 

src/views/Address.vue前端

  1. <div class="addr-opration addr-set-default">
  2.     <a href="javascript:;" class="addr-set-default-btn" v-if="!item.isDefault" @click="setDefault(item.addressId)"><i>Set default</i></a>
  3. </div>
  4. <div class="addr-opration addr-default" v-if="item.isDefault">Default address</div>
  5.  
  6. methods:{
  7.     setDefault(addressId){ // 设置默认地址
  8.         axios.post('/users/setDefault',{
  9.           addressId:addressId
  10.         }).then((response)=>{
  11.           let res = response.data;
  12.           if(res.status=='0'){
  13.             console.log("set default");
  14.             this.init(); // 重新渲染地址列表
  15.           }
  16.         })
  17.       }
  18. }

 

四、地址删除功能

server/routes/users.js后端删除地址接口

  1. //删除地址接口
  2. router.post("/delAddress", function (req,res,next) {
  3.   var userId = req.cookies.userId,addressId = req.body.addressId;
  4.   User.update({
  5.     userId:userId
  6.   },{
  7.     $pull:{
  8.       'addressList':{
  9.         'addressId':addressId
  10.       }
  11.     }
  12.   }, function (err,doc) {
  13.       if(err){
  14.         res.json({
  15.             status:'1',
  16.             msg:err.message,
  17.             result:''
  18.         });
  19.       }else{
  20.         res.json({
  21.           status:'0',
  22.           msg:'',
  23.           result:''
  24.         });
  25.       }
  26.   });
  27. });

 

点击删除图标会出现一个模态框,点击模态框的确定按钮,发送要删除的地址的id给后端,请求删除,然后重新渲染地址列表,删除的数据不会再出现。

src/views/Address.vue

  1. <!--删除图标-->
  2. <a href="javascript:;" class="addr-del-btn" @click="delAddressConfirm(item.addressId)">
  3.     <svg class="icon icon-del"><use xlink:href="#icon-del"></use></svg>
  4. </a>
  5.  
  6. <!-- 模态框 -->
  7. <modal :mdShow="isMdShow" @close="closeModal">
  8.     <p slot="message">
  9.         您是否确认要删除此地址?
  10.     </p>
  11.     <div slot="btnGroup">
  12.         <a class="btn btn--m" href="javascript:;" @click="delAddress">确认</a>
  13.         <a class="btn btn--m btn--red" href="javascript:;" @click="isMdShow=false">取消</a>
  14.     </div>
  15. </modal>
  16. export default {
  17.     data(){
  18.         return {
  19.           isMdShow:false, // 模态框的显示设置
  20.           addressId:'' // 地址id的存储,用于请求传参
  21.         }
  22.     }
  23.     methods:{
  24.       closeModal(){ // 关闭模态窗
  25.         this.isMdShow = false;
  26.       },
  27.       delAddressConfirm(addressId){ // 点击删除图标,模态框出现
  28.         this.isMdShow = true;
  29.         this.addressId = addressId; // 地址id赋值
  30.       },
  31.       delAddress(){
  32.         axios.post("/users/delAddress",{
  33.           addressId:this.addressId // 传参
  34.         }).then((response)=>{
  35.             let res = response.data;
  36.             if(res.status=="0"){
  37.               console.log("del suc");
  38.               this.isMdShow = false; // 告诉模态框组件,设置模态框消失
  39.               this.init(); // 重新渲染地址
  40.             }
  41.         })
  42.       }
  43.     }
  44. }

 



点击Next跳转到订单确认页面

跳转要传选择的地址id传过去

src/views/Address.vue

  1. <!--选择地址的时候将地址id赋值给selectedAddrId-->
  2. <li v-for="(item,index) in addressListFilter" v-bind:class="{'check':checkIndex == index}" @click="checkIndex=index;selectedAddrId=item.addressId"></li>
  3.  
  4. <!--动态跳转,传参传入地址id-->
  5. <router-link class="btn btn--m btn--red" v-bind:to="{path:'/orderConfirm',query:{'addressId':selectedAddrId}}">Next</router-link>
  6.  
  7. export default {
  8.     data(){
  9.         return {
  10.           selectedAddrId:'' // 选中的地址id存储,用于点击Next跳转到订单确认页面传参
  11.         }
  12.     }
  13. }

 

点击Next跳转,跳转到订单确认页面,url带了选择的地址id参数

posted on 2018-06-28 04:35  gisery  阅读(1067)  评论(1编辑  收藏  举报