React 拖拽辅助库选型求推荐? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
WangLiCha
V2EX    React

React 拖拽辅助库选型求推荐?

  •  
  •   WangLiCha 2024-01-16 02:22:23 +08:00 4271 次点击
    这是一个创建于 681 天前的主题,其中的信息可能已经有所发展或是发生改变。

    先说下实际的场景需求,是 flex 布局下允许换行的不定长短的标签列表(类似 V2EX 首页最下面的节点导航),要求可以通过拖拽进行排序,可以从外部拖拽元素添加到指定的位置(这个“外部”可能是自己定义的 React 元素或者 Ant Design 的 Tree 组件的一个节点,不过节点这个不强求)。同时只有特定的排序或者插入的顺序是允许的,不能允许用户插入或者交换到不合法的位置(比如说所有的标签都是英文单词,然后规定是所有首字母相同的单词必须是互相挨在一起的)。同时每个标签自己还有自己的点击事件,拖拽功能不能和点击事件冲突。

    调研过了几个可能比较流行的拖拽库,dnd-kit, react-beautiful-dnd, react-sortable-hoc, react-dnd 。前面三个都是封装的很好比较易用也很好看的库,但是同时存在的问题是他们要么仅支持单列列表的拖拽排序,要么可以支持多行但是仅限大小相同的网格。react-dnd 相比之下最抽象也最底层,只做了逻辑上的辅助,所有的 UI 效果要自己来。他的官方文档上有一个例子可以粗浅的实现我希望的效果,通过判断一个元素是否拖拽到另一个元素上来判断,理论上可以兼容任何布局,但是实际操作起来灵活性很差,在判定点边界的时候很容易反复判定拖拽到不同的元素上从而反复鬼畜。用起来感觉实际用户体验也远不如前面三个。

    所以还有什么适合我这个需求的 React 辅助拖拽库吗?还是这个需求太奇葩了只能在 react-dnd 的基础上自己想想办法?

    12 条回复    2024-01-18 21:18:16 +08:00
    kingofzihua
        1
    kingofzihua  
       2024-01-16 08:31:32 +08:00
    leokun
        2
    leokun  
       2024-01-16 08:50:24 +08:00
    一直用 https://interactjs.io/
    api 很优美
    woodytang
        3
    woodytang  
       2024-01-16 08:52:59 +08:00
    需要花时间深入研究原理,没有开箱即用方案,最近在做 把网页 变成图片,截取全网页,没想到这个简单的需求,要实现完善的功能 和 稳定的服务,,都要花很多功夫
    vizards
        4
    vizards  
       2024-01-16 09:16:31 +08:00 via iPhone   1
    你的要求 dnd-kit 都可以满足
    1. 跨容器拖拽排序官方有 examples ,其实就是定义多个 container ,共享 draggable element ,如果需要的是从源容器复制的效果,则需要源容器内的 draggable element 在被 drop 后重新渲染(通过修改 key 或 id ),这样被拖走后他会在原地重新生成一个,或在拖拽开始/拖到可放置区域时重新生成一个新的 key 以破坏和源容器中的元素的对应关系

    2. 限制特定交换顺序:真正的交换是否成功 是看渲染的结果,也就是说 dnd-kit 在拖拽完成的事件里你是否调用 arraymove 等帮助方法让列表数据改变,如果没有改变,那么拖拽就没有成功,列表顺序也不变

    3. 每个标签有点击事件:可以通过 sensors 实现只监听某些地方的 pointer 事件,也可以通过监听 onPointerDown 事件来变相监听 onClick ,通过监听延迟来确定是移动还是点击(因为开启了 pointerSensor 后无法监听到 onClick )

    4. flex 不定宽排序:官网有例子,至于拖拽时可能的变形问题,可以通过动态渲染一个 drop item placeholder 实现,即保存一个自定义的 dragoverlay 数据,在元素可以被放置到某个位置但元素还处在被用户鼠标抓住时,插入此 dragoverlay 对应的元素到预测的位置,展现为一个半透明的占位,可以保证布局不变形

    我目前遇到的 dnd-kit 较难做到的是多列瀑布流布局下的自由拖拽,拖拽可以实现,但是很难保证容器内不变形
    nzbin
        5
    nzbin  
       2024-01-16 09:32:12 +08:00
    推荐 react-dnd ,我这有个 ng-dnd ( https://github.com/ng-dnd/ng-dnd ,借鉴 react-dnd ,代码可以互转) 实现的例子 https://stackblitz.com/edit/867pxw?file=src%2Fexample%2Fdrag-drop.directive.ts ,你看看是不是你想要的效果

    这个效果只是多加了个指令,然后附加到任意元素上,感觉可以借鉴一下思路
    realJamespond
        6
    realJamespond  
       2024-01-16 09:46:10 +08:00
    https://github.com/haltu/muuri
    之前找了一遍,可变列宽好像只有这个
    WangLiCha
        7
    WangLiCha  
    OP
       2024-01-16 09:53:32 +08:00
    @vizards dnd-kit 官方的不定宽排序的例子不是也是基于 Grid 的吗?还是长款都是整倍数关系在网格里排列的
    WangLiCha
        8
    WangLiCha  
    OP
       2024-01-16 09:55:46 +08:00
    @nzbin 其实我自己用 react-dnd 已经能做到非常接近的效果了,但是我提到那个问题还是存在,拖拽到另一个标签的边缘位置的时候还是会因为反复判定到不同的标签上从而开始疯狂闪烁……
    swaggeek
        9
    swaggeek  
       2024-01-16 09:57:15 +08:00
    https://github.com/SortableJS/Sortable 这个可以?虽然体积有点大,但是我们用的这个
    vizards
        10
    vizards  
       2024-01-16 10:01:02 +08:00 via iPhone
    @WangLiCha 实际上如果是单纯的 flex 布局(即使包含 wrap )直接 flex 排就可以了,拖拽也可以正常工作,只不过由于不定宽高,要自己处理动画变形问题
    crazyweeds
        11
    crazyweeds  
       2024-01-16 10:08:34 +08:00
    你要不看看我网站?只不过,自由度非常高导致你开发成本可能就上去了。我用这个,你可以完全自己掌控。

    hutubox.com
    WangLiCha
        12
    WangLiCha  
    OP
       2024-01-18 21:18:16 +08:00
    @vizards 回过头来补充一下,感谢推荐 dnd-kit ,但是我最后还是选用 react-dnd 成功实现效果了。我这边需求不需要有动画效果,但是从外部拖拽尤其是从 Ant Design 的 Tree 组件节点拖拽还是 react-dnd 做起来相当简单省心
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3553 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 00:47 PVG 08:47 LAX 16:47 JFK 19:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86