【问题标题】:The new child element contains the parent. at HTMLDivElement.drop新的子元素包含父元素。在 HTMLDivElement.drop
【发布时间】:2018-06-30 07:48:04
【问题描述】:

我被这个 DOM 异常困住了。我有 div 元素和一个按钮 - 当用户单击按钮时,会选择一个随机 div,在该 div 上附加另一个 div。这另一个 div 有一个设置了背景颜色的类。换句话说,当用户点击按钮时,一个随机的 div 容器会被另一个随机颜色的 div 填充。然后我希望用户能够将这个新创建的彩色 div 拖到一个空的 div 上。这就是问题所在。这是我的标记:

<div class="row">
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
</div>

单击按钮后(添加了一个新的 div)如下所示:

 <div class="row">
    <div class="empty border"></div>
    <div class="empty border">
        <div class="filled" draggable="true" id="test
        style="background-color: rgb(242, 202, 185);"></div>
    </div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
 </div>

所以,当“填充”的 div 被放入 dropzone(一个空的 div)时,我得到了这个未捕获的异常。这是我的 JS:

const prepareForDrag =  () => {
let divElements = Array.from(document.getElementsByTagName('div'));
let emptyCubes = divElements.filter(cube =>    cube.classList.contains('empty'));
let filledCubes = divElements.filter(cube => cube.classList.contains('filled'));

emptyCubes.forEach(function (cube) {
    cube.addEventListener('dragover', dragOver);
    cube.addEventListener('drop', drop);
})

filledCubes.forEach(function (cube) {
    cube.addEventListener('dragstart', dragStart);
})

function dragStart (e) {
    emptyCubes.forEach(cube => cube.classList.add('dropzone-border'));
    e.dataTransfer.setData('text/plain', e.target.getAttribute('id'));
}

function dragOver (e) {
    e.preventDefault();
}


function drop (e) {
    let coloredCube = e.dataTransfer.getData('text/plain');
    e.target.appendChild(document.getElementById(coloredCube));
    emptyCubes.forEach(cube => cube.classList.remove('dropzone-border'));
}
}

我清楚地理解的是,当我释放鼠标按钮时,它会尝试同时附加父 div 和“填充”一个,但我真的找不到解决方案。任何帮助和残酷的批评将不胜感激:)

【问题讨论】:

    标签: javascript html css drag-and-drop


    【解决方案1】:

    这是我的解决方案。 我将当前拖动的 div 保存在 dragged 变量中,并在整个文档上放置了一个 drop 事件,然后您可以使用该拖动变量将其从其父节点中删除并附加到放置的元素。

    我认为您要么有多个元素具有相同的 id,这会混淆 Javascript,要么您在 drop 函数中拥有的 coloredCube 变量没有返回您认为的值。我会在coloredCube 上放置一个console.log。当我在 dataTransfer 属性上运行 getData 方法时得到一个空字符串,这可能会导致您遇到错误。

    let dragged;
    
    function appendDiv(e) {
        e.preventDefault();
        const emptyDivs = Array.from(document.getElementsByClassName('empty'));
        const newDiv = document.createElement('div');
        newDiv.classList = 'filled';
        newDiv.draggable = true;
        newDiv.style.backgroundColor="red";
        newDiv.style.height = "50px";
        newDiv.style.width = "50px";
        newDiv.addEventListener('dragstart', dragStart);
        newDiv.addEventListener('dragend', dragEnd);
        // Should add to a random empty div. I just picked one to add it.
        emptyDivs[1].appendChild(newDiv); 
    }
    
    function dragStart(e){
        dragged = e.target;
        e.target.style.opacity = .5;
        e.dataTransfer.setData('text/plain', null);
    }
    
    function dragEnd(e){
        e.target.style.opacity = "";
    }
    
    function handleDrop(e){
        e.preventDefault();
        dragged.parentNode.removeChild(dragged);
        e.target.appendChild(dragged);
    }
    
    function dragOver(e){
        e.preventDefault();
    }
    
    document.addEventListener('drop', handleDrop);
    
    Array.from(document.getElementsByClassName('empty')).forEach(emptyDiv => {
        emptyDiv.addEventListener('dragover', dragOver);
    });
    
    
    document.getElementById('btn-append').addEventListener('click', appendDiv);
    

    【讨论】:

    • 是的,问题是在特定时刻,第二个具有相同名称的 id 被添加到随机 div 中(我昨天没有分享的部分代码)。关于你得到的空字符串,它不是这样工作的吗?我的意思是 dataTransfer.setData() 不是受 JS 引擎保护还是我错了?
    猜你喜欢
    • 1970-01-01
    • 2016-07-18
    • 2017-03-28
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 2014-12-05
    • 1970-01-01
    • 2017-05-25
    相关资源
    最近更新 更多