Vue項目實戰:訂單確認頁面實現

目錄

訂單確認頁面 如下

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-U33EFpdC-1586238491258)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\1586171626629.png)]

(1)訂單父組件結構封裝

  • 回顧路由文件router.js中關於order的路由:
       {
            path: '/order',
            name: 'order',
            component: Order,
            children: [
                {
                    path: 'list',
                    name: 'order-list',
                    component: OrderList
                },
                {
                    path: 'confirm',
                    name: 'order-confirm',
                    component: OrderConfirm
                },
                {
                    path: 'pay',
                    name: 'order-pay',
                    component: OrderPay
                },
                {
                    path: 'alipay',
                    name: 'alipay',
                    component: AliPay
                }
            ]
        }

上面那樣子定義路由是因爲訂單列表、支付、確認頁面的頁面結構相似。所以把他們封裝在order路由下。

  • order.vue文件如下:
<template>
    <div>
        <order-header></order-header>
        <router-view></router-view>
        <ServiceBar></ServiceBar>
        <nav-footer></nav-footer>
    </div>
</template>
<script>
import OrderHeader from './../components/OrderHeader';
import ServiceBar from './../components/ServiceBar';
import NavFooter from './../components/NavFooter';
export default {
    name: 'order',
    components: {
        OrderHeader,
        NavFooter,
        ServiceBar
    }
}
</script>

訂單確定、列表、支付頁面的<order-header></order-header>組件中的文字內容不一樣。

我們可以通過在各個頁面中去單獨引入<order-header></order-header>同時綁定不同的文字內容,添加展示內容。或者像上面order.vue文件一樣,在order.vue中引入,然後通過路由判斷當前頁面屬於哪個,並展示不同內容。

下面是第二種方式:

        <order-header v-bind:title="title">
            <template v-slot:tip>
                <span>{{tip}}</span>
            </template>
        </order-header>
<script>
export default {
    data() {
        return {
            title: '',
            tip: ''
        }
    },
    mounted() {
       let path = this.$route.path;
       if (path == '/order/confirm') {
           this.title = '訂單確認';
           this.tip = '請認真填寫收貨地址';
       }  else if (path == '/order/list') {
           this.title = '訂單列表';
           this.tip = '請謹防釣魚鏈接或咋騙電話,瞭解更多';           
       } else if (path == '/order/pay') {
           this.title = '訂單支付';
           this.tip = '請謹防釣魚鏈接或咋騙電話,瞭解更多';           
       }
    }
}
</script>

(2)地址和商品數據加載

在orderConfirm.vue中添加:

<!--省略樣式和結構代碼-->
<script>
export default{
  data(){
    return {
      list: [], //收貨地址列表
      cartList: [], //購物車中需要結算的商品列表
      cartTotalPrice: 0,  //商品總金額
      count: 0, //商品結算數量  
    }
  },
  mounted() {
      this.getAddressList();
      this.getCartList();
  },
  methods:{
    getAddressList() { //獲取收貨地址列表
        this.axios.get('/shippings').then((res) => {
            this.list = res.list;
        })
    },
    getCartList() {
        this.axios.get('/carts').then((res) => {
            let list = res.cartProductVoList; //獲取購物車中所有商品數據
            this.cartTotalPrice = res.cartTotalPrice;
            this.cartList = list.filter(item => item.productSelected);
            list.cartList.map((item) => {
                this.count += item.quantity;
            })
        })
    }
  }
}
</script>

(3)地址刪除功能實現

在orderConfirm.vue中添加:

<script>
import Modal from './../components/Modal'   
export default{
  data(){
    return {
      checkedItem: {}, // 選中的商品對象
      userAction: '', // 用戶行爲, 0是新增,1是編輯,2是刪除
      showDelModal: false, //是否彈窗   
    }
  },
  components:{
    Modal
  },
  methods:{
    delAddress(item) { //點擊刪除圖標會出現彈窗
        this.checkedItem = item;
        this.userAction = 2;
        this.showDelModal = true;
    },
    submitAddress() { //在彈窗中點擊“確認”時會觸發該方法
        //地址刪除、編輯、新增功能
        let {checkedItem, userAction} = this;
        let method, url;
        if (userAction == 0) {
            method = 'post', url = '/shippings';
        } else if (userAction == 1) {
            method = 'put', url = `/shippings/${checkedItem.id}`;
        } else {
            method = 'delete', url = `/shippings/${checkedItem.id}`
        }
        this.axios[method](url).then(() => {
            this.closeModal();
            this.getAddressList();
            this.$message.success('操作成功');
        });
    }, 
    closeModal(){
      this.checkedItem = {};
      this.userAction = '';
      this.showDelModal = false;
    }
  }
}
</script>

