Javascript 拖动';n';放下Div返回到新的最终位置
我正在尝试创建一个拖放,在这里我可以将项目移动到列表上的不同位置,它将实时更新列表,因此,如果在下面的示例中,我将内容为Javascript 拖动';n';放下Div返回到新的最终位置,javascript,html,css,reactjs,Javascript,Html,Css,Reactjs,我正在尝试创建一个拖放,在这里我可以将项目移动到列表上的不同位置,它将实时更新列表,因此,如果在下面的示例中,我将内容为1的div移动到内容为3的div,则div 2和3将向上移动,内容为1的div将位于第三个位置。到目前为止没有问题,我可以把它放在那里,一切都是正确的。 当我不放下并将div移动到一个不可放下的区域并让它离开时,问题就出现了,在这种情况下,它将返回到我第一次从第一个位置将其拖出的原始位置,但是,我希望它返回到3以前所在的新位置 示例代码: 开始拖动1: 将鼠标悬停在3上,是什
1
的div移动到内容为3
的div,则div 2和3将向上移动,内容为1的div将位于第三个位置。到目前为止没有问题,我可以把它放在那里,一切都是正确的。
当我不放下并将div移动到一个不可放下的区域并让它离开时,问题就出现了,在这种情况下,它将返回到我第一次从第一个位置将其拖出的原始位置,但是,我希望它返回到3以前所在的新位置
示例代码:
开始拖动1:
将鼠标悬停在3上,是什么让1取代了它
不停止拖动,向外移动并放下
我想让带有1的div返回到它在gree线后面的新位置,相反,它在红色线后面返回到它原来的位置
我的代码仅供参考
import React, { useState } from "react";
import "./App.css";
const initList = [1, 2, 3, 4, 5, 6, 7, 8, 9];
function App() {
const [list, setList] = useState(initList);
const [draggedItem, setDraggedItem] = useState(null);
function onDragStartHandle(e, index) {
setDraggedItem(list[index]);
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("text/html", e.target.parentNode);
e.dataTransfer.setDragImage(e.target.parentNode, 20, 22);
}
function onDragOverHandle(e, index) {
e.preventDefault();
const draggedOverItem = list[index];
if (draggedOverItem === draggedItem) {
return;
}
const items = list.filter((item) => item !== draggedItem);
items.splice(index, 0, draggedItem);
setList(items);
}
return (
<div className="App">
<header className="App-header">
<h3>Drag'n'Drop</h3>
<ul>
{list.map((item, index) => (
<li
key={index}
onDragOver={(e) => onDragOverHandle(e, index)}
className="item-style"
>
<div draggable onDragStart={(e) => onDragStartHandle(e, index)}>
{item}
</div>
</li>
))}
</ul>
</header>
</div>
);
}
export default App;
import React,{useState}来自“React”;
导入“/App.css”;
常量initList=[1,2,3,4,5,6,7,8,9];
函数App(){
const[list,setList]=useState(initList);
常量[draggedItem,setDraggedItem]=useState(null);
函数onDragStartHandle(e,索引){
setDraggedItem(列表[索引]);
e、 dataTransfer.effectAllowed=“移动”;
e、 dataTransfer.setData(“text/html”,例如target.parentNode);
e、 dataTransfer.setDragImage(e.target.parentNode,20,22);
}
函数onDragOverHandle(e,索引){
e、 预防默认值();
const draggedOverItem=列表[索引];
if(DRAGEDOVERITEM==DRAGEDITEM){
返回;
}
const items=list.filter((item)=>item!==draggedItem);
项目.拼接(索引,0,draggedItem);
设置列表(项目);
}
返回(
拖放
{list.map((项目,索引)=>(
- onDragOverHandle(e,索引)}
className=“项目样式”
>
onDragStartHandle(e,索引)}>
{item}
))}
);
}
导出默认应用程序;
好的,我花了一段时间才真正了解这一点,我能想到的最好办法是当你拖动一个元素并更新状态时,但是如果用户放弃拖放,该元素将“捕捉”回它的来源,而不是它悬停的最后一个位置。我花了一些时间研究了这个问题,但并没有什么能真正改变这种行为
我认为技术上更正确的行为是放弃拖放,即用户不在列表中拖放元素,是让列表保持它在拖动开始之前的状态
这里有一个解决方案,它添加了一个额外的状态片段,以便在拖动事件期间发生变化,如果拖放成功,则该临时状态将被提交到“真实”列表状态,如果不成功,则恢复到现有列表状态(只是保持不变)
import React,{useState}来自“React”;
导入“/App.css”;
常量initList=[1,2,3,4,5,6,7,8,9];
函数App(){
const[list,setList]=useState(initList);
const[dragList,setDragList]=useState(null);
常量[draggedItem,setDraggedItem]=useState(null);
/**
*拖动启动
*初始化要拖动的临时项并拖动列表。
*/
const onDragStartHandle=index=>e=>{
setDraggedItem(列表[索引]);
setDragList(列表);
e、 dataTransfer.effectAllowed=“移动”;
e、 dataTransfer.setData(“text/html”,例如target.parentNode);
e、 dataTransfer.setDragImage(e.target.parentNode,20,22);
};
/**
*在拖动端
*保存更新的拖动列表以列出临时值并使其为空。
*/
常量onDragEndHandle=e=>{
e、 预防默认值();
设置列表(dragList);
setDragList(空);
setDraggedItem(空);
};
/**
*左撇子
*项目未被删除,因此重置临时拖动列表
*/
const ondraglievehandle=e=>{
e、 预防默认值();
setDragList(列表);
};
/**
*拖过
*如果拖动到另一项上,请使用新位置更新拖动列表
*/
const ondragornandle=index=>e=>{
e、 预防默认值();
常数draggedOverItem=dragList[index];
if(DRAGEDOVERITEM==DRAGEDITEM){
返回;
}
const items=dragList.filter(item=>item!==draggedItem);
项目.拼接(索引,0,draggedItem);
setDragList(项目);
};
返回(
拖放
{(draggedItem?dragList:list).map((项,索引)=>(
-
{item}
))}
);
}
导出默认应用程序;
*从li
元素移动到div
,以保留来自同一元素的所有事件。将onDragOver
事件侦听器放在列表项上会导致一个奇怪的问题,有时UI会“卡住”在半悬停状态
好的,我花了一段时间才真正了解这一点,我能想到的最好办法是当你拖动一个元素并更新状态时,但是如果用户放弃拖放,该元素将“捕捉”回它原来的位置,而不是它悬停的最后一个位置。我花了一些时间研究了这个问题,但并没有什么能真正改变这种行为 我认为技术上更正确的行为是放弃拖放,即用户不在列表中拖放元素,是让列表保持它在拖动开始之前的状态 这里有一个解决方案,它添加了一个额外的状态片段,以便在拖动过程中进行变异
import React, { useState } from "react";
import "./App.css";
const initList = [1, 2, 3, 4, 5, 6, 7, 8, 9];
function App() {
const [list, setList] = useState(initList);
const [dragList, setDragList] = useState(null);
const [draggedItem, setDraggedItem] = useState(null);
/**
* On drag start
* Initialize the temporary item being dragged and drag list.
*/
const onDragStartHandle = index => e => {
setDraggedItem(list[index]);
setDragList(list);
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("text/html", e.target.parentNode);
e.dataTransfer.setDragImage(e.target.parentNode, 20, 22);
};
/**
* On drag end
* Save updated drag list to list and nullify temporary values.
*/
const onDragEndHandle = e => {
e.preventDefault();
setList(dragList);
setDragList(null);
setDraggedItem(null);
};
/**
* On drag leave
* Item wasn't dropped so reset temporary drag list
*/
const onDragLeaveHandle = e => {
e.preventDefault();
setDragList(list);
};
/**
* On drag over
* If dragging over another item update the drag list with new position
*/
const onDragOverHandle = index => e => {
e.preventDefault();
const draggedOverItem = dragList[index];
if (draggedOverItem === draggedItem) {
return;
}
const items = dragList.filter(item => item !== draggedItem);
items.splice(index, 0, draggedItem);
setDragList(items);
};
return (
<div className="App">
<header className="App-header">
<h3>Drag'n'Drop</h3>
<ul>
{(draggedItem ? dragList : list).map((item, index) => (
<li key={index} className="item-style">
<div
draggable
onDragOver={onDragOverHandle(index)} // Moved *
onDragLeave={onDragLeaveHandle}
onDragEnd={onDragEndHandle}
onDragStart={onDragStartHandle(index)}
>
{item}
</div>
</li>
))}
</ul>
</header>
</div>
);
}
export default App;