如何使用JavaScript实现Row-box整体拖拽至Column-box内?
实现Row-box拖拽至Column-box内的解决方案
需求背景
现有页面具备以下功能:
- 点击「Add Row」按钮创建Row-box,自动添加到
contentBox容器中 - 点击「Add Column」按钮后,再点击任意Row-box,可将Column-box添加至目标Row-box内
- Column-box可在不同Row-box间拖拽
需要新增功能:支持将整个Row-box拖拽至另一个Column-box内部
核心修改方案
1. 让Row-block支持拖拽
在创建Row-block时添加可拖拽属性,并绑定拖拽事件:
// 在addRow函数中新增以下代码 row.setAttribute('draggable', true); row.addEventListener('dragstart', dragStart); row.addEventListener('dragend', dragEnd);
2. 让Column-block成为可放置目标
给所有Column-block(包括动态创建的)添加放置事件监听,确保能接收拖拽的Row-box:
// 在addCol函数中新增以下代码 col.addEventListener('dragover', dragOver); col.addEventListener('dragenter', dragEnter); col.addEventListener('dragleave', dragLeave); col.addEventListener('drop', Drop);
3. 修复原有拖拽逻辑的bug
- 修正
setTimeout的错误赋值写法(原代码中setTimeout=(()=>..., 0)是语法错误) - 在
dragEnd事件中恢复元素显示状态,避免拖拽后元素消失
修改后的完整代码
HTML(无需修改)
<div class="wrapper"> <div class="main-content"> <div class="header"> <button class="add-row" onclick="addRow()">Add Row +</button> <button class="add-column" onclick="addCol()">Add Column +</button> </div> <div class="content-box" id="contentBox"> </div> </div> </div>
JavaScript
// Row Addition var i=0; let newColNode = null; let dragItem = null; function addRow() { const row = document.createElement('div'); row.className = 'row-block'; row.id = "b" + ++i; // 设置Row可拖拽 row.setAttribute('draggable', true); document.getElementById('contentBox').appendChild(row); row.addEventListener('click', function (event) { if(newColNode != null) row.appendChild(newColNode); newColNode = null }); // 绑定Row的拖拽相关事件 row.addEventListener('dragstart', dragStart); row.addEventListener('dragend', dragEnd); row.addEventListener('dragover', dragOver); row.addEventListener('dragenter', dragEnter); row.addEventListener('dragleave', dragLeave); row.addEventListener('drop', Drop); } function addCol() { const col = document.createElement('div'); // 替换p标签为div,更符合容器语义 col.className = 'column-block'; col.setAttribute('draggable', true); col.textContent = `Column`; newColNode = col; // 绑定Column的拖拽事件 col.addEventListener('dragstart', dragStart); col.addEventListener('dragend', dragEnd); // 让Column支持接收拖拽元素 col.addEventListener('dragover', dragOver); col.addEventListener('dragenter', dragEnter); col.addEventListener('dragleave', dragLeave); col.addEventListener('drop', Drop); } // 拖拽核心逻辑 function dragStart() { dragItem = this; // 修正setTimeout写法,隐藏拖拽元素 setTimeout(() => this.style.display = "none", 0); } function dragEnd() { // 恢复元素显示 setTimeout(() => this.style.display = "", 0); dragItem = null; } function Drop(){ this.append(dragItem); } function dragOver(e){ e.preventDefault(); } function dragEnter(e){ e.preventDefault(); } function dragLeave(){ // 可自定义拖拽时的视觉反馈,比如边框变色 }
CSS(优化视觉体验)
* { box-sizing: border-box; } .wrapper { float: left; width: 100%; height: 100vh; } body { padding: 0; margin: 0; position: relative; } .main-content { float: left; width: 100%; height: 100%; background: #fafafa; } .header { height: 60px; display: flex; align-items: center; justify-content: flex-end; padding: 0 20px; } .content-box { width: 100%; height: calc(100% - 60px); padding: 15px; } button { background: #000; border: 0; padding: 0 20px; height: 40px; margin-left: 10px; font-weight: 600; color: white; cursor: pointer; } .row-block { width: 100%; border: 2px dashed #848484; padding: 20px; display: flex; flex-wrap: wrap; margin-bottom: 20px; cursor: move; /* 添加拖拽光标提示 */ } .row-block:hover { border-color: #2654d1; } .column-block { position: relative; width: 100%; min-height: 100px; /* 增加最小高度,方便拖拽放置 */ padding-right: 10px; padding-left: 10px; margin: 0 10px 20px; flex-basis: 0; flex-grow: 1; max-width: 100%; border: 2px dashed #848484; background-color: #dedede; padding: 20px; } .column-block:first-child { margin-left: 0; } .column-block:last-child { margin-right: 0; }
内容的提问来源于stack exchange,提问作者Unnikrishnan PJ
相关产品推荐
相关产品推荐

