17

我不完全理解它,但显然不建议使用 findDOMNode()

我正在尝试创建拖放组件,但我不确定我应该如何从组件变量访问 refs。这是我目前拥有的一个例子:

const cardTarget = {
    hover(props, monitor, component) {
        ...
        // Determine rectangle on screen
        const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();
        ...
    }
}

资源

编辑

这可能是由于我的组件既是拖放源又是目标,因为我可以让它在这个例子中工作,但不是这个

4

3 回答 3

22

假设您使用的是 es6 类语法和最新版本的 React(在撰写本文时为 15),您可以像 Dan 在他的示例中所做的那样在您共享的链接上附加一个回调引用。从文档

当 ref 属性用于 HTML 元素时,ref 回调接收底层 DOM 元素作为其参数。例如,此代码使用 ref 回调来存储对 DOM 节点的引用:

<h3
    className="widget"
    onMouseOver={ this.handleHover.bind( this ) }
    ref={node => this.node = node}
>

然后您可以像我们以前与老朋友一样访问该节点,findDOMNode()或者getDOMNode()

handleHover() {
  const rect = this.node.getBoundingClientRect(); // Your DOM node
  this.setState({ rect });
}

在行动: https ://jsfiddle.net/ftub8ro6/

编辑:

因为 React DND 在幕后做了一些魔术,所以我们必须使用他们的 API 来获取装饰组件。它们提供getDecoratedComponentInstance(),因此您可以获取底层组件。一旦你使用它,你可以得到component.node预期的结果:

hover(props, monitor, component) {
    const dragIndex = monitor.getItem().index;
    const hoverIndex = props.index;
    const rawComponent = component.getDecoratedComponentInstance();
    console.log( rawComponent.node.getBoundingClientRect() );
    ...

这是在行动:

https://jsfiddle.net/h4w4btz9/2/

于 2016-11-14T04:07:30.750 回答
3

更好的解决方案

更好的解决方案是只用 a 包装您的可拖动组件,在其div上定义一个 ref 并将其传递给可拖动组件,即

<div key={key} ref={node => { this.node = node; }}>
  <MyComponent
    node={this.node}
  />
</div>

并且MyComponent被包裹在DragSource. 现在你可以使用

hover(props, monitor, component) {
  ...
  props.node && props.node.getBoundingClientRect();
  ...
}

props.node &&只是为了避免调用getBoundingClientRect未定义的对象而添加)

替代品findDOMNode

如果您不想添加 wrapping div,可以执行以下操作。@imjared 的回复和这里建议的解决方案不起作用(至少在react-dnd@2.3.0and中react@15.3.1)。

findDOMNode(component).getBoundingClientRect();唯一不使用的可行替代方案findDOMNode是:

hover(props, monitor, component) {
  ...
  component.decoratedComponentInstance._reactInternalInstance._renderedComponent._hostNode.getBoundingClientRect();
  ...
}

这不是很漂亮和危险,因为react可能会在未来的版本中改变这个内部路径!

其他(较弱)替代品

使用monitor.getDifferenceFromInitialOffset();which 不会给你精确的值,但如果你有一个小的dragSource可能就足够了。然后返回的值是相当可预测的,误差范围很小,具体取决于您的dragSource的大小。

于 2017-05-05T13:36:56.657 回答
0

React-DnD的 API 非常灵活——我们可以(ab)使用它。

例如,React-DnD 让我们确定将哪些连接器传递给底层组件。这意味着我们也可以包装它们。:)

例如,让我们覆盖目标连接器以将节点存储在监视器上。我们将使用 aSymbol这样我们就不会将这个小技巧泄露给外界。

const NODE = Symbol('Node')

function targetCollector(connect, monitor) {
  const connectDropTarget = connect.dropTarget()
  return {
    // Consumer does not have to know what we're doing ;)
    connectDropTarget: node => {
      monitor[NODE] = node
      connectDropTarget(node)
    }
  }
}

现在在您的hover方法中,您可以使用

const node = monitor[NODE]
const hoverBoundingRect = node.getBoundingClientRect()

这种方法搭载 React-DnD 的流程并通过使用Symbol.

无论您是使用这种方法还是基于类的this.node = noderef 方法,您都依赖于底层的 React 节点。我更喜欢这个,因为消费者不必记住手动使用refReact-DnD 已经要求的其他组件,而且消费者也不必是类组件。

于 2017-11-06T13:43:09.183 回答