大家好,今天跟大家分享一个小知识,前端页面的拖拽效果。这个效果可以说还是很常见的,比如说玩一些游戏的时候,将装备直接拖拽到一定区域就会丢掉或者装备上,再比如说一个列表,通过拖拽排序等。那么今天我们就从最简单的列表拖拽来了解它的实现。
认识一些拖拽API
| API | |
|---|---|
dragable = 'true' | 表示某个元素是可以拖动的(简单来说,元素有这个属性,就可以拖动了) |
ondragstart | 用于处理元素开始被拖动时触发的相关操作事件(字面意思,你在拖动它的时候,想让它干什么,在此时定义。比如改变css等) |
ondragenter | 被拖动的元素进入到有效的放置目标区域时触发(简单来说,我们拖拽的这个元素,进入到一个区域可行的区域的时候,此时会触发什么。比如我们游戏点击一个装备拖拽到区域内可以装上(此时还没有放手),来到这个区域有个提示可以装) |
ondragend | 事件会在被拖动的元素结束拖动操作时触发,也就是当用户松开鼠标按键(简单来说,你松开鼠标的时候要触发的事件定义在此。接着上个例子:装备拖到此区域,然后放手装上了) |
| 【额外了解】 | |
e.target.nextElementSibling | 获取触发当前事件的那个元素的下一个同级兄弟元素(字母意思比较好理解,同时可以通过这个API去设置一个元素的下一个元素是什么,这个会在我们的这次测试中用到) |
insertBefore | JavaScript操作DOM节点的方法,将一个节点插入到另一个指定节点之前 |
建立一个测试案例列表
这是一个比较好理解的简单的一个list列表,同时已经给每个元素加上了可拖拽API:dragable = 'true',也就是说,这个页面已经可以拖拽了
注意:拖拽的时候,鼠标是一个禁止的符号:大多数网页和应用程序都不能放置拖拽数据,想要成功必须取消dragenter 和 dragover 事件的默认处理行为。
e.prevetDefault()解决
设置ondragstart
我们希望在拖拽之后让 被拖拽的元素样式 和 其被拖拽的区域样式 是不同的,这样便于区分,也是为了让这个过程更具有分辨性。
注意:此时我们看到,我们拖拽的鼠标dom和 拖拽区域都改变了,是因为 鼠标拖拽的dom会根据拖拽的时候的原样式。这里我们要用到
事件循环机制的原理,加一个定时器来减缓样式的改变。(了解事件循环机制:问:下面代码的宏任务微任务执行顺序是怎样的对于事件循环不知道有多少同学在面试的笔试题被它绕的团团转,作为js的处理事件的 - 掘金 (juejin.cn))
修改后
设置ondragenter
这里我们设置的是,被拖动的元素进入到有效的放置目标区域时触发的情况。目标是:让我们的这些列表可以根据我当前的移动调整位置。
- 初步测试:测试移动到相关的位置,输出一下
这里我们发现:移动的时候不仅会触发获取 dom的原来位置还会有父元素的位置,从优化方面来说,可以通过判断去除。(
e.prevetDefault()解决大多数网页和应用程序都不能放置拖拽数据)
- 获取当前元素的下标,通过判断 当前我拖拽dom的下标 和 要放置位置的下标 进行判断
nextElementSibling 和 insertBefore 修改位置
根据这两个API的作用,在 拖动dom的下标 和 放置区域的下标进行 判断,大于或小于情况分别使用(这里不对两个方法进行介绍了,大家可以自行搜索详细使用方式)
ondragend
收尾工作,放置后,如果不设置 ondragend ,被拖拽元素会回到原来样式(也就是我们改变后的样式),移除掉样式即可。此时整个的效果就达成了
最终效果
- 拖拽到其他位置,并放下
- 拖拽大数字,往上放
总结
总体来说,简单的去实现一个拖拽功能不会太难,主要是去把握住这几个API分别代表着什么作用,以及可以在其中可以做的一些操作。如果大家想自己练习一下,大家可以试试,如何把 拖拽的dom 放到一个新的区域中去。