介绍

React DnD 是一组 React 高阶组件,可以用来帮你构建复杂的拖拽接口,同时解耦你的组件。React DnD 非常适合像 Trello 和 Storify 这样的应用,在不同地方通过拖拽转移数据,而组件会改变它们的外观和应用的状态来响应拖拽事件。

基本用法

  1. 把应用的根组件包装在 DragDropContext 中

  2. 把可以拖拽的组件包装在 DragSource 中

    1. 设置 type

    2. 设置 spec,让组件可以响应拖拽事件

    3. 设置 collect,把拖拽过程中需要信息注入组件的 props

  3. 把可以接受拖拽的组件包装在 DropTarget 中

    1. 设置 type

    2. 设置 spec,让组件可以响应拖拽事件

    3. 设置 collect,把拖拽过程中需要信息注入组件的 props

翻译成代码就是:

 
// 1
import HTML5Backend from 'react-dnd-html5-backend';
import { DragDropContext } from 'react-dnd'; class App { ... }
export default DragDropContext(HTML5Backend)(App); /*---------------------------*/ // 2
import { DragSource } from 'react-dnd'; class MyComponent { ... }
export default DragSource(type, spec, collect)(MyComponent); /*---------------------------*/ // 3
import { DropTarget } from 'react-dnd'; class MyComponent2 { ... }
export default DropTarget(types, spec, collect)(MyComponent2);

这样,MyComponent 就变得可以拖拽,而 MyComponent2 就变得可以接受拖拽了,但这并不代表 MyComponent 可以放到 MyComponent2 中!

一些概念

React DnD 中有一些特殊的概念,理解这些概念之后才能活用这个库!

  • Backend 实现 DnD 的方式,默认是用 HTML5 DnD API,它不能在触屏环境下工作,而且在 IE 下可定制性比其他浏览器弱。你也可以用自己实现,具体请看官方文档。

  • Items 拖拽数据的表现形式,用 Object 来表示。譬如,要拖拽一张卡片,那这张卡片的数据的表现形式可能是 { id: xxx, content: yyy }

  • Types 表示拖/放组件的兼容性,DragSource 和 DropTarget 必须指定 type。只有在 type 相同的情况下,DragSource才能放到 DropTarget 中。

  • Monitors 用来响应拖拽事件,可以用来更新组件的的状态。

  • Connectors 底层接触 DOM 的东西,用来封装你的组件,让你的组件有拖拽的特性。一般在 collect 方法中指定,然后注入到组件的 props 中,最后 render 方法中包装你自己的组件。

  • DragSource && DropTarget 把上面的概念都绑在一起的东西,也是真正跟你的组件打交道的东西。

主要 API 介绍

这些主要 API 都是通过包装你的组件,然后返回一个新的组件。

DragDropContext(backend)

  • backend 实现 DnD 的方式,一般是 HTML5Backend

export default DragDropContext(HTML5Backend)(App);

DragSource(type, spec, collect)

DropTarget(type, spec, collect)

  • type 必须。type 是自定义的,可以是 string,symbol,也可以是用一个函数来返回该组件的其他 props。该组件只能放到相同 type 的 DropTarget 中。

  • spec 必须。一个带有特定方法的纯 Object,里面是一些响应拖拽事件的方法。

  • collect 必须。一个函数返回一个 Object,这个 Object 会注入到组件的 props 中。

  • options 可选。除非有性能问题,否则不需要关心这个参数。

const type = 'xxx';
const spec = { ... };
function collect(connect, monitor) { ... } export default DragSource(type, spec, collect)(MyComponent);
export default DropTarget(type, spec, collect)(MyComponent2);

DragSource#spec

让你的组件响应 dnd 相关事件,支持以下方法:

  • beginDrag(props, monitor, component) 必须

  • endDrag(props, monitor, component) 可选

  • canDrag(props, monitor) 可选

  • isDragging(props, monitor) 可选

参数含义如下:

  • props 组件当前的 props

  • monitor 是一个 DragSourceMonitor 实例,用来查询当前 drag state 的信息。

  • component 表示当前组件,可以省略。

const spec = {
beginDrag(props) {
return {
id: props.id,
content: props.content
}
}
//...
}

DropTarget#spec

让你的组件响应 dnd 相关事件,支持以下方法:

  • drop(props, monitor, component) 可选,响应 drop 事件

  • hover(props, monitor, component) 可选

  • canDrop(props, monitor) 可选

参数含义如下:

  • props 组件当前的 props

  • monitor 是一个 DropTargetMonitor 实例,用来查询当前 drag state 的信息。

  • component 表示当前组件,可以省略。

const spec = {
drop(props, monitor, component) {
// 获取正在拖放的数据
const item = monitor.getItem();
// 更新组件状态
component.setState({
item
}) }
}

DragSource#collect(connect, monitor)

DropTarget#collect(connect, monitor)

返回一个 object,这个 object 可以会注入到组件的 props 中。

  • connect 一个 DragSourceConnector/DropTargetConnector 实例,可以用connect.dragSource()/connect.dropTarget() 来封装我们的组件。

  • monitor 一个 DragSourceMonitor/DropTargetMonitor 实例,用来查询当前拖拽的信息。

function collect(connect, monitor) {
return {
isDragging: monitor.isDragging(),
connectDragSource: connect.dragSource()
}
} class MyComponent extends Component {
render() {
// 可以访问 collect 中返回的 object
const { isDragging, connectDragSource } = this.props;
// 需要用 connect.dragSource()/connect.dropTarget() 封装自己的组件
return connectDragSource(
<div>123</div>
)
}
}

