发布网友
共1个回答
热心网友
深入解析React DnD拖拽原理,轻松掌握拖放技巧!
业务中会有一些需要实现拖拽的场景,尤其是偏视觉方向以及移动端较多。拖拽在一定程度上能让交互更加便捷,能大大提升用户体验。以业务中心子产品配置功能为例,产品模块通过拖拽来调整顺序,的确会更加方便一些。
React DnD 是一组 React 实用程序,可帮助您构建复杂的拖放界面,同时保持组件分离。它非常适合 Trello 和 Storify 等应用程序,在应用程序的不同部分之间拖动可以传输数据,组件会根据拖放事件更改其外观和应用程序状态。React-DnD 特点包括:
看下Container组件,主要是管理数据,并渲染Card列表。
Card组件
至此一个简单的拖拽排序列表就实现了,实现的效果类似于React DnD官网的这个示例: react-dnd.github.io/rea...,接下来我们来看看实现原理。
主要代码代码目录结构
核心代码主要分三个部分:
实现原理: dnd-core向backend提供数据的更新方法,backend在拖拽时更新dnd-core中的数据,dnd-core通过react-dnd更新业务组件。
DndProvider
先看一下源码
就是使用 React 的createContext创建的上下文容器组件。
接下来看下这个manager,主要是用来控制拖拽行为,通过Provider让子节点也可以访问。我们看下创建manager的getDndContextValue方法:
getDndContextValue方法又调用了createSingletonDndContext方法,并传入了backend、context、options、debugMode这几个属性,然后通过dnd-core中的createDragDropManager来创建manager。
DragDropManager
看下createDragDropManager.js中的主要代码
DragDropManagerImpl的主要代码
createDragDropActions方法
manager包含了之前生成的 monitor、store、backend,manager 创建完成,表示此时我们有了一个 store 来管理拖拽中的数据,有了 monitor 来监听数据和控制行为,能通过 manager 进行注册,可以通过 backend 将 DOM 事件转换为 action。接下来便可以注册拖拽源和放置源了。
useDrag方法返回了一个包含3个元素的数组,CollectedProps、ConnectDragSource、ConnectDragPreview
connector获取了manager.getBackend后端的数据。
useRegisteredDragSource方法会对拖动源进行注册,会保存拖动源实例,并记录注册的数量。
useDrop
HTML5Backend
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
ToucheBackend主要是为了支持移动端,也支持web端,在web端可以使用 mousedown、mousemove、mouseup,在移动端则使用 touchstart、touchmove、touchend。
React-DnD 采用了分层设计,react-dnd充当接入层,dnd-core实现拖拽接口、定义拖拽行为、管理数据流向,backend将DOM事件通过redux action转换为数据。
使用可插入的方式引入backend,使拖拽的实现可扩展且更加灵活。
使用了单向数据流,在拖拽时不用处理中间状态,不用额外对DOM事件进行处理,只需专注于数据的变化。 React-DnD对backend的实现方式、数据的管理方式,以及整体的设计都值得借鉴。