如何实现仅拖动内部元素而非其可拖动容器?
容器可拖动时仅拖动内部元素的解决方案
有时我们需要在容器本身也设置了可拖动属性的情况下,仅拖动其内部的指定元素。但如果直接给容器和内部元素都添加拖动事件监听,会出现一个问题:拖动内部元素时,dragging 类会被错误地添加到容器的类列表中——这是因为拖动事件会向上冒泡到容器,触发容器的 dragstart 事件。
问题示例代码
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>拖动示例</title> </head> <body> <div id="container" class="container draggable" draggable="true" style="background-color: rgb(0, 0, 255); width: 500px; height: 500px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);"> <div id="inner" class="inner draggable" draggable="true" style="background-color: red; width: 200px; height: 200px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);"></div> </div> </body> <script> // 为所有可拖动元素绑定拖动事件监听 const draggables = document.querySelectorAll('.draggable'); draggables.forEach(draggable => { draggable.addEventListener('dragstart', (e) => { draggable.classList.add('dragging'); }); draggable.addEventListener('dragend', () => { draggable.classList.remove('dragging'); }); }); </script> </html>
解决方案
要解决这个问题,只需在内部元素的 dragstart 事件处理函数中调用 e.stopPropagation(),阻止事件向上冒泡到容器元素。这样拖动内部元素时,就只会给内部元素添加 dragging 类,不会触发容器的拖动事件:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>拖动示例</title> </head> <body> <div id="container" class="container draggable" draggable="true" style="background-color: rgb(0, 0, 255); width: 500px; height: 500px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);"> <div id="inner" class="inner draggable" draggable="true" style="background-color: red; width: 200px; height: 200px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);"></div> </div> </body> <script> // 为所有可拖动元素绑定拖动事件监听 const draggables = document.querySelectorAll('.draggable'); draggables.forEach(draggable => { draggable.addEventListener('dragstart', (e) => { // 阻止内部元素的拖动事件冒泡到容器 if (draggable.classList.contains('inner')) { e.stopPropagation(); } draggable.classList.add('dragging'); }); draggable.addEventListener('dragend', () => { draggable.classList.remove('dragging'); }); }); </script> </html>
注:示例中补充了position: absolute和transform: translate(-50%, -50%)样式,确保元素能按设置的left和top值居中显示。
内容的提问来源于stack exchange,提问作者Rory McDonald
相关产品推荐
相关产品推荐

