vue实现购物车页面功能交互,单选、全选、左滑删除

vue实现购物车页面功能交互,单选、全选、左滑删除

首先说单选全选的实现:
单选:其实就是给每一个点击的item通过点击事件添加选中属性

choose(item){
    if(item.isSelect){
        this.$set(item,'isSelect',false)
    }else{
        this.$set(item,'isSelect',true)
    }
},

全选:核心其实就是遍历,如果所有项都是选中的也就是isSelect为true,那就是全选喽,如果有一个isSelect为false,那就非全选呗。可以通过vue的计算属性(computed)来进行判断:

isSelectAll(){//全选
 return this.goodsList.every(function (val) { return val.isSelect})&&!(this.goodsList.length==0)
},

通过every方法来遍历商品列表,查看每一项的isSelect是否为true;every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
every() 方法使用指定函数检测数组中的所有元素:
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
如果所有元素都满足条件,则返回 true。非常好用!!!
交互已经实现了,但是往往购物车这里是会根据你的勾选进行数量和价格的计算:
也是在computed中进行

getTotal(){
	var chooseData= this.goods.filter(function (val) { return val.isSelect});//返回所有isSelect为true的项,组成数组   
   var money=0;
   var num = 0;
	chooseData.forEach(item=>{//遍历数组,进行累加计算
       money+=Number(item.num)*Number(item.price)
       num+=Number(item.num)
   	})
	return {money:money,num:num,typeNum:chooseData.length}
},

在这里插入图片描述

仅针对单层结构的商品购物车,不针对带有店铺分类的购物车。当然原理是一样的,无非就是多了一层。

页面上的结构对应:

<li class="list-item" data-type="0" v-for="(item,i) in goodsList">
 <div class="list-box" @touchstart.capture="touchStart" @touchend.capture="touchEnd">
     <i class="iconfont uncheck" v-show="!item.isSelect" @click="choose(item)">&#xe8d7;</i>
     <i class="iconfont t_color" v-show="item.isSelect" @click="choose(item)">&#xe8d8;</i>
     <div class="list-content">
         <img :src="item.goods_img+'?x-oss-process=image/resize,m_fill,h_160,w_160'" alt="" @click="goDetail(item.goods_id)">
         <div class="goods-msg">
             <p class="title">{{item.goods_name}}</p>
             <p class="size">规格:{{item.specs_name}}</p>
             <div class="money-num">
                 <div class="left">
                     <p class="pintuan" v-if="item.active_type==1">拼团</p>
                     <p class="seckill" v-if="item.active_type==2">秒杀</p>
                     <span class="price">¥{{item.price}}</span>
                 </div>
                 <div class="right">
                     <span class="stock" v-if="Number(item.stock)<2">仅剩{{item.stock}}件</span>
                     <div class="num">
                         <span class="dnum" @click="numDecrease(item,i)">-</span>
                         <input class="nums" type="number" @input ="setNum(item,i)" v-model.trim="item.num" @blur="numBlur(item)">
                         <span class="anum" @click="numAdd(item,i)">+</span>
                     </div>
                 </div>
             </div>
         </div>
     </div>
 </div>
 <div class="delete" @click="deleteShopCar([item.id])" :data-index="i">删除</div>
</li>

样式:

