本教程操作环境:Windows10系统、react17.0.1版、Dell G3电脑。
react-dnd怎么实现拖拽
React DnD是React和Redux核心作者 Dan Abramov创造的一组React 高阶组件,可以在保持组件分离的前提下帮助构建复杂的拖放接口。
React DnD 的需求
默认使用 HTML5 拖放API,但支持
不直接操作 DOM
DOM 和拖放的源和目标解耦
融入HTML5拖放中窃取类型匹配和数据传递的想法
React DnD 的特点
专注拖拽,不提供现成组件
React DnD提供了一组强大的原语,但它不包含任何现成组件,而是采用包裹使用者的组件并注入 props 的方式。 它比jQuery UI等更底层,专注于使拖放交互正确,而把视觉方面的效果例如坐标限制交给使用者处理。这其实是一种关注点分离的原则,例如React DnD不打算提供可排序组件,但是使用者可以基于它快速开发任何需要的自定义的可排序组件。
单向数据流
类似于 React 一样采取声明式渲染,并且像 redux 一样采用单向数据流架构,实际上内部使用了 Redux
隐藏了平台底层API的问题
HTML5拖放API充满了陷阱和浏览器的不一致。 React DnD为您内部处理它们,因此使用者可以专注于开发应用程序而不是解决浏览器问题。
可扩展可测试
React DnD默认提供了HTML5拖放API封装,但它也允许您提供自定义的“后端(backend)”。您可以根据触摸事件,鼠标事件或其他内容创建自定义DnD后端。例如,内置的模拟后端允许您测试Node环境中组件的拖放交互。
为未来做好了准备
React DnD不会导出mixins,并且对任何组件同样有效,无论它们是使用ES6类,createReactClass还是其他React框架创建的。而且API支持了ES7 装饰器。
示例如下:
1.1.使用DndProvider定义一个可以拖拽的范围
/* * @Author: muge * @Date: 2021-12-04 16:59:25 * @LastEditors: Please set LastEditors * @LastEditTime: 2021-12-08 14:24:47 */import React, { useState } from "react";import { DndProvider } from "react-dnd";import { HTML5Backend } from "react-dnd-html5-backend";import SourceBox from "./SourceBox";import TargetBox from "./TargetBox";import TreeBox from "./TreeBox";const item: any[] = [ { id: 1, name: "muge", }, { id: 2, name: "muxi", }, { id: 3, name: "mugege", },];const Container = () => { // 当前拖拽项 const [currentList, setCurrentList] = useState({}); return ( // 类似redux数据传输 需要在最外层包裹对象 );};export default Container; 拖拽源组件 列表-----树
{/* 列表拖拽源 */} {item.map((itemz: any, index: number) => ({/* 注意,不要树组件整体直接设置拖拽,抽成一个组件来遍历每一项 =》自定义渲染*/} {/* 树形拖拽源 */}))} 拖拽放置目标
{/* 拖拽最终放置组件 */}
2.使用 DragSource 包裹住组件,使其可以进行拖动
/* * @Author: muge * @Date: 2021-12-07 14:26:08 * @LastEditors: Please set LastEditors * @LastEditTime: 2021-12-08 14:18:52 */import { useDrag } from "react-dnd";const ItemTypes = { BOX: "box",};const style = { border: "1px dashed gray", backgroundColor: "white", padding: "0.5rem 1rem", marginRight: "1rem", marginBottom: "1rem", cursor: "move",};const SourceBox = ({ item, setCurrentList }: any) => { const [{ opacity }, drag] = useDrag( () => ({ type: ItemTypes.BOX, collect: (monitor) => ({ opacity: monitor.isDragging() ? 0.4 : 1, }), item: () => item, //返回当前列表项数据 canDrag: (monitor) => { //是否取消拖拽 console.log(monitor, "monitor131"); return true; }, // end(currentItem, monitor) { // monitor.getDropResult(); //获取拖拽对象所处容器的数据 // monitor.didDrop(); // 当前容器能否放置拖拽对象 拖动停止时触发 monitor.didDrop() && setCurrentList(currentItem); //在容器点松开 才赋值 }, }), [], ); return ({item.id}------{item.name});};export default SourceBox;
3.使用 DropTarget 包裹住组件,使其对拖动,悬停或 dropped 的兼容项目做出反应。
/* * @Author: muge * @Date: 2021-12-07 14:26:08 * @LastEditors: Please set LastEditors * @LastEditTime: 2021-12-08 14:33:08 */import React from "react";import { useDrop } from "react-dnd";const ItemTypes = { BOX: "box",};const style: any = { border: "1px solid gray", height: "15rem", width: "15rem", padding: "2rem", textAlign: "center",};const TargetBox = ({ currentList }: any) => { const [{ isActive, isOver, canDrop }, drop] = useDrop(() => ({ accept: ItemTypes.BOX, collect: (monitor) => ({ isActive: monitor.canDrop() && monitor.isOver(), isOver: monitor.isOver(), canDrop: monitor.canDrop(), }), // hover: (item, monitor) => { // console.log(item, "item"); // console.log(monitor, "monitor"); // }, })); // console.log(isOver, "isOver"); // console.log(canDrop, "canDrop"); return ({isActive ? "Release to drop" : "Drag item here"});};export default TargetBox;{JSON.stringify(currentList) !== "{}" ? JSON.stringify(currentList) : "当前item"}
到此列表拖拽即可完成
推荐学习:《react视频教程》
以上就是react-dnd怎么实现拖拽的详细内容,更多请关注php中文网其它相关文章!