React Draggable 实现拖拽 - 最详细中文教程 - 卡拉云

HiJiangChuan · · 1022 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

![react-draggable](https://kalacloud.com/static/2ea61fcd7c5823d6e606ff7ba5f398e0/eea4a/head.jpg) 本文首发:《[React Draggable 实现拖拽 - 最详细中文教程 - 卡拉云](https://kalacloud.com/blog/react-draggable-tutorial/)》 React Draggable 是 react 生态中,最好用的拖拽实现库之一。如果你的应用中需要实现拖拽功能,可以尝试用 [react-draggable](https://github.com/react-grid-layout/react-draggable),它可以满足多数情况下的拖拽需求,比如一个弹出设置浮窗,可以相互遮挡的容器之类。在所有 react 拖拽库里(即 react dnd, drag and drop),react-draggable 算是把功能性和易用性平衡得最好的拖拽库了。 在实现[卡拉云](https://kalacloud.com/blog)时,我们也大量使用了 `react-draggable`。所以这篇文章里,我们介绍如何使用 react-draggable,一些常见的设置和我们的经验。请根据下面的代码一步步实现,最终你要实现的效果如下 ![react-draggable 最终效果](https://kalacloud.com/32333fcb36df302397dfd1de82e7852b/react-draggable-final.gif) 如果你在参考的过程中有不确定代码应该怎么写,可以直接到代码库中找到对应的文件。本文可参考的代码放在 github 上: [react-draggable代码](https://github.com/kalacloud-inc/react-draggable-tutorial),觉得不错的话不妨打个星。 ## react-draggable 简介 react-draggable 经过几年的发展,已经是一个相对比较稳定的库了。从 npm trends 上看,从 16 年起它的流行程度就迅速超过了其它几个类似的项目。它在 github 上算非常热门的项目了,使用它的项目众多,所以可以放心地使用。如果有 bug 反馈也会非常快 ![react-draggable的github页面](https://kalacloud.com/static/77b55d790397c9303fb78a4df8234de3/00fb1/react-draggable-github.png) 如果看它的源码的话,会发现它的原理其实很简单,它只是将一个需要被拖拽的组件包到它定义的一个组件中,当鼠标拖拽时,重新计算组件的位置,这样就实现了“拖拽”的效果。这也是绝大多数拖拽组件库的实现方式。 ## 准备项目 我们按常规,使用 `create-react-app` 这个工具来创建项目。如果你本地没有安装 npx 的话,强烈推荐,使用非常方便。 ``` npx create-react-app react-draggalbe-tutorial cd react-draggalbe-tutorial npm start ``` 在准备好 react 脚手架后,你就可以到目录里,把项目跑起来。 执行 `npm start`。这时候应该看到一个熟悉的画面 ![react 初始设置](https://kalacloud.com/static/72178fc5a9777c428fb82bb99181a295/990be/react-init.png) 当然如果你是在已有项目里准备加上 react-draggable,那么跳过本步,直接执行下一步安装就好了。 ## 安装 react-draggable 现在执行 `npm install react-draggable`,执行完后应该在你的 `node_modules` 中就装好了 react-draggable。 ``` ☁ react-draggalbe-tutorial [master] npm install react-draggable added 2 packages, and audited 1408 packages in 2s ``` ## 新建一个盒子组件 我们先在 `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可以拖动了](https://kalacloud.com/3b926b8c641239c361e06ad5d47b5cf2/react-dnd-1.gif) 要解决这个问题也很简单,请看下一章 ## 如何在 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` 的组件部分,也就是对应的我们的把手。 那么到此,组件就只能通过拖动把手而拖动了。 ![只有拖动把手时可以移动](https://kalacloud.com/c4601b391bf1e76d9e527e57dd23924d/only-handle-works.gif) ## 限制可拖动范围 有时候我们希望限制可以拖动的范围,比如你不希望用户把一个组件拖到另一个区域,因为可能挡住那个区域的其它界面。在 react-draggable 中,要限制拖动范围很简单,只需要给定 `bounds` 属性就可以了。 ``` bounds: {left?: number, top?: number, right?: number, bottom?: number} | string, ``` 这个 bounds 属性可以指定屏幕上上下左右四个位置的边界限制,同时你也可以给一个字符串,用来选择组件的父组件,这样可以限制该组件只能在它的父组件中移动。限制在父组件中的情况较多,比如你在做一个扑克牌游戏时,显然只希望扑克牌只在牌桌上被拖动,那么你就可以限制扑克牌,让它始终在父组件牌桌中。 具体的例子这里就不展开讲了,请自行探索。 ## 调整样式 最后我们稍微调整一下样式,让整个 APP 看起来漂亮一些。到此,你应该就已经学会使用 react-draggable 来实现拖拽操作了 ![react-draggable 最终效果](https://kalacloud.com/32333fcb36df302397dfd1de82e7852b/react-draggable-final.gif) ## 其它库和实现 实现拖拽的其它方式也还很多,我们会在之后的文章中介绍。如果你用的是 Vue 的话,不妨参考我们的文章:[最好的Vue拖拽库推荐](https://kalacloud.com/blog/best-drag-drop/) ## 总结 `react-draggable` 总体来说是一个非常优秀的拖拽库,虽然自己写也不需要太多代码,但使用一个“经历过战场”的组件库还是可以省掉不少自己实现的时间。同时它的 API 足够优秀,可以满足日常工作需要。如果你觉得自己写有太大挑战,尝试一下用[卡拉云](https://kalacloud.com/)搭建[后台工具](https://kalacloud.com/blog/best-vue-js-admin-dashboard/),事半功倍。

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1022 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传