.list-item{
 position: relative;
 height:104px;
 -webkit-transition: all 0.2s;
 transition: all 0.2s;
 &[data-type="0"]{
     transform: translate3d(0,0,0);
 }
 &[data-type="1"]{
     transform: translate3d(-1.2rem,0,0);
 }
 &::after{
     content: " ";
     position: absolute;
     left: 0.2rem;
     bottom: 0;
     right: 0;
     height: 1px;
     color: #ccc;
     -webkit-transform-origin: 0 100%;
     transform-origin: 0 100%;
     -webkit-transform: scaleY(0.5);
     transform: scaleY(0.5);
     z-index: 2;
 }
 .list-box{
     padding:12px 16px 14px 12px;
     background: #fff;
     display: flex;
     align-items: center;
     position: absolute;
     top: 0;
     right: 0;
     bottom: 0;
     left: 0;
     i{
         font-size:20px;
         margin-right:12px;
     }
     .uncheck{
         color:#CFCCCD; 
     }
     .list-img{
         display: block;
         width: 0.4rem;
         height: 0.4rem;
     }
     .list-content{
         position: relative;
         flex: 1;
         display: flex;
         justify-content: space-between;
         img{
             width:1.6rem;
             height:1.6rem;
             border-radius:0.12rem;
             vertical-align:middle;
             margin-right:12px;
         }
         .goods-msg{
             flex:1;
             .title{
                 font-size: 0.3rem;
                 color:#333333;
                 overflow: hidden;
                 margin-bottom:4px;
                 white-space:nowrap;
                 width:210px;
                 text-overflow:ellipsis;
             }
             .size{
                 font-size: 0.26rem;
                 color:#999999;
                 overflow: hidden;
                 white-space:nowrap;
                 text-overflow:ellipsis;
             }
             .money-num{
                 display: flex;
                 justify-content: space-between;
                 align-items: center;
                 height:0.6rem;
                 position: relative;
                 top:0.2rem;
                 .left{
                     display: flex;
                     align-items: center;
                     .seckill{
                         width:30px;
                         height:16px;
                         background:rgba(245,63,60,0.1);
                         border-radius:2px;
                         border:1px solid rgba(245,63,60,1); 
                         display:flex;
                         align-items:center;
                         justify-content: center;
                         font-size:11px;
                         color:#F53F3C;
                         margin-right:8px;
                     }
                     .pintuan{
                         width:30px;
                         height:16px;
                         border-radius:2px;
                         border:1px solid #FFD446; 
                         display:flex;
                         align-items:center;
                         justify-content: center;
                         font-size:11px;
                         color:#FFD446;
                         margin-right:8px;
                     }
                     .price{
                         color: #F04F4C;
                         font-size:0.3rem;
                         font-weight:600;
                     }
                 }
                 .right{
                     display: flex; 
                     align-items: center;
                     .stock{
                         font-size:13px;
                         font-weight:400;
                         color:rgba(245,63,60,1);
                         margin-right:8px;
                     }
                     .num{
                         display: flex; 
                         align-items: center;
                         .dnum{
                             width: 22px;
                             height:22px;
                             text-align: center;
                             line-height: 0.35rem;
                             border-radius: 50%;
                             border:1px solid #EEEEEE;
                             font-size: 0.34rem;
                             color:#333333;
                         }
                         .nums{
                             width:36px;
                             height:22px;
                             text-align: center;
                             background:rgba(244,244,244,1);
                             font-size:0.3rem;
                             color:#333333;
                             border: none;
                             border-radius:2px;
                             outline: none;
                         }
                         .anum{
                             width:22px;
                             height:22px;
                             text-align: center;
                             line-height: 0.35rem;
                             border-radius: 50%;
                             border:1px solid #EEEEEE;
                             font-size: 0.34rem;
                             color:#333333;
                         }
                     }
                 }
             }
         }
         
     }
 }
 .delete{
     width: 1.2rem;
     height: 2rem;
     background: #F04F4C;
     font-size: 0.3rem;
     color: #ffffff;
     text-align: center;
     line-height: 2rem;
     position: absolute;
     top:0;
     right: -1.2rem;
 }
 
}

然后轮到滑动删除:
原理就是通过touch事件来监听滑动事件,然后根据坐标判断左滑还是右滑,进而让当前item进行对应平移,将隐藏的删除显示或者隐藏,实现滑动点击删除。

//滑动开始
touchStart(e){
    // 记录初始位置
    this.startX = e.touches[0].clientX;
},
//滑动结束
touchEnd(e){
            // 当前滑动的父级元素
    let parentElement = e.currentTarget.parentElement;
    // 记录结束位置
    this.endX = e.changedTouches[0].clientX;
            // 左滑
    if( parentElement.dataset.type == 0 && this.startX - this.endX > 40 ){
        this.restSlide();
        parentElement.dataset.type = 1;
    }
            // 右滑
    if( parentElement.dataset.type == 1 && this.startX - this.endX < -30 ){
        this.restSlide();
        parentElement.dataset.type = 0;
    }
    this.startX = 0;
    this.endX = 0;
},
//判断当前是否有滑块处于滑动状态
checkSlide(){
    let listItems = document.querySelectorAll('.list-item');
    for( let i = 0 ; i < listItems.length ; i++){
        if( listItems[i].dataset.type == 1 ) {
            return true;
        }
    }
    return false;
},
//复位滑动状态
restSlide(){
    let listItems = document.querySelectorAll('.list-item');
    // 复位
    for( let i = 0 ; i < listItems.length ; i++){
        listItems[i].dataset.type = 0;
    }
},
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值