React:我可以操纵DOM React渲染多less?

这就是我正在做的: 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,定位的元素仍然会更新!)

我的问题是有多less由此产生的假设是安全的(例如,如果我假设这些东西,我的代码是否会在未来版本的React中被破解?):

  • React不关心DOM是否在更新之间移动,只要你把它放回componentWillUpdate。
  • React事件处理程序仍然可以处理已移动的元素。
  • React会将您要求的任何内联样式与元素上的样式合并(即使它没有设置它们)。
  • React将更新它所呈现的DOM,即使您将该DOM移动到文档中的其他位置也是如此!

最后一个对我来说似乎有些极端和神奇,但是如果它持续下去的话,会有一些重大的意义。

我是React开发者。 我会回答你的每个问题:


React不关心DOM是否在更新之间移动,只要你把它放回componentWillUpdate。

真 – 除了事件处理程序更新以外,React不查看DOM:

React事件处理程序仍然可以处理已移动的元素。

我不会依赖这个,而且我不确定现在甚至是这样。

React会将您要求的任何内联样式与元素上的样式合并(即使它没有设置它们)。

我也不会依赖这个 – 现在React设置个别属性,但是我可以很容易地想象如果设置el.style.cssText更快,这会吹掉你所做的个别更改。

React将更新它所呈现的DOM,即使您将该DOM移动到文档中的其他位置也是如此!

我不相信这是真的,你也不应该依赖这个。


一般来说,您不应该手动操作React创build的DOM。 在React中创build一个空的<div>并用手工填充是100%洁净的; 只要你以后不要尝试在React中改变它的属性(导致React去执行DOM更新),修改一个React-rendered元素的属性甚至是可以的,但是如果你移动一个元素,React可能会去查找它,当它找不到时会感到困惑。

希望有所帮助。

一方面我同意苏菲的观点,你不应该根据实施细节做出决定。 不过,我想说看看React实际上是如何工作仍然是有趣的:

有些事情可能已经改变了一些,但通常这是发生了什么事情以及如何发生。

  1. 考虑一下这样一个事实,即React在其创build的每个DOM元素上放置唯一的id(现在是数据属性)。 这些ID目前基于一个非常简单的系统。 这应该解释系统 – 根节点总是'.0'

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

无论何时您提供“键”属性,您提供的值都将用于该ID,而不是列表中的索引,但系统保持不变。

  1. 由React创build的虚拟DOM也具有相同ID的轻量级对象。 这是虚拟DOM和真实DOM之间的简单映射系统。

  2. 这也是为什么如果不提供“key”属性,那么列表中的元素将被覆盖,因为如果元素在列表中间被添加或删除,元素的id将会改变。

牢记这一点:

React不关心DOM是否在更新之间移动,只要你把它放回componentWillUpdate。

是。 我认为即使你没有把元素放在更新之前,事情也可能会起作用,因为React使用ID来工作。 但是,这将是一个非常棘手和不可靠的工作,因为元素可能被添加或删除,事情可能会破坏。

React事件处理程序仍然可以处理已移动的元素。

是的…在某种程度上。 事件处理者反应工作的方式是所有事件都是合成的。 这意味着在React根DOM节点上只有一个事件监听器。 所有捕获的事件都与React中的事件侦听器相匹配。 我认为这也使用ID来匹配元素。 但是,React可能会对其父元素进行一些最小的检查。 我认为这应该工作,只要该元素保持在由React呈现的相同的根节点。 也就是说,React可以在将来更新id系统,并在将来对父节点进行更多的检查,然后这可能会中断。

React会将您要求的任何内联样式与元素上的样式合并(即使它没有设置它们)。

这已经被回答了。 目前工作,未来可能无法工作。 但是,我不会在短期内改变,因为有一些animation系统依赖于这个实现细节。

React将更新它所呈现的DOM,即使您将该DOM移动到文档中的其他位置也是如此!

是的,如果你使用相同的react-id保持相同的DOM元素,那么react就不会知道它已经移动到文档中,只会更新它,就好像它处于它所呈现的相同位置一样。 正如你已经注意到它需要在同一个React Root中。 这很重要,因为React只绑定到合成事件的React根DOM节点。这样React和其他库一起工作,并且不需要访问文档根目录。

谨慎的话:只因为你可以做点什么,并不意味着你应该这样做。 一般而言,您只应添加其他DOM节点,并在不受Reactpipe理的DOM节点(样式:变换值对于animation通用)上添加属性。 当你做其他事情时,明白事情可能会奏效,但是通常情况下有更好的方法去做事情。


至于你的问题:

那么你如何解决我的问题? 例如滚动区域内的下拉菜单被溢出中断…我一直将元素移动到正文,但似乎不是反应的方式。

我认为这里最理想的状况就是把这个下拉开始。 然后,您可以在点击事件和下拉菜单之间传递消息。 要么你可以使用callback在虚拟DOM上足够高,然后将道具一直更新到下拉菜单来pipe理它的状态。 或者只是使用一个好的“事件系统”。