React Draggable 实现拖拽

2023-11-13

React Draggable 是 react 生态中,最好用的拖拽实现库之一。如果你的应用中需要实现拖拽功能,可以尝试用 react-draggable,它可以满足多数情况下的拖拽需求,比如一个弹出设置浮窗,可以相互遮挡的容器之类。在所有 react 拖拽库里(即 react dnd, drag and drop),react-draggable 算是把功能性和易用性平衡得最好的拖拽库了。

在实现卡拉云时,我们也大量使用了 react-draggable。所以这篇文章里,我们介绍如何使用 react-draggable,一些常见的设置和我们的经验。请根据下面的代码一步步实现,最终你要实现的效果如下

如果你在参考的过程中有不确定代码应该怎么写,可以直接到代码库中找到对应的文件。本文可参考的代码放在 github 上: react-draggable代码,觉得不错的话不妨打个星。

react-draggable 简介

react-draggable 经过几年的发展,已经是一个相对比较稳定的库了。从 npm trends 上看,从 16 年起它的流行程度就迅速超过了其它几个类似的项目。它在 github 上算非常热门的项目了,使用它的项目众多,所以可以放心地使用。如果有 bug 反馈也会非常快

如果看它的源码的话,会发现它的原理其实很简单,它只是将一个需要被拖拽的组件包到它定义的一个组件中,当鼠标拖拽时,重新计算组件的位置,这样就实现了“拖拽”的效果。这也是绝大多数拖拽组件库的实现方式。

准备项目

我们按常规,使用 create-react-app 这个工具来创建项目。如果你本地没有安装 npx 的话,强烈推荐,使用非常方便。

在准备好 react 脚手架后,你就可以到目录里,把项目跑起来。

执行 npm start。这时候应该看到一个熟悉的画面

当然如果你是在已有项目里准备加上 react-draggable,那么跳过本步,直接执行下一步安装就好了。

安装 react-draggable

现在执行 npm install react-draggable,执行完后应该在你的 node_modules 中就装好了 react-draggable。

新建一个盒子组件

我们先在 App.js 文件中加上几个简单的结构,比如一个框用来表示需要拖拽的组件,同时在框上加上一个拖拽把手,这样方便用户识别。

在 App.js 中加上一个叫 Box 的组件先占位,如下

import './App.css';

const Box = () => {
  return <>hello world</>
}

function App() {
  return (
    <div className="App">
        <Box></Box>
    </div>
  );
}

export default App;

 

注意,这里的 Box 只是非常简单地在屏幕上打一行字出来。

接着,我们把 Box 稍微完善一下,把它的 css 写得规整一点。如果你对 css 本身不熟悉,没有关系,直接复制 index.css 中的代码就可以了。

.box {
  background-color: green;
  width: 300px;
  height: 300px;
  display: flex;
  flex-direction: column;
}

.drag-handler {
  background-color: grey;
  height: 50px;
  cursor: move;
}

 

到这里,我们应该已经可以看见基本成型的一个盒子组件。注意当鼠标移到把手上时,会出现拖拽的指针指示,这样可以提示用户这是一个可拖拽组件。

接入 react-draggable

现在,我们希望当用户鼠标拖拽把手时,把手本身可以被移动。首先我们把 react-draggable 导入

import Draggable from 'react-draggable'; 

到这里,App.js 中就是。

import './App.css';
import Draggable from 'react-draggable'; // The default

const Box = () => {
  return <div className="box">
    <div className='drag-handler'>拖这里可以</div>
    <div>box 正文,拖这里拖不动</div>
  </div>
}

function App() {
  return (
    <div className="App">
      <Draggable>
        <Box></Box>
      </Draggable>

    </div>
  );
}

export default App;

但是千万注意,如果这里你去试图拖拽一下把手,是拖不动的。原因是 Draggable 并不能直接包一个组件,而需要再包一层 div。我一开始在这里卡了很久时间,但解决的办法很简单,只需要多包一层 div 在外面即可。

function App() {
  return (
    <div className="App">
      <Draggable>
        <div>
          <Box />
        </div>
      </Draggable>

    </div>
  );
}

 

