应用场景:
在项目列表(List)中左滑,删除 || 取消关注当前项
实现方式
使用移动端触摸事件ontouchstart、ontouchmove、ontouchend; + SCSS
移动端事件详解:事件详解
布局css部分
.slide-item {
width: 100vw;
overflow: hidden;
line-height: 48px;
height: 160px;
text-align: center;
margin-bottom: 20px;
&-wrap {
width: calc(100vw + 180px);
height: 100%;
position: relative;
}
&-left {
width: 100vw;
width: 686px;
padding: 0 32px;
display: flex;
}
&-right {
width: 180px;
height: 100%;
background: #f60;
position: absolute;
right: 0;
top: 0;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
}
.schoolLogo{
width: 120px;
height: 120px;
}
.schoolInformation{
text-align: left;
padding-left: 8px;
}
}
js hook 部分
排除纵向滑动,横向滑动是如果左滑出现删除 || 取消关注,如果右滑恢复原位置
排他性,判断当前滑动为那一项,当前项滑动时,其他已滑动选项恢复初始样式,
当前滑动项出现删除 || 取消关注
export default function AttentionSchool() {
const [hasTransition, setHasTransition] = useState(false)
const [startX, setStartX] = useState(0)
const [startY, setStartY] = useState(0)
const [moveX, setMoveX] = useState(0)
const [current, setCurrent] = useState()
const [arr, setArr] = useState([1, 2, 3, 4, 5, 6])
let moveY = 0
let moveStyle = {}
const handleTouchStart = e => {
// console.log('handleTouchStart', e, e.touches[0].pageX)
setStartX(e.touches[0].pageX)
setStartY(e.touches[0].pageY)
}
const handleTouchMove = (e,index) => {
// 若想阻止冒泡且最外层盒子为scrollView,不可用e.stopPropogagation(),否则页面卡死
setCurrent(index)
moveY = e.touches[0].pageY - startY
setMoveX(e.touches[0].pageX - startX)
// 纵向移动时return
if (Math.abs(moveY) > Math.abs(e.touches[0].pageX - startX)) {
return
}
// 滑动超过一定距离时,才触发
if (Math.abs(e.touches[0].pageX - startX) < 10) {
return
} else {
// 否则没有动画效果
setHasTransition(true)
}
}
const handleTouchEnd = () => {
// 结束时,置为true,否则render时不生效
setHasTransition(true)
}
const handleDel = (index) => {
setArr((sz)=>{
sz.splice(index,1)
return sz
})
setHasTransition(false)
}
const prefix = 'slide-item'
const distance = moveX > 0 ? 0 : -90
return (
<View>
{
arr.map((item,index) => {
// 排他性,若某一个处于滑动状态时,其他都回归原位
if( hasTransition && current == index ){
moveStyle = {
transform: `translateX(${distance}PX)`,
webkitTransform: `translateX(${distance}PX)`,
transition: 'transform 0.3s ease',
WebkitTransition: 'transform 0.3s ease'
}
}else{
moveStyle = {
transform: `translateX(${0}PX)`,
webkitTransform: `translateX(${0}PX)`,
transition: 'transform 0.3s ease',
WebkitTransition: 'transform 0.3s ease'
}
}
return (
<View className={prefix} key={item}>
<View className={`${prefix}-wrap`} style={moveStyle}>
<View
className={`${prefix}-left`}
onTouchStart={(e) => handleTouchStart(e)}
onTouchMove={(e) => handleTouchMove(e,index)}
onTouchEnd={() => handleTouchEnd()}
>
<Image className='schoolLogo' src={require('../../../assets/images/hot.svg')} />
<View className='schoolInformation'>
<View>标题{item}</View>
<View><Text>内容</Text><Text>内容</Text><Text>内容</Text></View>
</View>
</View>
<View className={`${prefix}-right`}>
<View className={`${prefix}-del`} onClick={() => handleDel(index)}>取消关注</View>
</View>
</View>
</View>
)
})
}
</View>
)
}