【问题标题】:How can I disable hover state on mousedown or on dragstart?如何在 mousedown 或 dragstart 上禁用悬停状态?
【发布时间】:2026-01-21 16:10:01
【问题描述】:

我有一个可以通过拖放重新排列的节点 (div) 列表。下面列出了示例代码。通常,我想用一个类突出显示悬停的节点(为简单起见,让我们说蓝色背景,“:悬停”伪类),但是当一个节点被拖动时,我想用另一个类(红色,“拖动”类)。

我有两个问题:

  1. dragstart() 中,我将“拖动”类应用于节点,但它不会立即生效。我可以通过直接修改 style.backgroundColor 来更改背景颜色,但我希望有一个更直接的 css 解决方案来在添加类后重绘节点。

  2. 一旦我更改节点的顺序,悬停状态就会变得混乱。如您所见,如果从上到下拖动节点,悬停状态会跟随该节点(屏蔽“拖动”类),但如果从下到上拖动,悬停状态会跳转到原始索引(收到 mousedown 的节点的索引)现在“拖动”类出现了。

我尝试了各种方法,但无济于事。据我所知,没有办法删除或暂停 :hover 伪类,而且我不知道是否有办法强制悬停在某个节点上(我尝试了简单的事情,比如设置焦点以使节点处于活动状态) .

第二个问题是真正的问题,但如果有人能就如何解决这两个问题发表评论,我将不胜感激。提前致谢。

<html>

<head>
<style>
.node {
    border: 1px solid gray;
    height: 26px;
    width:300px;"
}
.node:hover {
    background-color: #4444ff;
}
.dragged {
    background-color: #ff4444;
}
</style>
</head>

<body>
<div id='cont' style="width: 300px;"></div>
</body>

<script>

(function(){
    var html = '';
    for (var i = 1; i < 11; i++) {
        html += '<div id="' + i + '"draggable="true" ondragstart="dragstart(event)" ondragenter="dragenter(event)" ondragend="dragend(event)" class="node">item' + i + '</div>';
    }
    document.getElementById('cont').innerHTML = html;
})();

function dragstart(event) {
    event.target.className += ' dragged';
    event.dataTransfer.setData('text/html', event.target.id);
}

function dragenter(event) {
    var sourceId = event.dataTransfer.getData('text/html');
    var targetId = event.target.id;

    if (targetId === sourceId) {
        return true;
    }

    var sourceNode = document.getElementById(sourceId);
    var targetNode = document.getElementById(targetId);
    var sourceIndex = Array.prototype.indexOf.call(sourceNode.parentNode.childNodes, sourceNode);
    var targetIndex = Array.prototype.indexOf.call(targetNode.parentNode.childNodes, targetNode);
    if (targetIndex > sourceIndex) {
        targetNode.parentNode.insertBefore(targetNode, sourceNode);
    } else {
        targetNode.parentNode.insertBefore(sourceNode, targetNode);
    }
}

function dragend(event) {
    event.target.className = event.target.className.replace(' dragged', '');
}

</script>

</html>

【问题讨论】:

  • 对于您的第一个问题,请在您的.draggedbackground-color 末尾添加!important。对于第二个,我想我不清楚问题是什么,在 Firefox 上对我来说很好
  • 凯多,感谢您的及时回复。添加 !important 确实适用于第一个问题。第二个问题出现在 Chrome 中,我刚刚检查了 Firefox,它确实可以正常工作。

标签: javascript css hover drag


【解决方案1】:

第一期:

在 CSS 中,在 .draggedbackground-color 末尾添加 !important

第二期:

显然,Chrome 有一个 odd behaviourevent.dataTransfer.setData()

我刚刚通过将setData('text/html'... 替换为setData('Text'... 进行了测试 它实际上在我的 Chrome (36 osx) 中工作。

当然,您也必须将 getData() 参数更改为 "Text"

从 cmets 编辑

由于 Chrome 对 dataTransfer.setData() 的限制,我无法为最后的代码制作一个有效的小提琴。 但它在独立页面中对我有用。

最简单的解决方案是使用一个全局变量来存储您的元素。

var draggedItem;
function dragstart(event) {
    event.target.className += ' dragged';
    draggedItem = event.target;   
}

function dragenter(event) {
    var sourceId = draggedItem.id;
    var targetId = event.target.id;
...

这是一个工作小提琴:http://jsfiddle.net/2Kgvh/

【讨论】:

  • Kaiido,再次感谢您的回答。第一个问题已解决,此外,我们可以在 mousedown 中添加 .dragged 类而不是 dragstart 以立即强制重绘。但即使使用“文本”格式类型,我仍然看到第二个问题 - 从下到上拖动节点使其中一个节点处于悬停状态。 (顺便说一句,刚刚还了解到 IE 不支持 'text/html' 类型,所以我可能还需要为 IE 找到解决方案。)
  • 嗨 Kaiido,就setData 而言,它正在工作,但在 Chrome 中仍然存在悬停节点的问题。如果我向上拖动一个节点,我会看到前一个节点(立即向下移动的节点)保持在“悬停”状态。在 Firefox 中不会发生。
  • @S.V.我添加了一个工作小提琴,看看这个,你还有问题吗?
  • 是的,不幸的是我仍然看到这个问题。如果我从下到上拖动一个项目,其中一个项目保持蓝色,而拖动的项目为红色。在这种情况下,我希望蓝色悬停状态消失。
【解决方案2】:

这变成了 CSS 和跨浏览器的噩梦,所以我求助于 jQuery 及其 Sortable Widget 实现。

【讨论】:

    最近更新 更多