React-dnd: Используйте внутри и / или с iframe.

Созданный на 20 июл. 2015  ·  22Комментарии  ·  Источник: react-dnd/react-dnd

Когда контекст, источник и цель находятся внутри iframe, DnD не может быть отменен. Я отследил его до бэкэнда HTML5.js, который поставляется с DnD.
Хотя я думаю, что это может быть связано с перерисовкой в ​​iframe. Вот пример кода 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 Комментарий

Изначально перетаскивание между кадрами у меня тоже не работало. Похоже, что события перетаскивания / перетаскивания просто необходимо применить к каждому объекту окна дополнительного фрейма. В настоящее время их получает только объект окна, в котором вы запускаете приложение реакции:

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

Я исправил HTML5-бэкэнд в своем недавнем проекте, чтобы заставить его работать ( setup и teardown принимают альтернативный объект win window):

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

Это также требует, чтобы экземпляр серверной части был каким-то образом открыт (больше исправлений обезьяны в DragDropContext.js ...) для выполнения setup и teardown при необходимости (при настройке ваших фреймов) .

Но как только это будет сделано - это работает как шарм: D

Ого, хорошая находка, в ней много смысла. Собираясь попробовать это позже сегодня, можно ли избежать изменения DragDropContext.js? Таким образом, мы могли бы просто создать новый бэкэнд, как упоминается в документации.

Я рад рассмотреть конкретный API и предложение по реализации для решения этой проблемы.
К сожалению, трудно понять, что именно было изменено и почему.

На данный момент допустим, что мы не поддерживаем фреймы.

@gaearon Я пытаюсь создать конструктор страниц с перетаскиванием. Пробовал все остальное и они ужасно работают с флюсом. Можете дать мне несколько подсказок, где настроить, чтобы он работал с перекрестным фреймом?

@nadimtuhin Я сам работал над

Я не уверен, что работа внутри iframe больше будет лучшим решением, это было бы хорошо. Но цель заставить react-dnd работать в нескольких приложениях - лучший вариант.

Вчера я кратко изучил это и просто зарегистрировал некоторые дескрипторы в бэкэнде html5. и источник из первого окна обнаруживается на цели из второго. Но это все, что я получил.

@gaearon Несколько указателей / подсказок о том, где искать, было бы здорово, если я хочу сделать / попробовать свои первые настоящие вклады с открытым исходным кодом.

@mattconde нет, я не управляю iframe внутри своего приложения для реагирования. Я планирую установить два разных приложения на двух разных фреймах. Родительское окно содержит логику для манипулирования данными, а дочерний фрейм - для представления. Дочерний элемент получает свои реквизиты из родительского хранилища потоков.

@mattconde

Мне трудно дать какие-либо указания, кроме «попробуйте поместить журналы в бэкэнд HTML5, а затем начните его настраивать». Возьмите простейший пример и посмотрите, сможете ли вы заставить его работать. Бэкэнд делает только одно: подписывается на события окна и события узла и преобразует их в действия. Я недостаточно знаю, как работают фреймы. Возможно, вам нужно изменить код, чтобы подписаться не на окно, а на окно верхнего уровня определенного узла (или iframe), если это имеет смысл. Но я здесь совсем не в себе, так что могу говорить чушь.

@mattconde @gaearon

Недавно у меня была такая же проблема. Причина сбоя в том, что HTML5Backend устанавливает прослушиватели событий в окне, но если вы хотите использовать его внутри iframe, вам лучше установить их, скажем, в window.frames [0].

@gaearon Что вы думаете о возможности передачи контекста в функцию настройки / удаления в HTML5Backend.js?

Я столкнулся с той же проблемой, создав расширенный редактор (текст, изображения, ..), который работает в iframe, и мне нужно перетаскивать элементы (текст, img) внутри него, в основном перетаскивая элементы, чтобы изменить заказ.

Я открыл проблему https://github.com/gaearon/react-dnd/issues/435 и просто понял, что это из-за iframe. Я попытаюсь "настроить это", но если есть какое-то решение, я был бы рад узнать! :)

Я пытаюсь сделать пиар, чтобы он работал с фреймами. В настоящее время выполняется, но пока не работает, мне сложно понять, как вызвать setup и teardown соответственно в моих componentDidMount и 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;
    },

Тогда я мог бы поймать эту строку JSON на другом конце с react-dnd , работает очень хорошо.

Дайте мне знать, как у вас дела, хотелось бы услышать об альтернативных способах решения этой проблемы.

@mattconde Я работаю над двумя отдельными ветками, некрасивым исправлением и настоящим исправлением для этого. Уродливое исправление просто изменяет эти строки в файле HTML5Backend.js . Изменения можно посмотреть здесь: https://github.com/Gutenberg-Technology/react-dnd-html5-backend/commit/8b3d6a44b2cdbfe8d5bac025fc263715968d8b6c

_ (в основном он просто добавляет параметр target к setup и teardown , в котором мой iframe используется по умолчанию, и возвращается к использованию window . Исправление настолько уродлив, что на самом деле он потерпит неудачу, если не будет найден iframe, но на данный момент он подойдет.) _

Но это, скорее всего, не удастся в какой-то ситуации, если есть более одного iframe, так что это просто, чтобы избежать зависания. Лучшим решением было бы вручную вызвать setup и teardown в моем собственном коде, просто передав параметр target для привязки и отмены привязки слушателей.

Спасибо за объяснение вашего решения, я обязательно улучшу свой PR, если найду лучший обходной путь в ближайшем будущем. :)

Привет, ребята, я сам столкнулся с этой проблемой, не могу понять, как связать окно с iframe. Например, я хочу иметь некоторый DragSource в окне, и я хочу создать некоторый DropTarget в iframe, даже если я настрою HTML5Backend, я не могу заставить его работать так ...

@mattconde Спасибо, что поделились этим. Думаю, я создаю аналогичный конечный продукт. Хуже всего то, что мы используем Angular 2. Я частично портировал response-dnd на Angular, но, в конце концов, столкнулся с проблемой iframe. Собираюсь попробовать свой путь.

@gaearon PR здесь ☝️ позволяют response-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/

У меня также возникают проблемы с использованием dnd в iframe (без взаимодействия с родителями). Перетаскивание работает нормально, но зоны перетаскивания больше не работают. Каково решение, чтобы зоны перетаскивания работали внутри iframe (просто перемещая элемент полностью внутри iframe).

Я хочу указать, что он работает с бэкэндом Touch, но не с бэкэндом HTML5.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги