滑动单元格组件原理是主题部分把按钮进行遮挡,按钮通过绝对定位,定位在最右边,通过监听触摸事件(touch),判断滑动的方向和计算滑动的距离以此来判定显示和隐藏按钮。显示和隐藏按钮是通过对主体部分进行css 的transform属性对主体元素进行移动,以达到显示和隐藏按钮的效果。今天介绍APICloud AVM框架封装滑动单元格组件的实例。
组件文件
easy-swipe-cell.stml
<template>
<view class="easy-swipe-cell_container" data-id={itemId} @touchstart="start" @touchmove="move" @touchend="end">
<view class="easy-swipe-cell_content" :style="itemId == touchIdNow?handleSwipe:'transform:translateX(0px)'">
<text>{itemContent}</text>
</view>
<view class="easy-swipe-cell_btn" id="btn">
<view class="easy-swipe-cell_btn-item" style="background-color: #ee0a24;" data-id={itemId} data-type='delete' @click="clickItem">
<text class="easy-swipe-cell_btn-item-label">删除</text>
</view>
<view class="easy-swipe-cell_btn-item" style="background-color: #07c160;" data-id={itemId} data-type='read' @click="clickItem">
<text class="easy-swipe-cell_btn-item-label">已读</text>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'easy-swipe-cell',
props:{
itemId:String,
itemContent:String,
touchIdNow:String
},
data() {
return{
startX:0, //触摸位置
endX:0, //结束位置
moveX: 0, //滑动时的位置
disX: 0, //移动距离
handleSwipe: '',//滑动时的效果,动态绑定
touchId:''
}
},
mounted (){
},
methods: {
start(e){
// console.log(JSON.stringify(e.detail) '开始');
this.data.startX = e.detail.x;
this.data.touchId = e.currentTarget.dataset.id;
this.fire('touch',this.data.touchId);
},
move(e){
// console.log(JSON.stringify(e.detail) '移动');
let wd=document.getElementById('btn').offsetWidth;
this.data.moveX = e.detail.x;
this.data.disX = this.data.startX - this.data.moveX;
console.log(this.data.disX);
// 如果是向右滑动或者不滑动,不改变滑块的位置
if(this.disX < 0 || this.disX == 0) {
this.data.handleSwipe = "transform:translateX(0px)";
// 大于0,表示左滑了,此时滑块开始滑动
}else if (this.disX > 0) {
//具体滑动距离我取的是 手指偏移距离*5。
this.data.handleSwipe = "transform:translateX(-" this.disX*5 "px)";
// 最大也只能等于按钮宽度
if (this.disX*5 >=wd) {
this.handleSwipe = "transform:translateX(-" wd "px)";
}
}
this.fire('touch',this.data.touchId);
},
end(e){
//console.log(JSON.stringify(e.detail) '结束');
let wd=document.getElementById('btn').offsetWidth;
let endX = e.detail.x;
this.disX = this.data.startX - endX;
//如果距离小于按钮一半,强行回到起点
if ((this.disX*5) < (wd/2)) {
this.data.handleSwipe = "transform:translateX(0px)";
}else{
//大于一半 滑动到最大值
this.data.handleSwipe = "transform:translateX(-" wd "px)";
}
this.fire('touch',this.data.touchId);
},
clickItem(e){
this.data.handleSwipe = "transform:translateX(0px)";
this.fire('clickBtn',{type:e.currentTarget.dataset.type,id:e.currentTarget.dataset.id});
}
}
}
</script>
<style>
.easy-swipe-cell_content{
justify-content: center;
background-color: #ffffff;
position: relative;
width: 100%;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
transition: 0.6s;
min-height: 50px;
padding: 10px;
}
.easy-swipe-cell_btn{
position: absolute;
right: 0;
top: 0;
display: flex;
flex-flow: row nowrap;
height: 100%;
z-index: 1;
}
.easy-swipe-cell_btn-item{
height: 100%;
justify-content: center;
}
.easy-swipe-cell_btn-item-label{
color: #ffffff;
font-size: 15px;
padding: 0 20px;
}
</style>
示例文件
demo-easy-swipe-cell.stml
<template>
<scroll-view class="page">
<safe-area></safe-area>
<view v-for="(item,index) in list">
<easy-swipe-cell
:itemId="item.id"
:itemContent="item.content"
:touchIdNow="touchID"
ontouch="getTouchID"
onclickBtn="getClickTyeAndId"
>
</easy-swipe-cell>
</view>
</scroll-view>
</template>
<script>
import '../../components/easy-swipe-cell.stml'
export default {
name: 'demo-easy-swipe-cell',
apiready(){//like created
},
data() {
return{
list:[{
id:'1',
content:'关于开展什么活动的通知'
},{
id:'2',
content:'这是一条新的系统通知'
},{
id:'3',
content:'您有一条新的消息提醒,请及时查看'
}],
touchID:''
}
},
methods: {
getTouchID(e){
console.log(JSON.stringify(e));
this.data.touchID = e.detail;
},
getClickTyeAndId(e){
console.log(JSON.stringify(e));
api.toast({
msg:'当前点击的是' e.detail.type '按钮,记录ID是' e.detail.id
})
}
}
}
</script>
<style>
.page {
height: 100%;
}
</style>