React:我可以操作DOM React渲染了多少?

noa*_*oah 60 dom reactjs

这就是我在做的事: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();
},
Run Code Online (Sandbox Code Playgroud)

这个现在很好用.我假设React在更新之间单独留下DOM并且不会错过它,我会在组件更新之前将内容放回去.事实上,React似乎可以正常移动内容(如果我删除componentWillUpdate并且componentDidUpdate定位的元素仍然更新!)

我的问题是有多少结果假设是安全的(即,如果我假设这些东西,我的代码是否会在未来版本的React中破坏?):

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

对我来说,最后一个看起来有点极端和神奇,但如果它成立,它会有一些很大的影响.

Sop*_*ert 60

我是React dev.我会回答你的每个问题:


只要将它放回componentWillUpdate中,React就不关心DOM是否在更新之间移动.

True - React不会在更新时查看DOM,但事件处理程序除外:

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

我不会依赖于此,我不确定它现在是否真实.

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

我也不会依赖于此 - 现在React设置了各个属性,但我可以很容易想象它设置el.style.cssText是否更快,这会吹走你所做的个别变化.

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

我不相信这是真的,你也不应该依赖于此.


从广义上讲,你不应该手动操作React创建的DOM.<div>在React中创建一个空的并且用手填充它是100%犹太人; 只要您以后不尝试在React中更改其属性(导致React执行DOM更新),甚至可以修改React渲染元素的属性,但是如果移动元素,React可能会查找它并且当它找不到它时会感到困惑.

希望有所帮助.

  • 谢谢!非常有启发性. (2认同)

Nam*_*oel 16

一方面,我同意Sophie的观点,即您不应该根据实施细节做出决定.但是,我想说React实际上是如何工作的仍然很有趣:

有些事情可能会有所改变,但通常这就是发生的事情以及它是如何发生的.

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

               .0
        .0.0        .0.1
    .0.0.0     .0.1.0 .0.1.1
    
    Run Code Online (Sandbox Code Playgroud)

每当您提供"key"属性时,您提供的值将用于id而不是列表中的索引,但系统保持不变.

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

  2. 这也是为什么如果不提供'key'属性则覆盖列表中的元素的原因,因为如果在列表中间添加或删除元素,则元素的id会发生变化.

记住这一点:

只要将它放回componentWillUpdate中,React就不关心DOM是否在更新之间移动.

是.我认为即使你没有在更新之前把元素放回去,事情仍然有效,因为React使用id工作.但这可能是一个非常棘手和不可靠的工作,因为元素可能被添加或删除,事情可能会破裂.

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

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

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

这已经得到了解答.暂时工作,将来可能无法使用.我不会在短期内改变,因为有一些动画系统依赖于这个实现细节.

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

是的,如果您使用相同的react-id保留相同的DOM元素,则react将不知道它已在文档中移动,并且只是更新它,就好像它处于呈现它的相同位置一样.正如您已经注意到它需要在同一个React Root中.这很重要,因为React仅绑定到React根DOM节点以获取合成事件等.这样React可以很好地与其他库一起使用,并且不需要访问文档根目录.

谨慎之言:仅仅因为你可以做某事并不意味着你应该这样做.一般来说,您应该只添加其他DOM节点,并在未由React管理的DOM节点上添加属性(样式:变换值对于动画是常见的).当你做其他事情时,要明白事情可能有效,但通常有更好的方法来做事.


至于你的问题:

那你怎么解决我的问题呢?例如,滚动区域内的下拉菜单被溢出切断...我总是将元素移动到正文,但似乎这不是React方式.

我认为这里的理想情况是将体内下拉开始.然后,您可以在单击事件和下拉列表之间传递消息.您可以使用回调在虚拟DOM上足够高,然后将道具一直更新到下拉列表以管理它的状态.或者只是使用一个好的'事件系统.