您现在的位置是:亿华云 > IT科技类资讯
让拖拽更加人性化-如何自定义 Dragover 样式?
亿华云2025-10-09 01:19:40【IT科技类资讯】7人已围观
简介在 web 开发中,经常会碰到需要拖拽的场景。为了更好的体验,拖拽区域需要有一定的变化提示,告诉用户:"现在可以放在这里了~",例如这样的。dragover效果这次接着探索一下如何自定义 dragov
在 web 开发中,让拖经常会碰到需要拖拽的拽更场景。为了更好的加人体验,拖拽区域需要有一定的性化变化提示,告诉用户:"现在可以放在这里了~",何自例如这样的定义。
dragover效果
这次接着探索一下如何自定义 dragover 样式。样式
一、让拖dragenter 和 dragleave要实现这样的拽更效果,少不了和dragenter和dragleave打交道。加人
当拖动的性化元素进入有效的放置目标时, 将会触发dragenter 事件。何自当拖动的定义元素离开有效的放置目标时,将会触发dragleave 事件。样式拖拽目标和放置目标
假设现在有这样一个结构,让拖这里 img是拖拽目标,div.content是放置目标。
<div class="content"></div>然后在document监听一下;
document.addEventListener(dragleave, function(ev) {
console.log(dragleave, ev.target)
})
document.addEventListener(dragenter, function(ev) {
console.log(dragenter, ev.target)
})那么,将img拖入div.content的过程中,肯定会触发dragenter和dragleave这两个事件,如下:
dragenter和dragleave
如果页面比较简单,要自定义拖拽过程就比较容易了;
document.addEventListener(dragleave, function(ev) {
ev.target.toggleAttribute(over,false);
})
document.addEventListener(dragenter, function(ev) {
ev.target.toggleAttribute(over,true);
})通过添加over属性自定义样式;
.content[over]{
outline: 4px solid slateblue;
}效果如下:
dragover效果
是源码下载不是非常容易呢?
实际使用起来其实还存在很多局限性,下面一一介绍。
二、当放置目标有子元素时大部分情况下,放置目标并不是空的,还有其他子元素,如果采用上面的方式就会有问题了,假设布局是这样的,为了区分,可以给需要放置的元素添加一个属性,比如allowdrop,表示允许放置;
不允许放置</div>这里通过属性区分一下:
document.addEventListener(dragleave, function(ev) {
if (ev.target.getAttribute(allowdrop)!==null) {
ev.target.toggleAttribute(over,false);
}
})
document.addEventListener(dragenter, function(ev) {
if (ev.target.getAttribute(allowdrop)!==null) {
ev.target.toggleAttribute(over,true);
}
})效果如下:
有子元素的情况下
可以看到,当拖拽目标经过子元素时,外面的样式已经丢失了。原因其实很简单,在经过子元素时,放置目标也触发了dragleave事件!
那有没有办法不触发呢?这里有两种方式:
首先可以取消dragleave的监听,因为在执行dragleave时,元素本身是不知道即将进入哪一个区域,很容易“误伤”。取而代之的云服务器提供商是每次dragenter时,先移除上一次放置目标的属性,然后再添加新的,有点类似选项卡的操作,具体实现如下:
var lastDrop = null;
document.addEventListener(dragenter, function(ev) {
if (lastDrop) {
lastDrop.toggleAttribute(over,false);
}
const dropbox = ev.target.closest([allowdrop]); // 获取最近的放置目标
if (dropbox) {
dropbox.toggleAttribute(over,true);
lastDrop = dropbox;
}
})还有另一种方式:借助 CSS 就非常容易了。
这里有一个非常简单粗暴的方式,直接将子元素禁用鼠标响应,如下:
.content[allowdrop](empty::after{ "allowdrop") *{
pointer-events: none;
}这样,在滑过任何子元素都不会有响应了,完美。
有子元素的情况,完美
三、多层嵌套放置目标上面这种方式其实可以解决大多数问题了,毕竟大部分场景都是扁平的。不过有时候也会碰到多层结构,比如那种可视化编辑工具,尤其是目前比较火的低代码平台,就会涉及到多层结构,假设 HTML 是这样的。
不允许拖拽</div>如果按照 CSS 的b2b供应网处理方式(JS 方式没有问题),由于所有子元素都被禁用,里面的结构自然也无法响应了。
多层嵌套结构无响应
那如何让里面的放置目标可以响应呢?其实只需要改一下上面的 CSS 即可,如下:
.content[allowdrop](empty::after{ "allowdrop")>*:not([allowdrop]){
pointer-events: none;
}这里使用了>选择器,表示只选择子元素,不包含后代元素,然后排除掉放置目标,这样就能实现多层嵌套了,效果如下:
多层嵌套结构,完美
是不是出乎意料的简单呢?
四、其他交互细节不知道大家发现没,上面的例子在拖拽开始,鼠标就一直处于这种“可放置”状态,不管是在放置目标外部还是内部,如下:
鼠标指针状态
这是因为设置了dragover属性,所以整个document都变成了可放置目标,都允许触发drop事件。
document.addEventListener(dragover, function(ev){
ev.preventDefault()
})如果希望交互更加细腻,体验更好,那么在鼠标指示上也可以进一步的优化,可以在进入放置目标后才变成这种状态,实现如下:
document.addEventListener(dragover, function(ev){
const dropbox = ev.target.closest([allowdrop]);
if (dropbox) {
ev.preventDefault()
}
})效果如下(注意观察鼠标的变化
很赞哦!(1482)
相关文章
- .net 适用于从事Internet相关的网络服务的机构或公司
- 如何使用 IDEA 创建 Java 入门应用
- 面试突击:如何使用线程池执行定时任务?
- 关系型数据库RDBMS的旧与新 -- 谈谈NewSQL
- 为什么大家都选优质域名?到底存在着什么好处?
- Redis是如何存储对象和集合的
- 5分钟快速入门,用Python做SQLite数据库开发,附代码适合初学
- Vue2剥丝抽茧-响应式系统完善
- 域后缀首选.com,.net,然后是.cn。后缀选择不当,导致流量损失。域名是企业与互联网网址之间的链接,关键是企业在网络上存在的标志。因此,选择好域名是开展网上工作的首要重要条件。
- 聊聊 React 18 对 Hooks 的影响