首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用自定义拖动层的react-dnd可排序列表

使用自定义拖动层的react-dnd可排序列表
EN

Stack Overflow用户
提问于 2020-04-06 12:23:45
回答 2查看 2.6K关注 0票数 2

我已经用react-dnd创建了一个简单的可排序列表,使用的代码类似于codesandbox中的react-dnd的可排序示例。

但是,我在尝试概念化如何调整此示例并利用react-dnd的custom drag layer来自定义拖动预览时遇到了一些困难。具体地说,我希望在开始拖动组件时更改组件的背景色。不要太复杂。

为什么我需要使用一个自定义的拖动层?因为由于浏览器API和react-dnd的HTML5后端的限制,我不能使用CSS设置拖动预览的样式(这就是我正在使用的)。

我在可排序列表中找不到任何使用自定义拖动层的示例,因此如果有任何帮助,我将不胜感激。

EN

回答 2

Stack Overflow用户

发布于 2021-10-27 07:14:51

我最近确实遇到了同样的问题,我不得不同意这一点的文档并不存在,这给了我相当多的悲痛来弄清楚事情。

Create CustomDragLayer

我已经使用了这个example (它工作得很好,当您刚接触这个库时,它就有点让人应接不暇了),并创建了一个简单的CustomDragLayer组件:

代码语言:javascript
复制
import { DragLayerMonitor, useDragLayer } from 'react-dnd'

const CustomDragLayer: React.FC = () => {  
    
    const {isDragging, currentOffset, item} = useDragLayer(
        (monitor: DragLayerMonitor) => {
            return {
                isDragging: monitor.isDragging(),
                currentOffset: monitor.getSourceClientOffset(),
                item: monitor.getItem()
            };
        }
    );

    return isDragging && currentOffset
        ? <div style={{ 
              // functional
              transform: `translate(${currentOffset.x}px, ${currentOffset.y}px)`,
              position: 'fixed',
              top: 0,
              left: 0,
              pointerEvents: 'none', 
        
              // design only
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              width: '150px',
              height: '50px',
              border: '1px solid red',
              color: 'red'
          }}>
              Dragging {item.id}
          </div> 
        : null;
};

export default CustomDragLayer;

它期望被拖动的项有一个名为id的属性(在它显示时)。大多数样式属性并不重要,您需要确保设置了transformpositiontopleft

坐标对于窗口是绝对的,因此position: fixed使工作变得更容易,否则可能需要一些额外的计算。

由于这个issue,你必须添加pointerEvents: 'none',否则在火狐中的悬停/拖放检测不能正常工作,我也注意到Chrome中的一些奇怪的行为(无法在带有点击处理程序的元素上拖动项目)。添加此属性似乎可以解决这些问题。

隐藏原始元素

现在,您已经渲染了自定义的拖动元素,但是,原始的源元素也是可见的,并随鼠标移动。这使得这种体验变得相当丑陋。在这里,我采用了example的方法,向我的Draggable对象添加了一个没有依赖项的useEffect钩子(在类组件中使用componentDidMount ),该对象利用了来自html5后端的一个空图像呈现函数,并隐藏了原始预览。

我决定做的最后一件事是在被拖动时隐藏源项目。我使用visibility风格的属性,它保留了dom中的原始位置,并使其看起来像项目实际上正在被移动。这也取决于上下文,您可能决定以不同的方式处理它。

以下是Draggable代码摘录:

代码语言:javascript
复制
import { getEmptyImage } from 'react-dnd-html5-backend';

const Draggable: React.FC = () => {

    // ...

    const [{ isDragging }, drag, dragPreview] = useDrag(() => ({
        // ...
    }));

    useEffect(() => {
        dragPreview(getEmptyImage())
    }, []);

    return <div ref={drag} style={{ visibility: isDragging ? 'hidden' : 'inherit'}}>
        {/* your draggable content here*/}
    </div>;
};
export default Draggable;

将CustomDragLayer添加到dom

最后,一旦你拥有了所有这些,你需要在dnd根组件的dom树中的某个地方挂载你的定制的拖动元素。

代码语言:javascript
复制
return <div ref={drop}>
    <Draggable ref={drag} />
    <CustomDragLayer />
</div>

希望这有助于理解它是如何在基础上工作的。

票数 3
EN

Stack Overflow用户

发布于 2020-04-06 16:05:54

你可以在Card上悬停时添加css。不确定这是你需要的.

代码语言:javascript
复制
import Radium from "radium";
import "./style.css";
const style = {
  border: "1px dashed gray",
  padding: "0.5rem 1rem",
  marginBottom: ".5rem",
  backgroundColor: "white",
  cursor: "move",
  ":hover": {
    background: "purple"
  }
};
export default Radium(Card);

检查此处CodeSandBox

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61052932

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档