it-swarm.com.ru

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

Это то, что я делаю: http://jsfiddle.net/iamnoah/pTrrw/

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

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 куда-нибудь еще в документе!

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

59
noah

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


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

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

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

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

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

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

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

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


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

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

57
Sophie Alpert

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

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

  1. Учтите, что React устанавливает уникальные идентификаторы (теперь атрибуты данных) для каждого создаваемого им элемента DOM. Эти идентификаторы в настоящее время основаны на очень простой системе. Это должно объяснить систему - корневым узлом всегда является ".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 будут по-прежнему работать с перемещенными элементами.

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

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

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

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

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

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


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

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

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

16
Naman Goel