VUE2.0 饿了么学习笔记(7)创建shopcart购物车组件的过程

 

创建购物车组件,引入并注册到goods组件中,在模板中添加shopCart购物车的初等样式。

先写结构:分左右两侧,左侧自适应,右侧部分为20元起送状态,固定宽度,使用flex布局

因为后来给shopcart添加了一个同级罩层mask,这样一个template下边就有两个div了,所以在这两个div的外边添加一个父层div

<template>
<!-- shopcart是goods组件的一部分,要将其引入到goods组件中,template下只能有一个div,所以添加一个div做最外层 -->
    <div>  
        <div class="shopcart">   
             <div class="content" @click="toggleList"> <!--  详情界面-->
                <div class="content-left"> </div>
                    
                <div class="content-right" @click.stop.prevent="pay"> </div>

              </div>
         </div>
    </div>
 </template>
     <div class="content-left">
                    <div class="logo-wrapper"> <!-- logo 区块-->
                        <div class="logo" :class="{'highlight': totalCount > 0}">
                            <span class="icon-shopping_cart" :class="{'highlight': totalCount > 0}"></span> <!-- icon.stylus中引入-->
                        </div>
                        <!-- 购物车中有东西时才出现-->
                        <div class="num" v-show="totalCount > 0">{{totalCount}}</div>
                    </div>
                    <div class="price" :class="{'highlight': totalCount > 0}">¥{{totalPrice}}元</div>
                    <div class="desc">另需配送费¥{{deliveryPrice}}元</div>
                </div>

上边是左侧,下边是右侧

 <!-- 点击去结算,结算过后因为事件冒泡的原因(pay按钮是content详情界面的子节点),详情列表会被展开,用stop.prevent阻止事件冒泡-->
                <div class="content-right" @click.stop.prevent="pay">
                    <div class="pay" :class="payClass"> <!-- 在这里做一个状态的判断-->
                        {{payDesc}}
                    </div>
                </div>

css样式:

    .shopcart
        position fixed 
        left 0
        bottom 0
        z-index 50
        width 100%
        height 48px
        .content    
            display flex
            background #141d27
            font-size 0 //解决inline-block的缝隙问题
            .content-left
                flex 1 //自适应
            .content-right
                flex 0 0 105 
                width 105px

接着写content-left部分的css,写样式之前先把购物车样式中用到的配送费和起送价通过父组件goods中传过来,并在购物车组件中用props接收

   <!-- props将seller的属性传进来,数据都存在data.json中 -->
   <shopcart :delivery-price="seller.deliveryPrice" :min-price="seller.minPrice"></shopcart>
        props: {
            deliveryPrice: {
                type: Number,
                default: 0
            },
            minPrice: {
                type: Number,
                default: 0
            }
        }

其中,seller数据也是从goods的父组件App.vue中传递过来的,在App.vue中,商品、评论、商家谁被渲染就把seller的值传递给那个组件

   <!-- 路由出口 -->
        <!-- 路由匹配到的组件将渲染在这里 -->
      <router-view :seller="seller"></router-view>

此时,接着写购物车的content-left部分,左侧部分的logo-wrapper,price和desc都是inliinline-block布局,

            .content-left
                flex 1 //自适应
                .logo-wrapper // 包裹着logo图片和上侧num的一个wrapper,圆形,相对于content有一个高出的部分
                    display inline-block
                    vertical-align top
                    position relative
                    top -10px
                    margin 0 12px
                    padding 6px
                    width 56px
                    height 56px
                    box-sizing border-box // 宽度包括了padding在内
                    border-radius 50%
                    background #141d27 //不设置颜色默认透明不显示 
                    .logo
                        width 100%
                        height 100%
                        border-radius 50%
                        text-align center
                        background #2b343c
                        &.highlight
                            background rgb(0,160,220)
                        .icon-shopping_cart
                            line-height 44px //88/2=44
                            font-size 24px
                            color #80858a
                            &.highlight
                                color #ffffff
                .price
                    display inline-block
                    vertical-align top
                    margin-top 12px
                    line-height 24px
                    box-sizing border-box
                    padding-right 12px
                    border-right 1px solid rgba(255,255,255,.1)
                    font-size 16px
                    font-weight 700px
                    color rgba(255,255,255,.4)
                    &.highlight
                        color #ffffff
                .desc
                    display inline-block
                    vertical-align top
                    margin 12px 0 0 12px
                    line-height 24px
                    font-weight 700
                    font-size 10px
                    color rgba(255,255,255,.4)