具体例子

出处

参考资料

react-dnd 拖拽的更多相关文章

  1. React 实现拖拽功能

    实现效果:(可戳 https://codepen.io/wenr/pen/EGEQxp 查看) 因为工作中会用到 JIRA 所以想实现一下相似的功能,顺便学习一下 H5 的拖拽.不支持拖拽改变顺序,感 ...

  2. react 可拖拽改变位置和大小的弹窗

    一 目标 最近,项目上需要一个可以弹出一个可以移动位置和改变大小的窗口,来显示一下对当前页面的一个辅助内容 二 思路 1.之前写过一个antd modal的可移动弹窗但是毕竟不如自己写的更定制化,比如 ...

  3. React.js实现原生js拖拽效果及思考

    一.起因&思路 不知不觉,已经好几天没写博客了...近来除了研究React,还做了公司官网... 一直想写一个原生js拖拽效果,又加上近来学react学得比较嗨.所以就用react来实现这个拖 ...

  4. 强大的拖拽组件:React DnD 的使用

    强大的拖拽组件:React DnD 的使用 react.js 10.6k 次阅读  ·  读完需要 25 分钟 17 文章首发我的个人blog : 原文链接 学习 React DnD 的最初原因是阅读 ...

  5. 再谈React.js实现原生js拖拽效果

    前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...

  6. GMF Q&A(1): 如何让palette支持拖拽(DnD)等10则

    1,如何让palette支持拖拽(DnD) 在*PaletteFactory类中,把私有类NodeToolEntry 和LinkToolEntry的基类修改为PaletteToolEntry.并在构造 ...

  7. React Editor 应用编辑器(1) - 拖拽功能剖析

    这是可视化编辑器 Gaea-Editor 的第一篇连载分析文章,希望我能在有限的篇幅讲清楚制作这个网页编辑器的动机,以及可能带来的美好使用前景(画大饼).它会具有如下几个特征: 运行在网页 文档流布局 ...

  8. 拖拽功能by javascript 和 react 两种实现方法

    使用鼠标移动图片或者移动图像怪有意思的,那这个移动的效果是怎么实现的呢? 在拖动的过程中,我们会涉及到鼠标向下按,以及移动图形,还有我们松开这几个步骤. 当我们将鼠标向下按的时候,我们鼠标点的这个动作 ...

  9. react实现的点击拖拽元素效果

    之前用vue做日程管理组件的时候,用到了点击拖拽的效果,即点击元素,鼠标移动到哪里,元素移动到哪里,鼠标松开,拖拽停止,现在在弄react,于是也在想实现这个效果,经过一番折腾,效果出来了,代码如下: ...

  10. react 拖拽排序---原生

    定义css, 两个动画 .drag-up { -webkit-animation: dragup ease 0.2s 1; animation: dragup ease 0.2s 1; -webkit ...

随机推荐

  1. jquery图片切换插件jquery.cycle.js参数详解

    转自:国人的力量 blog.163.com/xz551@126/blog/static/821257972012101541835491/ 自从使用了jquery.cycle.js,我觉得再也不用自己 ...

  2. 基于网站地址URL传输session信息

    在php的学习中,会话是我们常常用到的,那今天我们就来详细讲讲会话中的session: 一.session的工作机制:当开启session后,服务器会在服务器中保存session文件,然后再浏览器保存 ...

  3. 拼接Python字符串最常见的六种方式

    最常见的六种方式拼接Python字符串 字符串是所有编程语言中都有的基本变量的类型,程序员基本每天都在和字符串打交道. 每种字符串拼接方式的使用场景各不相同,我们可以在开发过程中灵活运用. 一.用逗号 ...

  4. 【Windows7注册码】

    [文章转载自 http://www.win7zhijia.cn/jiaocheng/win7_19324.html] 一.神Key: KH2J9-PC326-T44D4-39H6V-TVPBY TFP ...

  5. Kattis - doubleclique (图论)

    From : North American Invitational Programming Contest 2018 给你一个图,以及它的补图.如果部分点在原图中是团,并且其他的所有点在补图中也是团 ...

  6. Spring MVC+Mybatis 多数据源配置及发现的几个问题

    1.CustomerContextHolder 数据源管理类,负责管理当前的多个数据源,基于ThreadLocal实现,对每个线程设置不同的目标数据源 public class CustomerCon ...

  7. 有限状态机(FSM)的设计与实现

    有限状态机(FSM)是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用.通常FSM包含几个要素:状态的管理.状态的监控.状态的触发.状态触发后引发的动作.本文主要 ...

  8. Service 回顾

    绑定本地service需要实现onBind()方法

  9. 【Codeforces Round #476 (Div. 2) [Thanks, Telegram!] C】Greedy Arkady

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举那个人收到了几次糖i. 最好的情况显然是其他人都只收到i-1次糖. 然后这个人刚好多收了一次糖 也即 (i-1)kx + x & ...

  10. [每日App一]QQ主题要逆天!轻轻松松月入30万!

    听从吾师秦刚(微信或QQ:1111884)酋长的建议,谋哥(微信viyi88)我开始新的征程,每日更新一篇干货文章(要坚持啊!否则被酋长鄙视了). 好了,废话不多说,今天我给大家揭秘一个你从来想也木有 ...