React DnD如何处理拖拽详解

yizhihongxing

React DnD是封装的HTML5拖放API的React组件,可用于构建拖放交互功能。下面详细讲解React DnD如何处理拖拽,在这个过程中,将提供两个示例说明。

1. 拖拽源

拖拽源是可以被拖拽的组件。在React DnD中,拖拽源分为两种:简单的拖拽源和自定义拖拽源。

简单拖拽源

简单的拖拽源指的是一个纯组件,该组件可以设置可以被拖拽的数据类型以及数据。

import { useDrag } from 'react-dnd'

export default function SimpleDragSource() {
  const [{ isDragging }, drag] = useDrag({
    item: { type: 'BOX', text: 'This is a simple drag source' },
    collect: monitor => ({
      isDragging: monitor.isDragging()
    })
  })

  const opacity = isDragging ? 0.4 : 1
  return (
    <div ref={drag} style={{ opacity }}>
      Simple Drag Source
    </div>
  )
}

上面的代码展示了一个简单的拖拽源,它被设置为可以拖拽typeBOX,数据为text: 'This is a simple drag source'。在渲染组件时,要使用useDraghook。useDraghook接受一个配置对象,包含itemcollect属性。item属性指定了拖拽源能够拖拽的数据类型及其数据。collect属性场景的monitor对像,这个对象包含此拖动源内部状态以及DnD状态,这个对象的isDragging()方法可以判断当前组件是否处于拖动状态。

在组件渲染时需要将dragref通过组件绑定。当我们通过useDraghook生成的ref函数传递给组件后,将会自动添加拖拽起始事件监听。渲染视图时我们还需要根据动态改变拖拽表现的状态和数据来改变样式或内容。在这个例子种我们通过opacity属性来改变组件在拖拽状态下的透明度。

自定义拖拽源

由于简单的拖拽源只能提供基本的拖拽信息,不能满足对复杂情况的应用,React DnD还提供了一种自定义拖拽源的方式。

import React, { useState } from "react";
import { useDrag } from "react-dnd";
import { ItemTypes } from "./ItemTypes";

const style = {
  border: "1px dashed gray",
  padding: "0.5rem 1rem",
  backgroundColor: "white",
  cursor: "move"
};

export const Box = ({ id, left, top, hideSourceOnDrag, children }) => {
  const [{ isDragging }, drag] = useDrag({
    item: { type: ItemTypes.BOX, id, left, top },
    collect: monitor => ({
      isDragging: monitor.isDragging()
    })
  });
  const [isHidden, setIsHidden] = useState(false);

  if (isDragging && hideSourceOnDrag) {
    setIsHidden(true);
  }

  return (
    <div
      ref={drag}
      style={{ ...style, opacity: isDragging ? 0.5 : 1, display: isHidden ? "none" : "block" }}
    >
      {children}
    </div>
  );
};

上面的代码是一个自定义的拖拽源的示例,由Box组件创建。组件可以接受idlefttophideSourceOnDragchildren作为参数。在useDraghook中指定数据类型为ItemTypes.BOX,组件的lefttop作为初始位置进行设置。在collect属性中通过isDragging方法设置组件是否处于拖拽状态的内部变量isDraggingchildren是组件要显示的文字。

