React-DnD 的使用

介绍

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

基本用法

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

  2. 把能够拖拽的组件包装在 DragSourcereact

    1. 设置 typegit

    2. 设置 spec,让组件能够响应拖拽事件github

    3. 设置 collect,把拖拽过程当中须要信息注入组件的 props浏览器

  3. 把能够接受拖拽的组件包装在 DropTargetapp

    1. 设置 type函数

    2. 设置 spec,让组件能够响应拖拽事件性能

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

翻译成代码就是:

// 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 表示拖/放组件的兼容性,DragSourceDropTarget 必须指定 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>
        )
    }
}

具体例子

出处

参考资料

相关文章
相关标签/搜索