右侧,多少元起送部分,够不够起送费部分是要改变颜色的,在之后的部分会写到

            .content-right
                flex 0 0 105 
                width 105px
                .pay
                    height 48px
                    line-height 48px
                    text-align center
                    font-size 12px
                    color rgba(255,255,255,.4)
                    font-weight 700px
                    background #2b333b
                    &.not-enough
                        background #2b333b
                    &.enough
                        background #00b43c
                        color #ffffff

购物车中的数据应该来自goods组件中,商品在goods组件中被选中就将数据传递到购物车组件中,所以我们要在props中委会一个来自goods组件的selectedFoods数组,用来存放在goods组件中被选中的商品,这里先假设了里面的值,包括单价和数量

        props: {
            selectFoods: { //保存一个被选择商品的数组,包括被选择商品的单价和数量
                type: Array,
                default() { // 当type是一个数组时,defalut就是一个函数
                    return [{
                      //  price: 10,
                       // count: 2
                    }];
                }
            }

购物车中totalPrince的计算是依赖于selectFoods,我们使用计算属性计算总价格,并更新html中的值

        computed: {
            totalPrice() { //计算总价格
                let total = 0;
                this.selectFoods.forEach((food) => {
                    total += food.price * food.count;
                });
                return total;
            }
        }
<div class="price" :class="{'highlight': totalCount > 0}">¥{{totalPrice}}元</div>

当有商品选入购物车后,首先购物车颜色变化,右上角出现显示数量的num,totalPrince颜色加深,还差()元起送的值发生变化,当达到起送价格时会变为去结算的状态

首先计算totalCount

        totalCount() { //计算被选中商品的数量
                let count = 0;
                this.selectFoods.forEach((food) => {
                    count += food.count;
                });
                return count;
            }

计算到商品总数之后,回到购物车DOM部分添加数字角标

                    <div class="logo-wrapper"> <!-- logo 区块-->
                        <div class="logo" :class="{'highlight': totalCount > 0}">
                            <span class="icon-shopping_cart" :class="{'highlight': totalCount > 0}"></span> <!-- icon.stylus中引入-->
                        </div>
                        <!-- 购物车中有东西时才出现-->
                        <div class="num" v-show="totalCount > 0">{{totalCount}}</div>
                    </div>

添加num的样式,当total>0时,购物车logo背景色和小车的颜色改变

                     .num
                        position absolute
                        top 0
                        right 0
                        width 24px
                        height 16px //绝对定位要指定宽高才会被撑开
                        line-height 16px // 垂直居中
                        text-align center // 水平居中
                        border-radius 16px
                        font-size 9px
                        font-weight 700px
                        color #ffffff
                        background rgb(240,20,20)
                        box-shadow 0 4px 8px 0 rgba(0,0,0,.4)

当total>0时,购物车totalPrice颜色改变,在css中添加相应的highlight样式

 <div class="price" :class="{'highlight': totalCount > 0}">¥{{totalPrice}}元</div>

右侧结算部分有三种状态,()元起送,还差()元起送,结算,状态的描述依赖于selectFoods的变化,用payDesc来描述,返回一个描述

            payDesc() {
                if (this.totalCount === 0) { //不要忘了加this
                    return `¥${this.minPrice}元起送`; 
                } else if (this.totalPrice < this.minPrice) {
                    let diff = this.minPrice - this.totalPrice;//忘了加this
                    return `还差¥${diff}元起送`;//不要忘了加$
                } else {
                    return '去结算';
                }
            }

反映到模板里,而且达到起送状态时会改变颜色,添加动态的payClass类(返回css类名)

                <div class="content-right" @click.stop.prevent="pay">
                    <div class="pay" :class="payClass"> <!-- 在这里做一个状态的判断-->
                        {{payDesc}}
                    </div>
                </div>
            payClass() {
                if (this.totalPrice < this.minPrice) {
                    return 'not-enough';
                } else {
                    return 'enough';
                }
            }
                    &.not-enough
                        background #2b333b
                    &.enough
                        background #00b43c
                        color #ffffff

接下来我们应该去获取真实的selectFoods的数据,但是我们希望selectFoods数据是通过一个加减号组件来实现

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值