如何在reactjs中的div之间拖放?
Posted
技术标签:
【中文标题】如何在reactjs中的div之间拖放?【英文标题】:How to drag and drop in between divs in reactjs? 【发布时间】:2022-01-20 23:16:15 【问题描述】:我尝试使用香草html/js
API 在reactjs
中实现拖放功能。我几乎完成了它,但我不能将它放在现有的div
s 之间。我想在两个 div 中添加拖放功能(即,我应该能够拖动第一列中的任何 div
s 并拖放到第二列中的任何位置,反之亦然)。到目前为止,我只能在最后一个index
拖放,而不是介于两者之间
这是我到目前为止所尝试的。请附上代码。如果您提出建议,我不会那么强烈地追随
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const App = () =>
const drop = (e) =>
e.preventDefault();
const div_id = e.dataTransfer.getData("div_id");
const block = document.getElementById(div_id);
e.target.appendChild(block);
;
const dragOver1 = (e) =>
e.preventDefault();
;
const dragStart = (e) =>
const target = e.target;
e.dataTransfer.setData("div_id", target.id);
;
const dragOver = (e) =>
e.stopPropagation();
;
return (
<div
style=
display: "flex",
justifyContent: "space-between",
padding: "50px",
>
<div
onDrop=drop
onDragOver=dragOver1
id="board-1"
style=
border: "1px solid #222",
padding: 20,
>
<div
id="firstfirst"
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<div>
<h1>First Column First Row</h1>
</div>
</div>
<div
id="firstsecond"
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<div>
<h1>First Column Second Row</h1>
</div>
</div>
Array.from(Array(2)).map((_, index) =>
return (
<div
key=index
id=`first$index`
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<h1>First Column Row index</h1>
</div>
);
)
</div>
<div
id="board-2"
onDrop=drop
onDragOver=dragOver1
style=
border: "1px solid #222",
padding: 20,
>
<div
id="secondfirst"
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<h1>Second Column First Row</h1>
</div>
<div
id="secondsecond"
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<h1>Second Column Second Row</h1>
</div>
Array.from(Array(2)).map((c, index) =>
return (
<div
key=index
id=`second$index`
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<h1> Second Column Row index </h1>
</div>
);
)
</div>
</div>
);
;
ReactDOM.render(<App />, document.getElementById("app"));
</script>
【问题讨论】:
直接修改 DOM 可能会干扰 React 自己对 DOM 的管理。 dnd 最好使用一些特定于 React 的包。 @tromgy 有什么例子吗?而且我看到它已经正常工作了。只是顺序不对 这可能正是问题所在。一方面你让 React 使用Array.map
管理<div>
s 的列表,另一方面你直接通过appendChild
修改DOM。
【参考方案1】:
appendChild
总是将项目添加到目标 div
的末尾。您可以使用孩子的位置 (child.getBoundingClientRect().bottom
) 和鼠标放置位置 (e.clientY
) 进行简单的计算来确定要放置的位置。
如下更改drop
处理程序
const drop = e =>
e.preventDefault();
const div_id = e.dataTransfer.getData("div_id");
const block = document.getElementById(div_id);
// get the child div index where to drop
let dropIndex = Array.from(e.target.children).findIndex(
// find the first child index where
// a child bottom (vertical viewport height to the bottom of child div)
// is greater than mouse Y position
child => child.getBoundingClientRect().bottom > e.clientY
);
if (dropIndex === -1)
// drop at the end
e.target.appendChild(block);
else
// drop at start or in between
e.target.insertBefore(block, e.target.children[dropIndex]);
;
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const App = () =>
const drop = (e) =>
e.preventDefault();
const div_id = e.dataTransfer.getData("div_id");
const block = document.getElementById(div_id);
let dropIndex = Array.from(e.target.children).findIndex(
(child) => child.getBoundingClientRect().bottom > e.clientY
);
if (dropIndex === -1)
e.target.appendChild(block);
else
e.target.insertBefore(block, e.target.children[dropIndex]);
;
const dragOver1 = (e) =>
e.preventDefault();
;
const dragStart = (e) =>
const target = e.target;
e.dataTransfer.setData("div_id", target.id);
;
const dragOver = (e) =>
e.stopPropagation();
;
return (
<div
style=
display: "flex",
justifyContent: "space-between",
padding: "50px",
>
<div
onDrop=drop
onDragOver=dragOver1
id="board-1"
style=
border: "1px solid #222",
padding: 20,
>
<div
id="firstfirst"
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<div>
<h1>First Column First Row</h1>
</div>
</div>
<div
id="firstsecond"
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<div>
<h1>First Column Second Row</h1>
</div>
</div>
Array.from(Array(2)).map((_, index) =>
return (
<div
key=index
id=`first$index`
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<h1>First Column Row index</h1>
</div>
);
)
</div>
<div
id="board-2"
onDrop=drop
onDragOver=dragOver1
style=
border: "1px solid #222",
padding: 20,
>
<div
id="secondfirst"
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<h1>Second Column First Row</h1>
</div>
<div
id="secondsecond"
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<h1>Second Column Second Row</h1>
</div>
Array.from(Array(2)).map((c, index) =>
return (
<div
key=index
id=`second$index`
draggable
onDragStart=dragStart
onDragOver=dragOver
>
<h1> Second Column Row index </h1>
</div>
);
)
</div>
</div>
);
;
ReactDOM.render(<App />, document.getElementById("app"));
</script>
【讨论】:
@Grand Whiz,看看这个!!以上是关于如何在reactjs中的div之间拖放?的主要内容,如果未能解决你的问题,请参考以下文章
reactjs - 如何隐藏一个div并将其替换为reactjs中的另一个div?
ReactJS + React Router:如何使 div 居中?