react-dnd


介紹

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>
          )
      }
    }

     

轉自:https://scarletsky.github.io/2015/11/17/react-dnd-usage/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM