目錄
訂單確認頁面 如下:
(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()
方法,彈出如下彈窗:
- 在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>