React: 在 componentDidUpdate 中操作 DOM

创建于 2016-09-23  ·  3评论  ·  资料来源: facebook/react

嗨,这更像是一个问题,我想就componentDidUpdate DOM 操作展开讨论。

我正在创建一个 React 插件。 它必须做一些 DOM 计算,因为 CSS 不够强大,无法涵盖这个插件需要做的一切。 问题是我需要根据由同一组件呈现的其他一些 DOM 元素的 getBoundingClientRect() 的返回值来调整一些 CSS 属性

所以从技术上讲,我们有 3 个选择:

1) 在componentDidUpdate计算getBoundingClientRect并用计算值调用setState 。 我害怕在某些情况下可能发生无限循环,所以我不会选择这个。

2) 像在 1) 中那样做,并用shouldComponentUpdate玩一下,但这看起来非常复杂且不可读。 会弹出许多取决于特定用例的问题。

3) 从 componentDidUpdate 更新 DOM。 这是我决定采用的解决方案,它有效,简单,稳定并且按预期工作。 但是我觉得我处于边缘,所以我想仔细检查一下这是一种可以做事的方式。 可以在componentDidUpdate操作 DOM 吗? 每次完成render都会调用它,我可以放弃我的更改,因为接下来的render我将再次修改 DOM。

这是代码的一部分

componentDidMount() {
  this.recalculateIndent();
}

componentDidUpdate() {
  this.recalculateIndent();
}

recalculateIndent() {
  // calculate indent based on getBoundingClientRect of some DOM reference
  this.textareaRef.style.textIndent = `${indent}px`;
}

render() {
   return (
   ...
   <textarea ref={ref => this.textareaRef = ref}/>
   ...
   );
}

最有用的评论

@jvorcak使用componentDidUpdate是在渲染后手动操作 DOM 的正确位置。 根据文档:

以此为契机,在组件更新后对 DOM 进行操作。

此外,我们尝试仅将问题跟踪器用于功能请求和错误报告。 使用问题应该指向其他地方,比如Discussion.reactjs.org或 StackOverflow。 谢谢!

所有3条评论

每种解决方案(组件生命周期方法)都适合具体情况,但DOM操作是错误的。 使用状态并重新渲染组件。 我上一个用例“固定表头+表体虚拟滚动”的示例,我希望这能帮助您理解正确的流程。

  1. 组件构造函数:初始状态值:bodyHeight = 0(或为空,随你喜欢)。
  2. 第一次渲染,渲染表头但表体为空(0 行)。
  3. componentDidMount - 读取标题和容器 DOM 高度(+ 一些计算...)和 bodyHeight 的 setState(重新渲染)。
  4. 第二次渲染,bodyHeight !== 0,表格主体将被渲染。 现在,高度参数是已知的(我可以使用“样式”组件属性设置它,而不是 DOM 操作),我可以为行添加组件。
  5. “调整大小”(文档/浏览器调整大小)的附加事件侦听器,在 componentDidMount 中添加,在 componentWillUnmount 中删除。 在事件处理程序中,我做与 componentDidMount 相同的事情 - 读取新的 DOM 高度值和 setState。
  6. 没有手工操作 DOM,react 可以完成这项工作。

@jvorcak使用componentDidUpdate是在渲染后手动操作 DOM 的正确位置。 根据文档:

以此为契机,在组件更新后对 DOM 进行操作。

此外,我们尝试仅将问题跟踪器用于功能请求和错误报告。 使用问题应该指向其他地方,比如Discussion.reactjs.org或 StackOverflow。 谢谢!

如果您想在更改另一个组件后更新一个组件怎么办?

此页面是否有帮助?
0 / 5 - 0 等级