我用的是react-beautiful- nd。我让它工作,除了当我拖拽一个项目到我的一个列表,项目定位不正确,有一个短暂的延迟,然后跳转到正确的位置。
链接到issue可以看到,在列表中放入项目后,该项目会重新调整自己以适应div。
下面是该项目的代码:
import React, { useState } from "react";
import styled from "styled-components";
import { Draggable } from "react-beautiful-dnd";
const Container = styled.div`
margin: 0 0 8px 0;
background-color: rgba(140, 240, 255);
`;
const Title = styled.div`
font-size: 1.5rem;
`;
const Gradient = styled.div`
background: black;
height: 2px;
margin: 0.5rem;
`;
const Description = styled.div`
font-size: 1rem;
`;
const Ticket = ({ ticket, setCategories, id, index }) => {
const [isDeleted, setIsDeleted] = useState(false);
const handleDelete = (e) => {
e.preventDefault();
fetch(`/tickets/${ticket.id}`, {
method: "DELETE",
}).then(
fetch("/categories")
.then((r) => r.json())
.then(setCategories)
);
setIsDeleted(true);
};
return (
<Draggable draggableId={id.toString()} index={index}>
{(provided, snapshot) =>
isDeleted ? null : (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<Container
style={{
backgroundColor: snapshot.isDragging
? "aquamarine"
: "rgba(140, 240, 255)",
}}
>
<Title>{ticket.title}</Title>
<Gradient></Gradient>
<Description>{ticket.description}</Description>
<button onClick={handleDelete}>Delete</button>
</Container>
</div>
)
}
</Draggable>
);
};
export default Ticket;
下面是列表:
import React, { useState } from "react";
import styled from "styled-components";
import Ticket from "./Ticket";
import { Droppable } from "react-beautiful-dnd";
import { transformData } from "./Categories";
const Container = styled.div`
background-color: rgba(255, 255, 255, 0.8);
border-radius: 0.25em;
box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.25);
text-align: center;
width: 20rem;
font-size: 1.5rem;
padding: 4px;
margin: 1rem;
`;
const Gradient = styled.div`
background: black;
height: 2px;
margin: 1rem;
`;
const FormContainer = styled.div`
margin: 1rem;
border: 1px solid black;
backgroundColor: rgba(140, 240, 255);
`;
const Button = styled.button`
margin-left: 1rem;
`;
const DropDiv = styled.div`
min-height: 50vh;
padding: 4px;
`;
const Category = ({ category, user, setCategories, id }) => {
const [isClicked, setIsClicked] = useState(false);
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
const newTicket = {
title: title,
description: description,
user_id: user.id,
category_id: id,
};
fetch("/tickets", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newTicket),
}).then(
fetch("/categories")
.then((r) => r.json())
.then(transformData)
.then(setCategories)
);
setIsClicked(false);
};
return (
<Container>
{category.title}
<Button onClick={() => setIsClicked(!isClicked)}>Add</Button>
<Gradient></Gradient>
{isClicked ? (
<FormContainer>
<form onSubmit={handleSubmit}>
<label>Title</label>
<input onChange={(e) => setTitle(e.target.value)}></input>
<label>Description</label>
<input onChange={(e) => setDescription(e.target.value)}></input>
<button type="submit">Submit</button>
</form>
</FormContainer>
) : null}
<Droppable droppableId={id.toString()}>
{(provided, snapshot) => (
<DropDiv
{...provided.droppableProps}
ref={provided.innerRef}
style={{
background: snapshot.isDraggingOver ? "lightblue" : "",
}}
>
{category.tickets.map((ticket, index) => {
return (
<Ticket
ticket={ticket}
key={ticket.id}
setCategories={setCategories}
id={ticket.id}
index={index}
/>
);
})}
{provided.placeholder}
</DropDiv>
)}
</Droppable>
</Container>
);
};
export default Category;
我尝试了flexbox样式和混乱的边距和填充。如果我去掉边距和填充,它似乎就消失了,但在漂亮的例子中,它们都有项目之间的空间,没有像这样的延迟。有人有什么想法吗?
看起来占位符可能没有其他可拖放项所具有的8px底边距。
你会注意到,当你从列表末尾以外的地方拿起某样东西(不改变它的位置)时,列表会立即上移一点,而当你在列表末尾放下某样东西时,你看不到这个问题。
占位符从被拖动的项中获取其外边距。你可以通过查看占位符元素的内联样式来看到这种情况,当你拖动时,占位符元素出现在可拉件的末尾。
所以,你可能想尝试把提供的innerRef, draggableProps,和dragHandleProps放在票券容器本身,而不是父div,因为这是可能的,因为他们是在不同的元素,react- beautifulnd不考虑边距
延迟可能是因为您的列表在拖动元素时改变了大小,这会导致库重新计算并减慢动画速度。
解决方案是在拖动时避免这种大小变化。
问题的原因可能是:
----原因一----
在DOM中插入的{provided.placeholder}
在拖动时没有与其他可拖动元素相同的边距/内边距
解决方案/strong>确保添加分隔元素的样式(margin/padding)到你应用提供的元素innerRef, draggableProps和dragHandleProps,因为这样{provided.placeholder}
将继承这些样式。
----原因B ----
您正在使用flexbox
或css-grid
与gap
属性来分离元素。
解决方案/strong>停止使用gap
,只需将margin
添加到提供innerRef, draggableProps和dragHandleProps的元素(不要使用内联样式,而是css类)
Extra:确认尺寸变化是原因
从列表末尾以外的地方拖动一些元素,注意另一个元素是如何上移的。同样,当你在列表的末尾放一些东西时,你不会发现问题。
我也有同样的问题-但正如在文档中看到的,内联样式与提供的道具为我做了这个技巧:
const ListItem = ({ item, index }) => {
return (
<Draggable draggableId={item.id} className="draggableItem" index={index}>
{(provided, snapshot) => {
return (
<div
ref={provided.innerRef}
snapshot={snapshot}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
userSelect: "none",
padding: 12,
margin: "0 0 8px 0",
minHeight: "50px",
borderRadius: "4px",
backgroundColor: snapshot.isDragging
? "rgb(247, 247, 247)"
: "#fff",
...provided.draggableProps.style,
}}
>
<div className="cardHeader">Header</div>
<span>Content</span>
<div className="cardFooter">
<span>{item.content}</span>
<div className="author">
{item.id}
<img className="avatar" />
</div>
</div>
</div>
);
}}
</Draggable>
);
};