可以看到,如果这时候开始拖动,Box 就可以在界面上自由移动了。但是有一个问题,我们不希望用户拖动正文部分时,也将组件拖动。

要解决这个问题也很简单,请看下一章

如何在 react-draggable 中仅允许组件的一部分被拖动

在 react-draggable 的 API 中,一个属性叫 handle,这个属性的作用就是用来选出对拖动有反应的组件部分。

对应到我们上面的例子,我们只希望在用户拖动把手时,整个组件移动。所以我们只需要用 handle 属性,选出来把手即可。我们在代码中加入

function App() {
  return (
    <div className="App">
      <Draggable handle='.drag-handler'>
        <div>
          <Box />
        </div>
      </Draggable>

    </div>
  );
}

 

注意这里,.drag-handler 是一个选择器,用来选出 className=drag-handler 的组件部分,也就是对应的我们的把手。

那么到此,组件就只能通过拖动把手而拖动了。

限制可拖动范围

有时候我们希望限制可以拖动的范围,比如你不希望用户把一个组件拖到另一个区域,因为可能挡住那个区域的其它界面。在 react-draggable 中,要限制拖动范围很简单,只需要给定 bounds 属性就可以了。

bounds: {left?: number, top?: number, right?: number, bottom?: number} | string,

 

这个 bounds 属性可以指定屏幕上上下左右四个位置的边界限制,同时你也可以给一个字符串,用来选择组件的父组件,这样可以限制该组件只能在它的父组件中移动。限制在父组件中的情况较多,比如你在做一个扑克牌游戏时,显然只希望扑克牌只在牌桌上被拖动,那么你就可以限制扑克牌,让它始终在父组件牌桌中。

具体的例子这里就不展开讲了,请自行探索。

调整样式

最后我们稍微调整一下样式,让整个 APP 看起来漂亮一些。到此,你应该就已经学会使用 react-draggable 来实现拖拽操作了

总结

react-draggable 总体来说是一个非常优秀的拖拽库,虽然自己写也不需要太多代码,但使用一个“经历过战场”的组件库还是可以省掉不少自己实现的时间。同时它的 API 足够优秀,可以满足日常工作需要。如果你觉得自己写有太大挑战,尝试一下用卡拉云搭建后台工具,事半功倍。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React Draggable 实现拖拽 的相关文章

