vue3微信公众号商城项目实战系列(9)购物车页面

本篇显示购物车中的商品,购物车表结构如下,我们通过接口服务抓取登录用户的购物车信息。

表名

字段

功能
shoppingcart

cart_id (int) 购物车编号

user_id (int) 用户编号

goods_id (int) 商品编号

goods_name (varchar) 商品名称

photo (varchar) 商品图片

price (decimal) 价格

qty (int) 数量

购物车表

页面效果如下:

先在 app.js 中增加查询购物车商品、创建订单的接口方法,如下:

 1 export function cartQuery(data) {
 2   return request({
 3     url: '/cart/query', 
 4     method: 'post',
 5     data: data
 6   })
 7 }
 8  
 9 export function orderBuild(data) {
10   return request({
11     url: '/order/build', 
12     method: 'post',
13     data: data
14   })
15 }

下面来看 cart.js 的代码

布局代码块:

 1 <template>
 2     <div class="cart">
 3         <div class="cart-list">
 4             <div class="cart-item" v-for="(item,index) in cartList">
 5                 <div><img class="cart-img" :src="item.photo" /></div>
 6                 <div class="cart-info">
 7                     <div><span class="cart-name">{{ item.goodsName }}</span></div>
 8                     <span class="cart-price">¥{{ item.price }}元</span>
 9                     <div class="cart-qty">
10                         <input class="txt_qty" type="number" v-model="item.qty" @blur="onModifyCart(item.goodsId, index)" />
11                         <span class="cart-price">{{ item.price * item.qty }} 元</span>
12                     </div>  
13                 </div>
14             </div> 
15         </div>  
16         <div class="cart-total">
17             <span class="cart-price">总价 : {{ totalAmt }}元</span>
18             <input class="btn_order" type="button" value="下单" @click="onOrder" />
19         </div>
20 
21         <TabBar name="cart" />
22     </div>    
23 </template>

使用 v-for 遍历数组 cartList ,onModifyCart 是输入框的失去焦点事件,用户可以修改商品数量。

 

脚本代码块:

 1 <script setup>
 2 import { onMounted, reactive, toRefs, computed } from 'vue';
 3 import {cartQuery, cartAdd} from '@/http/api';
 4 import TabBar from '@/components/TabBar.vue';
 5 import { useCartStore } from '@/stores/cart.js'
 6 const cartStore = useCartStore();
 7 
 8 const data = reactive({cartList:[] })
 9 let {cartList} = toRefs(data);
10   
11 const totalAmt = computed(() => {
12     let ttl=0;
13     data.cartList.forEach(function(item, index) {ttl+=item.price * item.qty;});
14     return ttl;
15 })
16   
17 onMounted(() => {
18     let formData={}; 
19     cartQuery(formData).then(res=>{
20         data.cartList=res; 
21     });
22 })
23 
24 function onModifyCart(goodsId, index){ 
25     let newQty=data.cartList[index].qty
26     let formData = {goodsId:goodsId,qty:newQty}; 
27     //console.log(JSON.stringify(formData)); 
28     cartAdd(formData).then(res=>{ 
29         cartStore.reset(res.qty);
30     })
31 }

 

function onOrder(){ 
    let cartinfo = '';
    data.cartList.forEach((item, index)=>{
        cartinfo+=','+item.goodsId+':'+item.qty; 
    });
    cartinfo=cartinfo.substring(1);
    let formData={cartinfo:cartinfo}; 
    orderBuild(formData).then(res=>{  
        router.push({name:'order',query:{oid:res.orderId}}); 
    })  
}
</script>

 

和 Home.vue 大部分是相同的,不同的见红色部分。

1 . 使用了 vue3 的 computed() 函数,它能将 totalAmt 这个变量变成一个计算属性,其作用就是汇总购物车中商品总额

,然后在总价那里显示出来。

2. cartAdd() 这个后端接口会返回一个 qty ,它表示当前用户购物车中商品的总数量,每次更新购物车商品数量

,后端接口都需要重新计算一下总数量,前端可以用这个值更新 cart.count ,确保商品数量同步。

3. let newQty=data.cartList[index].qty 这里可以取到用户输入的值,因为 cartList 是一个响应式对象

,用户输入的值 vue3 框架会自动帮我们设置到相应索引的qty属性中去。

4. reset() 方法 是 cart状态 中新增的方法,用于重置数量,修改后的代码如下(见红色部分):

 1 import { ref } from 'vue';
 2 import {defineStore} from 'pinia';
 3 
 4 export const useCartStore = defineStore('cart', () => {
 5     const count = ref(0);
 6     function increment(qty) {
 7       count.value += qty;
 8     }
 9     function reduction(qty){
10         if(count.value>1){
11             count.value -= qty;
12         } 
13     }
14     function reset(qty){
15       count.value=qty;
16     }
17     return { count, increment, reduction, reset }
18   },
19   {persist:true}
20 )

其他两个方法也做了改进,可以根据参数来做增减。

5.  onOrder() 方法遍历购物车中的商品信息,调用 orderBuild( ) 来生成订单,该方法的返回值是新生成订单的编号

,调用 router.push({name:'order',query:{oid:res.orderId}}); 方法时会自动生成查询字符串,形如 " ?oid=237832 "

,实际项目中每个商品前有 checkbox 可以让用户勾选,这里做了简化处理。

 

样式代码块:

 1 <style>
 2 .cart-list{
 3     display: flex;
 4     flex-direction: column;
 5 }
 6 .cart-item{
 7     display: flex;
 8     flex-direction: row;
 9     border:solid 1px #E0E0E0;
10     margin-bottom: 6px;
11     padding: 4px 0;
12 }
13 .cart-img{
14     width: 100px;
15     height: 100px;
16     vertical-align: middle;
17     border: solid 1px #F0F0F0;
18     border-radius: 4px;
19 }
20 .cart-info{
21     width: 100%; 
22     padding-left: 8px;
23     padding-right: 8px;
24 }
25 .cart-name{
26     font-weight: bold;
27 }
28 .cart-price{
29     font-size: 16px;
30     font-weight: bold;
31     color:orangered;
32  } 
33  .cart-qty{ 
34     width: 100%;
35     display: flex;
36     flex-direction: row;
37     justify-content: space-between;
38  }
39  .txt_qty{
40     width: 60px;
41  }
42 
43  .cart-total{ 
44     width: 368px; 
45     height: 30px;
46     line-height: 30px;
47     position: fixed;
48     left: 3px;
49     bottom: 56px;
50     background-color: #e0fffe;
51 
52     display: flex;
53     flex-direction: row;
54     justify-content: space-between;
55  }
56  .btn_order{
57     width: 70px;
58     height: 30px;
59  }
60 </style>

这里根据页面布局要求来设置就可以了。

 

posted @ 2023-04-19 17:03  屏风马  阅读(302)  评论(0编辑  收藏  举报