目录
订单确认页面 如下:
(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)地址编辑和订单提交
-
地址编辑
点击编辑图标会出现弹窗,在弹窗表单中编辑新地址后,点击确认后弹出消失,页面中出现新地址项。
当点击地址项时,地址项的边框会变色。
扫描二维码关注公众号,回复: 10567592 查看本文章
<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>