React-dnd: 在内部和/或与iframe一起使用。

创建于 2015-07-20  ·  22评论  ·  资料来源: react-dnd/react-dnd

当上下文,源和目标位于iframe DnD内时,无法取消移动。 我已经将其追溯到DnD随附的HTML5.js后端。
尽管我认为这可能与iframe中的重新渲染有关。 这是有关Codepen的示例http://codepen.io/mattconde/pen/zGLXML?editors=101

enhancement wontfix

最有用的评论

经过大量尝试,我设法将元素放入iframe中,如下所示:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import FrameComponent from 'react-frame-component';

class DragDropAwareIFrame extends Component {
  static propTypes = {
    innerRef: PropTypes.func,
  };

  static contextTypes = {
    dragDropManager: PropTypes.object.isRequired,
  }

  constructor(props, context) {
    super(props, context);

    this.manager = this.context.dragDropManager;
  }

  componentDidMount() {
    const iframe = ReactDOM.findDOMNode(this.iframe);
    this.manager.getBackend().addEventListeners(iframe.contentWindow);
  }

  componentWillUnmount() {
    const iframe = ReactDOM.findDOMNode(this.iframe);
    this.manager.getBackend().removeEventListeners(iframe.contentWindow);
  }

  handleRef = (el) => {
    this.iframe = el;
    if (this.props.innerRef) this.props.innerRef(el);
  }

  render() {
    const { innerRef, ...props } = this.props;
    return <FrameComponent {...props} ref={this.handleRef} />;
  }
}

<DragDropContextProvider backend={HTML5Backend}>
    <div>
        <Item />
        <DragDropAwareIFrame>
            <div>
                <Dustbin />
            </div>
        </DragDropAwareIFrame>
    </div>
</DragDropContextProvider>

这似乎是正确的做法吗?

所有22条评论

开箱即用地跨帧拖放对我也不起作用。 似乎拖放事件只需要应用于每个其他框架的窗口对象。 当前,只有您在其中运行react应用程序的window对象可以获取它们:

https://github.com/gaearon/react-dnd/blob/master/src/backends/HTML5.js#L130 -L139

我在最近的项目中猴子修补了HTML5-后端,以使其正常工作( setupteardown接受备用的win窗口对象):

https://gist.github.com/rasmusfl0e/39db428399bd196ef706

它还需要以某种方式暴露后端实例(在DragDropContext.js更多的猴子修补)以在需要时执行setupteardown (设置框架)。 。

但是一旦完成-它就像一个魅力:D

哦,真好找,很有道理。 今天晚些时候要尝试一下,是否可以避免DragDropContext.js中的更改? 这样,我们可以像文档中提到的那样组成一个新的后端。

我很高兴考虑解决此问题的特定API和实施建议。
不幸的是,很难从本质上了解到底发生了什么变化以及原因。

现在,假设我们不支持iframe。

@gaearon我正在尝试构建一个拖放页面构建器。 尝试了其他所有内容,它们无法正常工作。 可以给我一些线索,以使其在横向框架中起作用吗?

@nadimtuhin当我提出这个问题时,我自己正在从事一个跨框架页面构建器的工作,本周我将重新开始获得一个多窗口解决方案。 您是否正在使用反应来管理iframe?

对我来说,我不确定在iframe中进行操作是否会成为最佳解决方案,这肯定会很好。 但是,以使react-dnd跨多个应用程序工作为目标似乎是更好的选择。

昨天,我对它进行了简短的查看,只是在html5后端中记录了一些句柄。 从第二个目标中检测到第一个窗口中的源。 但这是我所知。

@gaearon一些指向哪里的指针/线索会很棒,希望使/尝试我的第一个真正的开源贡献者。

@mattconde不,我没有在我的

@mattconde

除了“尝试将日志放入HTML5后端然后开始对其进行调整”之外,我很难给出任何指针。 以最简单的示例为例,看看是否可以使其工作。 后端只做一件事:订阅窗口事件和节点事件,并将它们转换为动作。 我对iframe的工作方式了解不足。 也许您需要更改代码以不订阅该窗口,而是订阅特定节点的顶级窗口(或iframe)(如果有必要)。 但是我不在这里,所以我可能在谈论垃圾。

@mattconde @gaearon

我最近有同样的问题。 失败的原因是因为HTML5Backend在窗口上设置了事件侦听器,但是如果您想在iframe中使用它,则应该将其设置为例如window.frames [0]。

@gaearon您如何考虑将上下文传递给HTML5Backend.js中的setup / teardown函数的选项?

我一直在遇到同样的问题,方法是构建一个可在iframe中使用的增强的编辑器(文本,图像等),我需要在其中拖放元素(文本,img),基本上是通过拖放元素来更改订购。

我打开了一个问题https://github.com/gaearon/react-dnd/issues/435,只是发现这是由于iframe所致。 我将尝试“调整”,但是如果有任何解决方法,我将很高兴知道! :)

我正在尝试制作PR以使其与iframe一起使用。 目前正在进行中,尚无法使用,我在弄清楚如何分别在componentDidMountcomponentWillUnmount分别调用setupteardown遇到麻烦componentWillUnmount方法。