当我们拖动这个Box组件时,将会执行useDraghook,并通过dragref将事件绑定到了组件上。我们在style中通过opacity属性来改变被拖拽组件的透明度;在display中,我们将组件隐藏以避免在拖拽时影响其他组件。如果不需要影藏组件,可以将hideSourceOnDrag设置为`false´。

2. 放置目标

放置目标是接收可以拖拽的组件的组件。在React DnD中,放置目标也需要分为简单的放置目标和自定义放置目标。

简单放置目标

简单放置目标是指只能接收特定数据类型的拖拽源。在下面这个例子中,我们有一个简单的放置目标,它只能接收typeBOX的拖拽源。

import { useDrop } from 'react-dnd'

export default function SimpleDropTarget() {
  const [{ isOver }, drop] = useDrop({
    accept: 'BOX',
    collect: monitor => ({
      isOver: monitor.isOver()
    })
  })

  const backgroundColor = isOver ? 'lightgreen' : 'white'
  return (
    <div ref={drop} style={{ backgroundColor }}>
      {isOver ? 'Release to drop' : 'Drag a box here'}
    </div>
  )
}

在渲染该组件后,使用useDrophook并传递一个配置对象。accept属性接收一个数据类型的数组,并在所有拖拽源中查找typeBOX的拖拽源。在配置对象中,使用collect方法将isOver状态传递到渲染函数中。当拖拽源经过组件时,isOver属性将设置为true,移出时则恢复。

在渲染的div中,使用我们的dropref将事件处理程序绑定到组件上。在组件渲染时,调整其样式来反映拖拽源是否可以被接收的状态。

自定义放置目标

自定义放置目标可以接受任何类型的拖拽源。在下面这个例子中,我们有一个自定义的放置目标,它可以接受任何类型的拖拽源。

import React, { useState } from "react";
import { useDrop } from "react-dnd";
import { ItemTypes } from "./ItemTypes";

const style = {
  height: "12rem",
  width: "12rem",
  margin: "1rem",
  border: "1px solid black",
  position: "relative"
};

export const Dustbin = ({ onDrop }) => {
  const [hasDropped, setHasDropped] = useState(false);
  const [{ isOver, canDrop }, drop] = useDrop({
    accept: ItemTypes.BOX,
    drop: () => {
      setHasDropped(true);
      onDrop();
    },
    collect: monitor => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop()
    })
  });

  const isActive = isOver && canDrop;

  let backgroundColor = "#222";

  if (isActive) {
    backgroundColor = "darkgreen";
  } else if (canDrop) {
    backgroundColor = "darkkhaki";
  }

  return (
    <div ref={drop} style={{ ...style, backgroundColor }}>
      {hasDropped ? (
        <p>Box has been dropped!</p>
      ) : (
        <p>Drag a box here.</p>
      )}
    </div>
  );
};

我们使用了useDrophook创建了一个自定义放置目标组件。在useDrophook中,我们指定了可以接收的数据类型为ItemTypes.BOX。我们还将drop回调传递到了dropref中。当一个拖拽源被放置时,如果它是有效的拖拽源类型,我们将hasDropped状态设置为true

collect属性中,我们可以使用isOvercanDrop方法将数据传递到组件中。我们可以使用isActive变量计算放置目标当前是否处于拖拽源悬停状态。

在渲染的组件中,我们展示一个提示信息,根据当前状态调整其样式。当拖拽源被放置到放置目标中时,将会调用onDrop回调函数。可以在这里处理放置后的操作。

这就是React DnD如何处理拖拽的详解,在这个过程中我们已经提供了两个示例说明来帮助您理解。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:React DnD如何处理拖拽详解 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • 八个一看就觉得很棒的Vue开发技巧分享

    来讲解一下“八个一看就觉得很棒的Vue开发技巧分享”的完整攻略。 八个一看就觉得很棒的Vue开发技巧分享 1. 用组件名前缀 在构建大型的应用程序过程中,可能会有许多个不同的组件文件。为了使组件更易于管理和组织,我们可以通过组件名前缀来对它们进行分类。例如,所有的表格组件都以table-作为前缀,所有的表单组件都以form-作为前缀。这样做可以避免组件命名冲…

    Vue 2023年5月27日
    00
  • vue中ref引用操作DOM元素的实现

    在Vue.js中,可以通过ref指令来获取DOM元素的引用,这使得我们可以在Vue组件中直接操作DOM元素。下面是实现这一功能的步骤。 步骤一:在DOM元素上添加ref指令 要获取一个DOM元素的引用,我们需要给它添加ref指令并指定一个名称。ref指令可以添加在任何元素上,如下所示: <template> <div> <but…

    Vue 2023年5月29日
    00
  • vue3中reactive数据被重新赋值后无法双向绑定的解决

    在Vue3中,数据响应式的实现由Vue2中的Object.defineProperty改为了ES6的Proxy,使得Vue3的响应式系统在性能和功能上都有了提升。但是,在Vue3中,当我们直接给响应式对象中的属性进行重新赋值时,这个属性就会脱离响应式系统,从而失去了双向绑定的功能,即无法自动更新页面。下面给出两个示例,分别说明这个问题的存在及解决方式。 问题…

    Vue 2023年5月27日
    00
  • 深入理解Vue父子组件生命周期执行顺序及钩子函数

    下面是“深入理解Vue父子组件生命周期执行顺序及钩子函数”的完整攻略: 什么是Vue组件生命周期? Vue组件是Vue.js中最重要的概念之一。一个Vue组件可以看作是一个拥有预定义选项的Vue实例。与Vue实例一样,Vue组件也有它们自己的生命周期。Vue组件的生命周期包括创建、挂载、更新和销毁四个阶段。 为了更好地理解Vue组件生命周期,我们需要明确每个…

    Vue 2023年5月28日
    00
  • vue 使用vue-i18n做全局中英文切换的方法

    下面我就来详细讲解“vue 使用vue-i18n做全局中英文切换的方法”的完整攻略。 1. 准备工作 首先,需要在Vue项目中安装vue-i18n模块,可以通过npm命令行工具来安装。在终端中输入以下命令: npm install vue-i18n –save 安装成功后,将在项目的node_modules文件夹中看到vue-i18n的相关文件。 2. 配…

    Vue 2023年5月29日
    00
  • 关于vue3中setup函数的使用

    下面开始讲解关于Vue3中setup函数的使用的完整攻略。 一、什么是setup函数 setup是Vue3中引入的全新选项,它是组件实例化之前最先执行的一个函数。Vue3中设计setup函数的目的是要取代Vue2中的data、created、beforeCreate三个选项,将它们的功能都整合在setup函数中。新的API可以更好地应对TS等类型化语言的需求…

    Vue 2023年5月28日
    00
  • vue 标签属性数据绑定和拼接的实现方法

    Vue是一个对视图层进行响应式处理的前端框架,其中最常用的功能就是标签属性数据绑定和拼接。下面将提供Vue标签属性数据绑定和拼接的实现方法。 Vue标签属性数据绑定的实现方法 在Vue中,绑定数据到HTML标签属性中非常容易,使用“v-bind”指令就可以了。下面是代码示例: <img v-bind:src="imgUrl">…

    Vue 2023年5月27日
    00
  • 详解vue+axios给开发环境和生产环境配置不同的接口地址

    为了给开发环境和生产环境配置不同的接口地址,我们需要依赖于webpack。我们可以通过环境变量在编译时设置接口地址,从而在不同的环境中使用不同的接口地址。 1. 修改webpack的配置文件 在项目的根目录中找到名为vue.config.js的文件,如果不存在则通过vue-cli工具生成(vue create projectName)。在该文件中添加如下代码…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部