随机推荐

  • mongodb安装

    MongoDB安装 MongoDB下载 下载链接 https www mongodb com download center community 打开下载得到的文件 一直next 接下来一路next 等待安装完成 安装完成
  • ElementUI DatePicker直接赋值回显后,无法更改与删除问题

    前言 使用vue ElementUI 开发项目时 使用到e date picker组件选择日期范围dateRange 当默认dateRange直接赋值后 导致组件内回显的值无法删除且也无法修改 解决方案 setTemp 直接使用下列方式直接
  • Java中BigDecimal详解

    引言 Effective Java 一书中提到 float和double类型主要是为了科学计算和工程计算而设计的 它们执行二进制浮点数运算是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的 然而 它们并没有提供完全精确的结果 先
  • 详解JS原型与原型链

    目录 1 构造函数原型prototype 2 对象原型 proto 3 constructor构造函数 4 原型链 5 原型对象中的this指向 6 扩展内置对象 原型对象的应用 在ES6之前 我们面向对象是通过构造函数实现的 我们把对象的
  • 巨无霸Win8PE X64服务器维护专用,【13年4月4日】维护版win8pe【32位+64位+纯64位】(支持BIOS+EFI)...

    因为单独一个PE是不够用的 已经制作了合盘 可BIOS启动 也可EFI启动 详情移步 欢迎下载使用 觉得好的话 请回帖支持一下 您的支持 就是我的动力 预祝大家新的一年合家欢乐 工作顺利 不定期更新 感谢支持
  • 数据库计算机三级等级考试--数据库技术相关知识点和笔记

    数据库计算机三级等级考试 数据库技术 计算机三级等级考试笔记 是博主通过计算机三级数据库技术考试的相关笔记 此篇博客 不仅适合需要考计算机三级考试的各位考生 也适合在职场处理关于数据库的部分操作 个人认为算是一篇使用性比较强的文档 我个人认
  • Tomcat配置文件信息泄露

    是由于server xml内的appBase置空导致
  • 苹果即将推出的共享表情图案2020将被添加到iPhone手机,ipad的预览

    明天 7月17日 是世界表情包日 World Emoji Day 苹果为庆祝这一节日 将推出的共享表情图案2020添加到iPhone手机 ipad的预览当中 2020年发布的表情符号是表情符号13更新的一部分 其中包括以下表情符号选项 面孔
  • Linux—使用readelf工具查看程序代码变量的内存空间布局情况

    1 源程序与程序的映射 BSS段 存放未初始化的全局变量或静态变量 Block Started by Symbol DATA段 存放已初始化的变量 TEXT段 存放二进制代码 2 程序到进程的映射 程序代码区 存放函数体二进制代码 常量区
  • pthread_detach函数

    线程分离状态 指定该状态 线程主动与主控线程断开关系 使用pthread exit或者线程自动结束后 其退出状态不由其他线程获取 而直接自己自动释放 网络 多线程服务器常用 进程若有该机制 将不会产生僵尸进程 僵尸进程的产生主要由于进程死后
  • 隐私合规:收集SDK部分介绍

    SDK信息查询网站 全国SDK管理服务平台 https sdk caict ac cn official home com meizu cloud pushsdk SystemReceiver 魅族推送服务是由魅族公司为开发者提供的消息推送
  • 为什么期货投资70%的亏钱,20%不亏不赚,10%是赚钱?

    在期货市场中 据专业数据统计 有70 的投资者都是亏钱的 有20 的投资者不亏不赚 只有10 的投资者是赚钱的 以下简单总结了几个原因 1 专业度不够 我国的股民一直就有 暴富 的心理 希望能在股市里一夜暴富 但期货市场需要运动的专业知识比
  • spring data jpa 利用@Query进行查询

    介绍 Query注释之前 先看看怎么利用 NamedQuery进行命名查询 1 现在实体类上定义方法已经具体查询语句 Entity NamedQuery name Task findByTaskName query select t fro
  • Python-字符串的世界

    Python字符串的世界 在Python编程中 字符串 String 是一种非常重要的数据类型 用于表示文本信息 字符串可以包含字母 数字 特殊字符以及空格 它们在编程中被广泛用于文本处理 格式化输出 字符串匹配等各种场景 创建字符串 创建
  • PCB是什么?你真的足够了解PCB吗?

    在电子行业有一个关键的部件叫做PCB printed circuit board 印刷电路板 这是一个太基础的部件 导致很多人都很难解释到底什么是PCB 这篇文章将会详细解释PCB的构成 以及在PCB的领域里面常用的一些术语 在接下来的几页
  • C#进行图片压缩(对jpg压缩效果最好)

    直接上代码 1 public static class ImageCompress 2 3
  • 基于5g的交通运输_江苏交通全面开启“5G”加速

    江苏交通全面开启5G加速 2020年4月1日 江苏省交通运输厅 与三大运营商 江苏铁塔公司 签署5G战略合作协议 共推未来交通信息化 数字化 智能化发展 从中国高层的多次部署 到资本市场的资金热捧 近期最受舆论关注的概念之一莫过于 新基建
  • SQLserver中存储过程的应用

    在SQL中 存储过程类似于编程语言的函数 即当创建一个存储过程之后便可以在接下来任何类似的操作是直接调用存储过程 那么我们创建存储过程的优势是什么呢 1 提高性能 存储过程将SQL语句封装在一起 降低了数据传输的成本 减少执行时间 2 提高
  • 虚拟机栈的作用以及特点

    4 虚拟机栈 每个线程运行时所需要的内存 称为虚拟机栈 在jvm里 方法的临时储存是在栈里完成的 每个栈由多个栈帧 Frame 组成 对应着每次方法调用时所占用的内存 每个线程只能有一个活动栈帧 对应着当前正在执行的那个方法 正在运行的方法
  • React Draggable 实现拖拽

    React Draggable 是 react 生态中 最好用的拖拽实现库之一 如果你的应用中需要实现拖拽功能 可以尝试用 react draggable 它可以满足多数情况下的拖拽需求 比如一个弹出设置浮窗 可以相互遮挡的容器之类 在所有