在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>