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

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

  先上效果图

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

 

实现思路

1. 确定渲染的数据结构

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

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

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

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

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssfxd.html