问题描述
我正在使用 react-beautiful-dnd 使用 Material UI ListItems
制作一些可拖动的列表项。
我的 ListItems
有一个 ListItemText
和一个 ListItemSecondaryAction
,它是用于打开上下文菜单的目标(包装图标)。
const DraggableListItem = ({ leaf,index,path,handleClick }) => {
return (
<Draggable draggableId={String(leaf.id)} index={index}>
{(provided) => (
<ListItem
{...provided.draggableProps}
{...provided.dragHandleProps}
innerRef={provided.innerRef}
button component={NavLink}
to={path + '/' + leaf.id}
>
<ListItemText primary={leaf.content} />
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="more options" value={JSON.stringify(leaf)} onClick={handleClick}>
<MoreHorizIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
)}
</Draggable>
)
}
我面临的问题是,当拖动 Draggable
时,ListItemSecondaryAction
内的上下文菜单图标会向上移动一点然后冻结,尽管 ListItemText
被拖动正如预期的那样。
在下方,您可以看到该项目正被拖到列表顶部,而其他 ListItemText
正在围绕占位符重新排列自己/拖动项目将被放置的位置。然而,被拖动项目的上下文菜单图标在它以前的位置上方被冻结了一点,并且其他项目的上下文菜单图标没有移动到新位置。
只需将 ListItemSecondaryAction
替换为 div
即可解决问题,但我需要 ListItemSecondaryAction
提供的目标。
以下在拖动项目方面按预期工作:IconButton
被拖动到 Draggable 内。
<div>
<IconButton>
<MoreHorizIcon />
</IconButton>
</div>
我尝试仅在不拖动时呈现 ListItemSecondaryAction
(而不是在拖动时呈现 div
),但仍存在延迟,其中被拖动项目的上下文菜单显示卡在一个地方在很短的时间内。我也可以在拖动时根本不渲染上下文菜单的目标 + 图标,但发生了同样难看的图标卡在一个奇怪的地方,一秒钟的问题。
当 IconButton
位于 Draggable
内时,如何确保 ListItemSecondaryAction
与 {{1}} 一起拖动?
解决方法
我使用解决方案 here 的变体修复了图标问题,但我没有渲染单独的 ListItemIcon
并仍然渲染 ListItemSecondaryAction
,这改变了每个项目的布局,我发现在拖动时根本不渲染 ListItemSecondaryAction
并在没有任何 Icon
或 ListItemIcon
包装器的情况下仅渲染 IconButton
效果更好。不过,当作为 Icon
的孩子渲染时,单独的 ListItem
会更暗。自行设置图标样式以匹配辅助操作中图标的颜色后,看起来不错。
dragInProgress
是传递给父列表中所有列表项的一段状态,以便它们在拖动时仅呈现图标。 snapshot
来自 Draggable
中的函数传递的快照,如链接的问题所示。还检查 snapshot.isDragging
以避免在状态 dragInProgress
正在更新并导致项目重新呈现时被拖动项目的图标的瞬间跳跃。
<ListItem
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<ListItemText primary={item.content} />
{dragInProgress || snapshot.isDragging ?
<MoreHorizIcon style={{color:'rgba(0,0.54)'}} />
:
<ListItemSecondaryAction>
<IconButton>
<MoreHorizIcon />
</IconButton>
</ListItemSecondaryAction>
}
</ListItem>
注意:
不幸的是,不拖动时呈现的 ListItemSecondaryAction
与触摸效果不佳(在 chrome 上的 android 上测试),必须拖动两次才能开始移动项目。我可能会将这个更具体的问题放在一个单独的问题中。