(4)新增地址交互實現

  • 在點擊 “添加新地址” 後觸發openAddressModal()方法,彈出如下彈窗:
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KNwBQbEm-1586238491273)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\1586181472047.png)]
  • 在orderConfirm.vue中添加:
   <modal
      title="新增確認"
      btnType="1"
      :showModal="showEditModal"
      @cancel="showEditModal=false"
      @submit="submitAddress"
    >
      <template v-slot:body>
        <div class="edit-wrap">
          <div class="item">
            <input type="text" class="input" placeholder="姓名" v-model="checkedItem.receiverName">
            <input type="text" class="input" placeholder="手機號" v-model="checkedItem.receiverMobile">
          </div>
          <div class="item">
            <select name="province" v-model="checkedItem.receiverProvince">
              <option value="北京">北京</option>
              <option value="天津">天津</option>
            </select>
            <select name="city" v-model="checkedItem.receiverCity">
              <option value="北京">北京</option>
            </select>
            <select name="district" v-model="checkedItem.receiverDistrict"> 
              <option value="北京">昌平區</option>
              <option value="天津">海淀區</option>
            </select>
          </div>
          <div class="item">
            <textarea name="street" v-model="checkedItem.recevierAddress"></textarea>
          </div>
          <div class="item">
            <input type="text" class="input" placeholder="郵編" v-model="checkedItem.receiverZip">
          </div>
        </div>
      </template>
    </modal>

<script>
export default{
  data(){
    return {
      showDelModal:false, //是否彈窗      
    }
  },
  methods:{
    submitAddress() {
        let {checkedItem, userAction} = this;
        let method, url,params = {};
        if (userAction == 0) {
            method = 'post', url = '/shippings';
        } else if (userAction == 1) {
            method = 'put', url = `/shippings/${checkedItem.id}`;
        } else {
            method = 'delete', url = `/shippings/${checkedItem.id}`
        }
        if (userAction == 0 || userAction == 1) {
          let { receiverName, receiverMobile, receiverProvince, receiverCity, receiverDistrict, receiverAddress, receiverZip } = checkedItem;
          let errMsg;
          if(!receiverName) {
            errMsg="請輸入收貨人名稱";
          } else if (!receiverMobile || !/\d{11}/.test(receiverMobile)) {
            errMsg="請輸入正確格式的手機號";
          } else if(!receiverProvince) {
             errMsg="請選擇省份";
          } else if (!receiverCity) {
            errMsg="請選擇對應的城市";
          } else if (!receiverDistrict || !receiverAddress) {
            errMsg="請輸入收貨地址";
          } else if (/\d{6}/.test(receiverZip)) {
            errMsg="請輸入郵編";
          }
          if (errMsg) {
            this.$message.error(errMsg)
            return;
          }
          params = {
            receiverName,
            receiverMobile,
            receiverProvince,
            receiverCity,
            receiverDistrict,
            receiverAddress,
            receiverZip
          }
        }
        this.axios[method](url, params).then(() => {
            this.closeModal();
            this.getAddressList();
            this.$message.success('操作成功');
        });
    }, 
    // 打開新增地址彈框
    openAddressModal(){
      this.showEditModal = true;
      this.checkedItem = {};
      this.showEditModal = true;
    },
      // 關閉彈框
    closeModal(){
      this.showEditModal = false;
      this.checkedItem = {};
      this.userAction = '';
      this.showDelModal = false;
    }     
  }
}
</script>

(5)地址編輯和訂單提交

  • 地址編輯

    點擊編輯圖標會出現彈窗,在彈窗表單中編輯新地址後,點擊確認後彈出消失,頁面中出現新地址項。

    當點擊地址項時,地址項的邊框會變色。

<div class="addr-info" :class="{'checked': index == checkIndex}" @click="checkIndex=index" v-for="(item, index) in list" :key="index">
<script>
export default{
  data(){
    return {
      checkIndex:0, //當前收貨地址中索引  
    }
  },
  methods:{
    ditAddressModal(item){
      this.userAction = 1;
      this.checkedItem = {};
      this.showEditModal = true;
    }      
  }
}
</script>
  • 訂單提交
<a href="javascript:;" class="fr">
   <svg class="icon icon-edit">
       <use xlink:href="#icon-edit" @click="editAddressModal(item)" />
   </svg>
</a>
<script>
export default{
  methods:{
// 訂單提交
    orderSubmit() {
      let item = this.list[this.checkIndex];
      if (!item) {
        this.$message.error("請選擇一個收貨地址");
        return;
      }
      this.axios
        .post("/orders", {
          shippingId: item.id
        })
        .then((res) => {
          this.$router.push({
            path: "/order/pay",
            query: {
              orderNo: res.orderNo
            }
          });
        });
    }     
  }
}
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章