https://github.com/gaearon/react-dnd-html5-backend/pull/27

@Vadorequest听起来我们俩都在瞄准类似的最终产品。 我最终没有使它与父窗口到子窗口的react-dnd一起使用。 我决定解决的工作是拥有编辑器(父)应用程序和预览(子级)应用程序。 预览应用程序只有在可以连接到编辑器redux存储之前才呈现。

然后,在我的redux商店中,我有一个模板列表,我希望用户将其从编辑器中拖动到一个漂亮的内容页面。 因此,我的模板列表位于“编辑器”窗口中,但我想将它们拖到“预览”中。

感谢react-dnd支持本机类型,我可以在“编辑器”窗口中设置文本拖动,以传递要呈现的每个模板所需的信息。 我的代码段...

    componentDidMount() {
        this.refs.template.addEventListener('dragstart', this.handleDragStart, false);
    },
    componentWillUnmount() {
        this.refs.template.removeEventListener('dragstart', this.handleDragStart, false);
    },
    handleDragStart(e) {
        const { template } = this.props;
        e.dataTransfer.setData('text/plain', JSON.stringify({
            type: template.type,
            name: template.name,
        }));
        return e;
    },

然后我可以用react-dnd捕获另一端的JSON字符串,效果很好。

让我知道您的生活,希望了解其他解决方法。

@mattconde我正在两个单独的分支上,为此进行一个丑陋的修复和一个实际的修复。 丑陋的修复仅更改了HTML5Backend.js文件中的那些行。 可以在这里查看更改: https :

_(它基本上只是在setupteardown添加target参数,将我的iframe作为默认值,然后回退到使用window 。太丑陋了,如果找不到iframe,它实际上会失败,但是现在就可以了。)_

但是,如果存在多个iframe,则在某些情况下这可能会失败,因此只是为了避免卡住。 更好的解决方案是在我自己的代码中手动传递setupteardown ,只需传递target参数来绑定和取消绑定侦听器。

感谢您解释您的解决方案,如果在不久的将来找到更好的解决方法,我一定会提高我的PR。 :)

大家好,我自己遇到了这个问题,无法弄清楚如何将窗口与iframe连接起来。 例如,我想在窗口上放置一些DragSource,并想在iframe上创建一些DropTarget,即使我对HTML5Backend进行了调整,也无法使其正常工作...

@mattconde感谢您的分享。 我正在构建类似的最终产品。 更糟糕的是,我们正在使用Angular2。我将react-dnd部分移植到Angular,但是最后,我使用iframe碰壁了。 要尝试一下。

@gaearon这里的PR☝️允许react-dnd支持iframe。 如果您有任何疑问或需要我进行任何更改,请告诉我。

@kesne您是新的维护者吗? 您可以查看这些PR吗?

嗨@darthtrevino
您所做的更改是否允许将元素从页面拖动到框架?
我可以在框架内部和外部拖放。

@crysislinux ,我希望将此库移植到Angular 2,很想看看你们提出了什么。 您愿意分享您的代码吗? 谢谢!

有没有一种方法可以将iframe外部的项目放置到iframe中,例如:

<DragDropContextProvider backend={HTML5Backend}>
    <div>
        <Item />
        <Frame>
            <div>
                <Dustbin />
            </div>
        </Frame>
    </div>
</DragDropContextProvider>

经过大量尝试,我设法将元素放入iframe中,如下所示:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import FrameComponent from 'react-frame-component';

class DragDropAwareIFrame extends Component {
  static propTypes = {
    innerRef: PropTypes.func,
  };

  static contextTypes = {
    dragDropManager: PropTypes.object.isRequired,
  }

  constructor(props, context) {
    super(props, context);

    this.manager = this.context.dragDropManager;
  }

  componentDidMount() {
    const iframe = ReactDOM.findDOMNode(this.iframe);
    this.manager.getBackend().addEventListeners(iframe.contentWindow);
  }

  componentWillUnmount() {
    const iframe = ReactDOM.findDOMNode(this.iframe);
    this.manager.getBackend().removeEventListeners(iframe.contentWindow);
  }

  handleRef = (el) => {
    this.iframe = el;
    if (this.props.innerRef) this.props.innerRef(el);
  }

  render() {
    const { innerRef, ...props } = this.props;
    return <FrameComponent {...props} ref={this.handleRef} />;
  }
}

<DragDropContextProvider backend={HTML5Backend}>
    <div>
        <Item />
        <DragDropAwareIFrame>
            <div>
                <Dustbin />
            </div>
        </DragDropAwareIFrame>
    </div>
</DragDropContextProvider>

这似乎是正确的做法吗?

@ethanve刚从一个重复的问题中https://cormacrelf.github.io/angular-skyhook/

我在iframe中使用dnd时也遇到了麻烦(无父级交互)。 拖动效果很好,但是拖放区域不再起作用。 使放置区域在iframe中工作的解决方案是什么(只需将项目完全在iframe中移动)。

我想指出的是,它适用于Touch后端,但不适用于HTML5后端。

此页面是否有帮助?
0 / 5 - 0 等级