Подтвердить что ты не робот

React: Сколько я могу манипулировать DOM React?

Это то, что я делаю: jsfiddle

Критический раздел:

position: function() {
  var container = $(this.getDOMNode());
  this._menu = $(this.refs.menu.getDOMNode());
  this._menu.appendTo(document.body).
      offset({
          top: container.offset().top + 
              container.outerHeight(),
          left: container.offset().left
      });
},
restore: function() {
  this._menu.appendTo(this.getDOMNode());      
},
componentWillUpdate: function() {
  this.restore();
},
componentDidUpdate: function() {
  this.position();
},
componentDidMount: function() {
  this.position();
},

Это прекрасно работает прямо сейчас. Я помещаю содержимое обратно до обновления компонента, предполагая, что React оставляет DOM в покое между обновлениями и не пропустит его. На самом деле, React, похоже, в порядке с движущимся контентом (если я удалю componentWillUpdate и componentDidUpdate, позиционируемый элемент все равно обновится!)

Мой вопрос состоит в том, сколько из полученных предположений являются безопасными (то есть, если я предположу эти вещи, мой код сломается в будущей версии React?):

  • React не волнует, перемещается ли DOM между обновлениями, если вы поместите его обратно в componentWillUpdate.
  • Обработчики событий React будут по-прежнему работать с перемещенными элементами.
  • React объединит любые встроенные стили, которые вы зададите, со стилями, уже имеющимися в элементе (даже если он их не установил).
  • React обновит DOM, который он отобразил, даже если вы переместите этот DOM куда-то еще в документе!

Последнее кажется мне несколько экстремальным и волшебным, но оно имеет некоторые важные последствия, если оно имеет место.

4b9b3361

Ответ 1

Я разработчик React. Я отвечу на каждый из ваших вопросов:


React не имеет значения, перемещается ли DOM между обновлениями, пока вы вернетесь обратно в componentWillUpdate.

True - React не смотрит на DOM, кроме как при обновлении, за исключением обработчиков событий:

Обработчики событий React будут по-прежнему работать с перемещенными элементами.

Я бы не стал полагаться на это, и я не уверен, что это правда сейчас.

React объединит любые встроенные стили, которые вы задаете со стилями уже на элементе (даже если он не установил их.)

Я тоже не буду полагаться на это - прямо сейчас React устанавливает индивидуальные свойства, но я легко мог предположить, что он устанавливает el.style.cssText, если бы это было быстрее, что сдуло бы отдельные изменения, которые вы сделали.

React обновит DOM, который он отобразил, даже если вы переместите этот DOM в другое место в документе!

Я не верю, что это правда сейчас, и вы также не должны полагаться на это.


В общем, вам не следует манипулировать вручную DOM, созданный React. Это 100% кошерный, чтобы создать пустой <div> в React и заполнить его вручную; даже если вы не измените его свойства в React (заставляя React выполнять обновления DOM), но даже если вы перемещаете элемент, React может искать его и запутаться, когда он не сможет его найти.

Надеюсь, что это поможет.

Ответ 2

С одной стороны, я согласен с Софи, что вы не должны основывать решения на деталях реализации. Однако я бы сказал, что по-прежнему интересно посмотреть, как работает React:

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

  • Рассмотрим тот факт, что React ставит уникальные идентификаторы (теперь атрибуты данных) на каждый созданный им элемент DOM. Эти идентификаторы в настоящее время основаны на очень простой системе. Это должно объяснить систему. Корень node всегда '.0'

               .0
        .0.0        .0.1
    .0.0.0     .0.1.0 .0.1.1
    

Всякий раз, когда вы предоставляете атрибут "ключ", значение, которое вы предоставляете, используется для идентификатора, а не индекса в списке, но система остается той же.

  1. Виртуальная DOM, созданная React, также имеет легкие объекты с одинаковыми идентификаторами. Это простая система отображения между виртуальным DOM и реальным DOM.

  2. Вот почему элементы в списке перезаписываются, если вы не предоставляете атрибут "ключ", поскольку идентификатор элементов будет меняться, если элемент будет добавлен или удален в середине списка.

Помня об этом:

React не имеет значения, перемещается ли DOM между обновлениями, пока вы вернетесь обратно в componentWillUpdate.

Да. Я думаю, что возможно, что все будет работать, даже если вы не вернете элемент перед обновлениями, так как React работает с использованием идентификаторов. Но это было бы очень сложно и ненадежно работать, поскольку элементы могут быть добавлены или удалены, и все может сломаться.

Обработчики событий React будут по-прежнему работать с перемещенными элементами.

Да... в некоторой степени. Способ обработки обработчиков событий заключается в том, что все события являются синтетическими. Это означает, что в React root DOM node есть только один прослушиватель событий. Все обнаруженные там события сопоставляются с прослушивателями событий в React. Я думаю, что это также использует идентификаторы для соответствия элементам. Тем не менее, React может выполнить некоторую минимальную проверку его родительских элементов. Я думаю, что это должно работать до тех пор, пока элемент хранится в пределах одного корня node, созданного React. Тем не менее, React может обновить систему id в будущем и сделать больше проверки родительских узлов в будущем, и это может сломаться.

React объединит любые встроенные стили, которые вы задаете со стилями уже на элементе (даже если он не установил их.)

Это уже ответили. Работы на данный момент, возможно, не сработают в будущем. В краткосрочной перспективе это не изменится, поскольку существуют некоторые системы анимации, которые зависят от этой детали реализации.

React обновит DOM, который он отобразил, даже если вы переместите этот DOM в другое место в документе!

Да, если вы сохраните один и тот же элемент DOM с одним и тем же идентификатором реакции, реакция не будет знать, что он переместился в документе и будет просто обновлять его, как если бы он находился в том же месте, где он отображался. Как вы уже заметили, он должен находиться в одном и том же корне Реагента. Это важно, так как React связывается только с React root DOM node для синтетических событий и т.д. Таким образом, React хорошо взаимодействует с другими библиотеками и не нуждается в доступе к корню документа.

Слово предостережения: просто потому, что вы можете что-то делать, это не значит, что вам нужно. Вообще говоря, вы должны добавлять только дополнительные узлы DOM и добавлять свойства на узлы DOM, которые не управляются с помощью React (значения стиля: преобразование являются общими для анимаций). Когда вы делаете другие вещи, понимайте, что все может работать, но обычно есть гораздо лучший способ сделать что-то.


Что касается вашей проблемы:

Итак, как бы вы решили мою проблему? например, выпадающее меню внутри области прокрутки, обрезанное переполнением... Я всегда перемещал элемент в тело, но, похоже, это не Реакт.

Я думаю, что идеальная ситуация здесь заключается в том, чтобы начать выпадающее из тела. Затем вы можете передавать сообщения между событием click и выпадающим. Либо вы можете использовать обратные вызовы, чтобы они были достаточно высокими на виртуальной DOM, а затем обновляли реквизиты вплоть до выпадающего списка, чтобы управлять им. ИЛИ просто используйте хорошую систему событий.