如何克隆反应元素以进行拖动

Posted

技术标签:

【中文标题】如何克隆反应元素以进行拖动【英文标题】:How to clone a react element for dragging purposes 【发布时间】:2016-08-23 14:13:25 【问题描述】:

所以,我有一个列表,我现在可以使用 react-draggable 将元素(div)拖出该列表。 React-draggable 使原始元素可拖动(有意义),但我需要拖动原始元素的副本(克隆),并将原始元素保持在原位。 所以,我有包含元素的实体列表,每个元素都有一个事件,该事件调用父元素列表希望克隆原始移位,并用可拖动元素包装原始元素以使其可拖动。一旦它可拖动/创建,我想将它附加到屏幕上的不同元素,并将初始位置放在鼠标光标所在的中心。 我想做的最后一件事是,如果元素被放在“错误”的位置,它应该动画(我猜是反应运动)返回到原始位置。最初它是用 Jquery 编写的,我显然知道如何使用 jquery-ui 来实现这一切,但我有点坚持以反应方式去做。

   var Scheduler = require('scheduler/components/Scheduler');

    var ShiftTypeDiv = require('scheduler/components/ShiftType');

    var Draggable = ReactDraggable;

    var ShiftTypes = React.createClass(
      getInitialState: function() 
         return (
          shiftTypes: SchedulerStore.getShiftTypes(),
          clonedItem: null
         )
      ,
      handleStart: function (event, ui) 
        console.log('handleStart: ', event);
        console.log('Position: ', ui.position);
      ,

      cloneShiftBeforeDrag: function (item) 
        console.log('cloning', item);
        React.cloneElement(item);
        ReactDOM.findDOMNode
        this.setState(
          clonedItem: item
        );
      ,

      handleDrag: function (event, ui) 
        console.log('handledrag: ',ui);
        console.log('dragging');
      ,

      handleStop: function (event, ui) 
        console.log('handleStop: ', event);
        console.log('Position: ', ui.position);
      ,

      render: function() 

        var self = this;

        shiftTypesJSX = this.state.shiftTypes.map(function(shiftType,index) 
        return (
                <ShiftTypeDiv shiftType=shiftType key=index cloneShiftBeforeDrag=self.cloneShiftBeforeDrag.bind(null, shiftType) />
                )
        );

        return (
          <div >
             <div className="box-header">
              <ul>
                <li className="title title-name">Shift Templates</li>
                <li className="title edit-link"></li>
              </ul>
            </div>
              <div className="box-content" data-onboarding-item="2">
                <Draggable
                  handle=".ui-draggable"
                  zIndex=100
                  onStart=this.handleStart
                  onDrag=this.handleDrag
                  onStop=this.handleStop
                  >
                  <div className="draggable-custom-shift ui-draggable ui-draggable-handle"><strong>New Shift</strong></div>
                </Draggable>
              </div>
            <div className="box-content" id="shift-templates">
              <div className="row-fluid">
                <div id="shift-types-list" className="span12">
                  <div className="input-group shift-type-filter-form">
                    <input type="text" className="span12" id="shift-type-filter" placeholder="Filter shift templates" />
                    <i className="icon-remove-sign" id="remove-shift-type-filter"></i>
                  </div>
                  <div id="shift_types" >
                    shiftTypesJSX
                  </div>
                </div>
              </div>
            </div>
          </div>
          )
      
    )

    module.exports = ShiftTypes;


var Scheduler = require('scheduler/components/Scheduler').default;

var Draggable = ReactDraggable;

var ShiftTypeDiv = React.createClass(
  handleStart: function (event, ui) 
    console.log('cloning');
    this.props.cloneShiftBeforeDrag(this);
  ,

  handleDrag: function (event, ui) 
    console.log('handledrag: ',ui);
    console.log('dragging');
  ,

  handleStop: function (event, ui) 
    console.log('handleStop: ', event);
    console.log('Position: ', ui);
    this.setState(

    )

  ,
  render: function() 
    shiftType = this.props.shiftType;
    return (
      <Draggable
              bounds="body"
              zIndex=100
              onStart=this.handleStart
              onDrag=this.handleDrag
              onStop=this.handleStop
              position=null
              >
        <div className="draggable-shift-type ui-draggable ui-draggable-handle" data-shift-type-id=shiftType.id>
          shiftType.name <span dangerouslySetInnerhtml=__html:shiftType.start_time + '-' + shiftType.end_time></span>
        </div>
      </Draggable>
      )
  
)

module.exports = ShiftTypeDiv;

【问题讨论】:

【参考方案1】:

由于没有人回答,这是我的解决方案。当组件识别出它正在被拖动时(例如,prop dragged = true),它只会添加另一个类似的转变。我仍然没有尝试实现它的所有“动画”部分,但可以使用 css 或 react-motion。

【讨论】:

如果有更多关于如何解决问题的解释/演示,此答案将提供更多信息和有用。【参考方案2】:

要克隆一个 react 元素可以参考这个问题:How to add props to a component instance in React.js?

这是 API:

React.cloneElement(
  element,
  [props],
  [...children]
)

【讨论】:

以上是关于如何克隆反应元素以进行拖动的主要内容,如果未能解决你的问题,请参考以下文章

在“停止”事件期间如何定位克隆的可拖动元素?

使用“克隆”助手执行可拖动事件后,如何删除原始元素?

在 jQuery UI 中克隆可拖动对象时,如何将数据和事件传输到新元素?

在 jquery drop UI 中,如何使用正确的鼠标位置将拖动元素克隆到放置位置?

克隆时的jQuery可拖动元素不可拖动

Joint.js 在新的克隆元素上触发拖动开始