您的位置:首页 > Web前端 > JavaScript

原生js实现一个侧滑删除取消组件(item slide)

2019-06-10 17:02 2011 查看

组件,本质上是解决某个问题封装的类,在此记录原生js实现侧滑删除

 

先上效果图

 

实现思路

1. 确定渲染的数据结构

2. 思考划分布局,总的有两个主要的模块:内容区域和按钮区域

  2.1 内容区域保持宽度永远占满设备的宽度

  2.2 内容区域和按钮区域之和的宽度等于每一行item的总宽度

3. 每行超出的item的部分设置overflow: hidden; 通过touch相关的API事件监听手势是左滑还是右滑

4. 左滑的时候通过改变元素的一个特定属性来表明左滑,右滑同理

5. 通过css3 slector提前写好左滑情况和右滑情况下的样式,这里的样式主要是改变item的左右偏移

6. 创建元素的时候做的一些性能优化,尽量减少reflow,reflow的来源是由于dom的改变引起的,所以可以思考先将所有元素都写好后一次性插入,减少dom的变化,减少reflow

7. 左滑和右滑的样式的动画优化,让滑动更自然,这里使用了过度效果

 

整体代码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximun-scale=1.0, user-scalable=0">
<title>item slide</title>
<style type="text/css">
body,p {
margin: 0;
}
.list-container {
padding: 0;
overflow: hidden;
margin: 0;
}
.item-container {
list-style: none;
border-bottom: 0.5px solid #9e9e9e73;
width: calc(100% + 10em);
display: flex;
align-items: stretch;
transition: all ease-in-out 0.2s;
}
.left-contianer {
padding: 10px 10px;
flex: 100%;
}
.delete-container,
.cancle-container {
width: 5em;
background: #f44336;
position: relative;
}

.delete-Content,
.cancle-Content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
}

.delete-container{
border-right: 0.5px solid #ffffff80;
}

.item-container[data-type = "1"]{
transform: translate3d(-10em, 0, 0);
}

.item-container[data-type = "0"]{
transform: translate3d(0, 0, 0);
}
</style>
</head>
<body>
<ul class="list-container"></ul>

<script type="text/javascript">

let list = [
{
name:'1111111',
address: '1111111dsdsdsdsdadsd'
},
{
name: '2222222',
address: '2222222ssdsdadsdsadsa'
},
{
name: '3333333',
address: '3333333sfsdsddsdsd'
}
];

class ItemSlide {
constructor(obj){
this.data = obj['data'] ? obj['data'] : [];
this.startX = 0;
this.endX = 0;
}

init(){
this.listContainer = document.querySelector('.list-container');
this.fragment = document.createDocumentFragment();
this.render();
}

render(){
this.data.map((v, i) => {
let item = document.createElement('li');
item.classList.add('item-container');
item.setAttribute('resource-id', i + 1);
item.addEventListener('touchstart', this.touchStart.bind(this));
item.addEventListener('touchend', this.touchEnd.bind(this))

let leftContianer = document.createElement('div');
leftContianer.classList.add('left-contianer');

let name = document.createElement('p');
name.textContent = v.name;

let address = document.createElement('p');
address.textContent = v.address;

leftContianer.appendChild(name);
leftContianer.appendChild(address);

let deleteBtn = document.createElement('div');
deleteBtn.classList.add('delete-container');

let deleteContent = document.createElement('span');
deleteContent.textContent = 'delete';
deleteContent.classList.add('delete-Content');
deleteBtn.appendChild(deleteContent);

let cancleBtn = document.createElement('div');
cancleBtn.classList.add('cancle-container');

let cancleContent = document.createElement('span');
cancleContent.textContent = 'cancle';
cancleContent.classList.add('cancle-Content');
cancleBtn.appendChild(cancleContent);

item.appendChild(leftContianer);
item.appendChild(deleteBtn);
item.appendChild(cancleBtn);

this.fragment.appendChild(item);
});
this.listContainer.appendChild(this.fragment);
}

touchStart(e) {
this.startX = e.touches[0].clientX;
}

touchEnd(e) {
const liEl = e.target.parentElement.parentElement;

this.endX = e.changedTouches[0].clientX;
let distance = this.startX - this.endX;

// 左滑
if(distance > 0) {
this.setSlide(liEl);
// 右滑
}else if(distance < 0) {
this.resetSlide(liEl);
}
}

setSlide(el){
el.setAttribute('data-type', "1");
}

resetSlide(el) {
el.setAttribute('data-type', "0");
}

}

new ItemSlide({
data: list
}).init();
</script>
</body>
</html>

 PS: 

代码中的创建节点感觉写得有点冗余,如果有刚简便并且要考虑到性能的好写法欢迎留言👍

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: