首页 文章

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

提问于
浏览
58

这就是我在做的事: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似乎没有移动内容(如果我删除 componentWillUpdatecomponentDidUpdate ,定位元素仍然更新!)

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

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

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

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

  • 即使你将DOM移动到文档中的其他位置,React也会更新它渲染的DOM!

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

2 回答

  • 16

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

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

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

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

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

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

    记住这一点:

    只要您将DOM放回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上足够高,然后将道具一直更新到下拉列表以管理它的状态 . 或者只是使用一个好的'事件系统 .

  • 55

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


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

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

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

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

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

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

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

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


    从广义上讲,你不应该在React中创建一个空的 <div> 并用手填充它 . 它后来尝试在React中更改其属性(导致React执行DOM更新),但是如果移动一个元素,React可能会查找它并在无法找到它时感到困惑 .

    希望有所帮助 .

相关问题