组件,本质上是解决某个问题封装的类,在此记录原生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 = [
{
remark:'1111111',
value: '1111111dsdsdsdsdadsd'
},
{
remark: '2222222',
value: '2222222ssdsdadsdsadsa'
},
{
remark: '3333333',
value: '3333333sfsdsddsdsd'
}
]; class ItemSlide {
constructor(obj){
this.data = obj['data'] ? obj['data'] : [];
this.name = obj['name'] ? obj['name'] : 'name';
this.value = obj['value'] ? obj['value'] : 'value';
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);
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[this.name]; let address = document.createElement('p');
address.textContent = v[this.value]; leftContianer.appendChild(name);
leftContianer.appendChild(address); let deleteBtn = document.createElement('div');
deleteBtn.classList.add('delete-container');
deleteBtn.addEventListener('click', this.delItem.bind(this), true); 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");
} delItem(e){
const parentEl = this.findParent(e, 'resource-id');
this.listContainer.removeChild(parentEl);
} findParent(childEl, attr){
const parentEl = childEl.target ?
childEl.target.parentElement :
childEl.parentElement;
const id = parentEl.getAttribute(attr);
if(id) {
return parentEl;
}
return this.findParent(parentEl, attr);
} } new ItemSlide({
data: list,
name: 'remark'
}).init();
</script>
</body>
</html>

PS:

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

原生js实现一个侧滑删除取消组件(item slide)的更多相关文章

  1. 原生JS动态添加和删除类

    原生JS动态添加和删除类 由于需要, 给按钮组监听点击事件(要求用事件委托),当有一个按钮被点击时,相应的给该按钮添加一个类(激活类),其他没有点击的按钮就要移出该类 添加和和删除类有三种方法 首先等 ...

  2. 原生js实现一个DIV的碰撞反弹运动,并且添加重力效果

    继上一篇... 原生js实现一个DIV的碰撞反弹运动,并且添加重力效果 关键在于边界检测,以及乘以的系数问题,实现代码并不难,如下: <!DOCTYPE html> <html la ...

  3. 原生js实现一个DIV的碰撞反弹运动

     原生js实现一个DIV的碰撞反弹运动: 关键在于DIV的边界检测,进而改变运动方向,即可实现碰撞反弹效果. <!DOCTYPE html> <html lang="en& ...

  4. 用原生js写一个"多动症"的简历

    用原生js写一个"多动症"的简历 预览地址源码地址 最近在知乎上看到@方应杭用vue写了一个会动的简历,觉得挺好玩的,研究一下其实现思路,决定试试用原生js来实现. 会动的简历实现 ...

  5. 用原生JS实现一个轮播(包含全部代码和详细思路)

    在我看来要想实现轮播主要是要知道当前位于的页面和即将位于的页面.这个案例是通过改变图片的透明度来实现轮播的效果. 我把涉及的知识点分为两个方面,分别是HTML+css和JS. 第一部分(html+cs ...

  6. 原生js写一个无缝轮播图插件(支持vue)

    轮播图插件(Broadcast.js) 前言:写这个插件的原因 前段时间准备用vue加上网易云的nodejs接口,模拟网易云音乐移动端.因为想自己写一遍所有的代码以及加固自己的flex布局,所以没有使 ...

  7. 用原生JS写一个网页版的2048小游戏(兼容移动端)

    这个游戏JS部分全都是用原生JS代码写的,加有少量的CSS3动画,并简单的兼容了一下移动端. 先看一下在线的demo:https://yuan-yiming.github.io/2048-online ...

  8. 原生 JS实现一个简单分页插件

    最近做的一个 PC端的需求,这个需求中有一个小点,页面底部有一块列表区域,这个列表的数据量比较大,需要进行分页控制,切换页码的时候,发送一个 ajax请求,在页面无刷新的情况下,实现列表数据的刷新,所 ...

  9. 使用原生JS封装一个动画函数

    最近一直在忙项目,很少有时间回顾之前的知识,今天刚好要做一个轮播,因为对兼容性有一定的要求,使用了各种插件和库中的轮播,效果都不是很理想,一怒之下,使用原生JS封装了一个轮播组件,其中重要的功能就是一 ...

随机推荐

  1. Grunt 学习笔记【1】----基础知识

    题记:虽然现在大家都在推Webpack,无奈业务需要,因此研究下Grunt. 说明:本文是基于Grunt 0.4.5版本. 一 说明 为何要用构建工具? 一句话:自动化.对于需要反复重复的任务,例如压 ...

  2. get_linux_ip_info.sh 获取ip地址

    linux 获取ip地址 get_linux_ip_info.sh #!/bin/bash #/告诉使用者,这程序的用户是从ipconfig 命令中获取IP地址 echo "该程序是从命令中 ...

  3. Spring事务超时时间可能存在的错误认识

    摘自:http://jinnianshilongnian.iteye.com/blog/1986023, 感谢作者. 1.先看代码 1.1.spring-config.xml <bean id= ...

  4. 51Nod 1376 最长递增子序列的数量 —— LIS、线段树

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376 1376 最长递增子序列的数量 基准时间限制:1 秒 空 ...

  5. PYTHON 爬虫笔记十一:Scrapy框架的基本使用

    Scrapy框架详解及其基本使用 scrapy框架原理 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了 ...

  6. socket,获取html,webservice等,支持chunked,gzip,deflate

    1. [代码][C#]代码using System;using System.Collections.Generic;using System.Linq;using System.Net.Socket ...

  7. 清除float浮动三种方式

    Float的作用? w3c的官方解释: Content flows down the right side of a left-floated box and down the left side o ...

  8. jsp日期插件My97DatePicker 强大的日期控件 使用方便简单(转)

    本文属转载(希望对编程爱好者有所帮助)详情请访问官方网站 http://www.my97.net/dp/index.asp 一. 简介 1. 简介 目前的版本是:4.7 2. 注意事项 My97Dat ...

  9. 「LOJ#10068」「一本通 3.1 练习 3」秘密的牛奶运输(次小生成树

    题目描述 Farmer John 要把他的牛奶运输到各个销售点.运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点. 运输的总距离越小,运输的成本也就越低.低成本的运输是 F ...

  10. myeclipse 2017破解安装教程+开发环境部署(jdk+tomcat)

    点击安装包,进入安装界面,点击next 选择接受协议,点击next 选择安装目录,点击next 格局自己电脑的机型选择32bit或64bit,点击next 安装完成后不要运行MyEclipse,将 & ...