深入解析React DnD拖拽原理,轻松掌握拖放技巧!

发布网友

我来回答

1个回答

热心网友

深入解析React DnD拖拽原理,轻松掌握拖放技巧!


业务中会有一些需要实现拖拽的场景,尤其是偏视觉方向以及移动端较多。拖拽在一定程度上能让交互更加便捷,能大大提升用户体验。以业务中心子产品配置功能为例,产品模块通过拖拽来调整顺序,的确会更加方便一些。


React DnD 是一组 React 实用程序,可帮助您构建复杂的拖放界面,同时保持组件分离。它非常适合 Trello 和 Storify 等应用程序,在应用程序的不同部分之间拖动可以传输数据,组件会根据拖放事件更改其外观和应用程序状态。React-DnD 特点包括:



安装 react-dnd, react-dnd-html5-backend
将需要拖拽的组件使用DndProvider进行包裹

看下Container组件,主要是管理数据,并渲染Card列表。


Card组件


至此一个简单的拖拽排序列表就实现了,实现的效果类似于React DnD官网的这个示例: react-dnd.github.io/rea...,接下来我们来看看实现原理。


主要代码代码目录结构


核心代码主要分三个部分:



dnd-core向backend提供数据的更新方法
backend在拖拽时更新dnd-core中的数据
dnd-core通过react-dnd更新业务组件

实现原理: dnd-core向backend提供数据的更新方法,backend在拖拽时更新dnd-core中的数据,dnd-core通过react-dnd更新业务组件。


DndProvider


先看一下源码



生成了一个manager,并将其放到DndContext.Provider中

就是使用 React 的createContext创建的上下文容器组件。


接下来看下这个manager,主要是用来控制拖拽行为,通过Provider让子节点也可以访问。我们看下创建manager的getDndContextValue方法:


getDndContextValue方法又调用了createSingletonDndContext方法,并传入了backend、context、options、debugMode这几个属性,然后通过dnd-core中的createDragDropManager来创建manager。


DragDropManager


看下createDragDropManager.js中的主要代码



使用了redux的createStore创建了store,并创建了monitor和manager实例
通过backendFactory创建backend后端实例并安装到manager总实例

DragDropManagerImpl的主要代码



handleRefCountChange方法,在构造函数里通过store进行订阅
在第一次使用useDrop或useDrag时会执行setup方法初始化backend
在拖拽源和放置源都被卸载时则会执行teardown销毁backend

createDragDropActions方法



绑定一些action

manager包含了之前生成的 monitor、store、backend,manager 创建完成,表示此时我们有了一个 store 来管理拖拽中的数据,有了 monitor 来监听数据和控制行为,能通过 manager 进行注册,可以通过 backend 将 DOM 事件转换为 action。接下来便可以注册拖拽源和放置源了。


useDrag方法返回了一个包含3个元素的数组,CollectedProps、ConnectDragSource、ConnectDragPreview



monitor是从前面Provider中的manager中获取的
主要看下connector

connector获取了manager.getBackend后端的数据。


useRegisteredDragSource方法会对拖动源进行注册,会保存拖动源实例,并记录注册的数量。


useDrop



返回了一个包含2个元素的数组,CollectedProps、ConnectDropTarget
monitor和connector的获取都和useDrag类似

HTML5Backend



使用了HTML5 拖放 API
了解下HTML拖拽事件:一个简单拖拽操作过程,会依次触发拖拽事件:dragstart -> drag -> dragenter -> dragover (-> dragleave) -> drop -> dragend。
drag事件会在dragstar触发后持续触发,直至drop
dragleave事件会在拖拽元素离开一个可释放目标时触发

HTML5Backend是React DnD 主要支持的后端,使用HTML5 拖放 API,它会截取拖动的 DOM 节点并将其用作开箱即用的“拖动预览”。React DnD 中以可插入的方式实现 HTML5 拖放支持,可以根据触摸事件、鼠标事件或其他完全不同的事件编写不同的实现,这种可插入的实现在 React DnD 中称为后端。官网提供了HTML5Backend和TouchBackend,分别用来支持web端和移动端。


后端担任与 React 的合成事件系统类似的角色:它们抽象出浏览器差异并处理原生DOM 事件。尽管有相似之处,但 React DnD 后端并不依赖于 React 或其合成事件系统。在后台,后端所做的就是将 DOM 事件转换为 React DnD 可以处理的内部 Redux 操作。


HTML5Backend 在初始化的时候在 window 对象上绑定拖拽事件的监听函数,拖拽事件触发时执行对应action,更新 store 中的数据,完成由 Dom 事件到数据的转变。


TouchBackend



HTML5 后端不支持触摸事件,因此它不适用于平板电脑和移动设备
可以使用react-dnd-touch-backend来支持触摸设备

ToucheBackend主要是为了支持移动端,也支持web端,在web端可以使用 mousedown、mousemove、mouseup,在移动端则使用 touchstart、touchmove、touchend。


React-DnD 采用了分层设计,react-dnd充当接入层,dnd-core实现拖拽接口、定义拖拽行为、管理数据流向,backend将DOM事件通过redux action转换为数据。


使用可插入的方式引入backend,使拖拽的实现可扩展且更加灵活。


使用了单向数据流,在拖拽时不用处理中间状态,不用额外对DOM事件进行处理,只需专注于数据的变化。 React-DnD对backend的实现方式、数据的管理方式,以及整体的设计都值得借鉴。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com