vue专栏Vue移动端

在vue项目中实现左滑删除(仿QQ 微信等)

2019-01-10  本文已影响301人  River_tong

近期公司在做一个积分商城的项目 其中购物车列表页面涉及到了左滑删除这个功能 不妨记录一下 以下附上效果图

购物车.png
实现这个小功能并没有使用任何的框架 所以也不需要大家安装插件 直接copy过去就可以用
废话不多说 附上代码
<div class="wrap-shop-cart">
      <ul class="cart-list">
          <li class="list-item" v-for="(item,index) in list " data-type="0">
              <div class="list-box" @touchstart.capture="touchStart" @touchend.capture="touchEnd" @click="skip">
                  <span class="ischeck" :class="{'active':item.status}" @click="item.status = !item.status"></span>
                  <div class="details">
                      <div class="img">
                          <img :src="item.imgUrl" />
                      </div>
                      <div class="info">
                          <p class="name">{{item.title}}</p>
                          <p class="txt">{{item.desc}}<span class="num">x{{item.num}}</span></p>
                          <p class="integral">{{item.integral}}积分</p>
                          <ul class="count">
                              <li><a href="javascript:void(0)" class="num-jia" @click="calc(item,0,index)">-</a></li>
                              <li><input type="text" class="input-num" id="input-num" v-model="item.num"/></li>
                              <li><a href="javascript:void(0)" class="num-jia" @click="calc(item,1,index)">+</a></li>
                          </ul>
                      </div>
                  </div>
              </div>
              <div class="delete" @click="deleteItem" :data-index="index">删除</div>
          </li>
      </ul>
      <div class="cart-bottom">
          <span class="ischeck"></span>
          <router-link to="/shop/settlement" class="btns">去结算(0)</router-link>
          <div class="info">
              <p class="total">总计:12800积分</p>
              <p class="freight">不含运费</p>
          </div>
      </div>
  </div>
<script type="text/ecmascript-6">
    export default {
        data () {
            return {
                list : [
                    {
                        title : '红色限量版套装礼盒4个装' ,
                        imgUrl : '' ,
                        desc : '礼盒装  4只  红色限量版' ,
                        num : '1',
                        integral:'12800',
                        status:0
                    },
                    {
                        title : '红色限量版套装礼盒4个装' ,
                        imgUrl : '' ,
                        desc : '礼盒装  4只  红色限量版' ,
                        num : '1',
                        integral:'12800',
                        status:0
                    },
                    {
                        title : '红色限量版套装礼盒4个装' ,
                        imgUrl : '' ,
                        desc : '礼盒装  4只  红色限量版' ,
                        num : '1',
                        integral:'12800',
                        status:0
                    },
                    {
                        title : '红色限量版套装礼盒4个装' ,
                        imgUrl : '' ,
                        desc : '礼盒装  4只  红色限量版' ,
                        num : '1',
                        integral:'12800',
                        status:0
                    },
                ],
                startX : 0 ,
                endX : 0 ,
            }
        },
        methods:{
            calc(item, minusOrPlus,index) {
                if (minusOrPlus === 1) {
                    item.num++;
                } else if (minusOrPlus === 0) {
                    item.num--;
                }
            },
            skip(){
                if( this.checkSlide() ){
                    this.restSlide();
                }
            },
            //滑动开始
            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 > 30 ){
                    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;
                }
            },
            //删除
            deleteItem(e){
                // 当前索引
                let index = e.currentTarget.dataset.index;
                // 复位
                this.restSlide();
                // 删除
                this.list.splice(index,1);
            }
        }
    }
</script>
<style lang="less" rel="stylesheet/less">
    .wrap-shop-cart{
        .cart-list{
            .list-item{
                position: relative;
                -webkit-transition: all 0.2s;
                transition: all 0.2s;
                margin-top: .2rem;
                .delete{
                    width: 1rem;
                    height: 2.2rem;
                    line-height: 2.2rem;
                    background: #e01212;
                    font-size: .28rem;
                    color: #fff;
                    text-align: center;
                    position: absolute;
                    top:0;
                    right: -1rem;
                }
            }
            .list-item[data-type="0"]{
                transform: translate3d(0,0,0);
            }
            .list-item[data-type="1"]{
                transform: translate3d(-1rem,0,0);
            }
            .list-box{
                padding: 0.3rem;
                background: #fff;
                display: flex;
                .details{
                    flex: 1;
                    display: inline-flex;
                    vertical-align: top;
                    .img{
                        width: 1.6rem;
                        height: 1.6rem;
                        display: inline-block;
                        img{
                            width: 100%;
                            height: 100%;
                        }
                    }
                    .info{
                        flex: 1;
                        display: inline-block;
                        padding-left: .2rem;
                        vertical-align: top;
                        .name{
                            font-size: .28rem;
                            color: #333333;
                        }
                        .txt{
                            font-size: .24rem;
                            color: #999999;
                            padding-top: .1rem;
                            .num{
                                float: right;
                            }
                        }
                        .integral{
                            font-size: .24rem;
                            color: #e01212;
                            padding-top: .3rem;
                            display: inline-block;
                        }
                        .count{
                            overflow: hidden;
                            font-size: 0;
                            line-height: 0;
                            vertical-align:middle;
                            display: inline-block;
                            float: right;
                            padding-top: .3rem;
                            li{
                                display: inline-block;
                                vertical-align: top;
                                a,input{
                                    display: inline-block;
                                    width: 20px;
                                    height: 20px;
                                    line-height: 20px;
                                    text-align: center;
                                    font-size: 12px;
                                    color: #999999;
                                    cursor: pointer;
                                    border: 1px solid #f8f8f8;
                                }
                                input{
                                    width: 30px;
                                    border-right: 0;
                                    border-left: 0;
                                }
                            }
                        }
                    }
                }
            }
        }
        .cart-bottom{
            height: .88rem;
            position: fixed;
            bottom: 0;
            width: 100%;
            background: #fff;
            padding-left: .3rem;
            box-sizing: border-box;
            .ischeck{
                margin-top: .28rem !important;
                position: relative;
                &:after{
                    content: '全选';
                    position: absolute;
                    width: 2em;
                    right: -3em;
                }
            }
            .btns{
                display: inline-block;
                width: 2rem;
                height: .88rem;
                line-height: .88rem;
                color: #fff;
                text-align: center;
                float: right;
                background: #e01212;
                font-size: .28rem;
            }
            .info{
                padding: .1rem .3rem .1rem 0;
                float: right;
                color: #999999;
                text-align: right;
                .total{
                    font-size: .28rem;
                }
                .freight{
                    font-size: .2rem;
                }
            }
        }
        .ischeck{
            width: .3rem;
            height: .3rem;
            border: 1px solid #ccc;
            display: inline-block;
            border-radius: 100%;
            margin-right: .3rem;
            margin-top: .6rem;
            &.active{
                background: url("../../assets/images/shop/true_icon.png") no-repeat center center;
                background-size: 100% 100%;
                border: 1px solid #ca3434;
            }
        }
    }
</style>
最后感谢大家的支持 一起加油
喜欢的可以关注以下
后期更新更多有关在vue中遇到的问题以及解决方案 ❤️
上一篇下一篇

猜你喜欢

热点阅读