【问题标题】:When and in what order does React update the DOM?React 何时以及以什么顺序更新 DOM?
【发布时间】:2019-11-27 17:10:22
【问题描述】:

我无法理解 React 更新 DOM 的确切时间。

注意:我在下面的示例中使用styled-components

看这个例子:

代码沙盒:https://codesandbox.io/s/elegant-dirac-j6e54

它显示了容器的max-height 属性的转换。

它按预期工作。我只是不知道为什么它有效。

代码:

两个列表:

  • shortList需要高度的70px
  • longList需要高度的124px
const shortList = ["Item 1", "Item 2", "Item 3"];
const longList = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"];

我有一个名为ListContainerDIVstyled-component 容器,它将根据props 处理转换。道具名称为idealHeight

const ListContainerDIV = styled.div`
  overflow: hidden;
  max-height: ${props => props.idealHeight + "px"};
  transition: max-height ease-out .5s;
`;

应用组件

function App() {

  // STATE TO KEEP LIST AND REF FOR THE CONTAINER DIV ELEMENT
  const [list, setList] = useState(shortList);
  const containerDiv_Ref = useRef(null);

  // FUNCTION TO TOGGLE BETWEEN LISTS FROM BUTTON CLICK
  function changeList() {
    setList(prevState => {
      if (prevState.length === 3) {
        return longList;
      } else {
        return shortList;
      }
    });
  }

  // CALCULATING THE IDEALHEIGHT DURING THE RENDER
  let idealHeight = null;

  if (list.length === 3) {
    idealHeight = 70;
  } else if (list.length === 6) {
    idealHeight = 124;
  }

  // RETURNING THE LISTCONTAINER WITH THE `idealHeight` PROP
  return (
    <React.Fragment>
      <button onClick={changeList}>Change List</button>
      <ListContainerDIV ref={containerDiv_Ref} idealHeight={idealHeight}>
        <ListComponent list={list} />
      </ListContainerDIV>
    </React.Fragment>
  );
}

列表组件

这是一个渲染&lt;ul&gt;&lt;li&gt;'s的简单组件

function ListComponent(props) {
  const listItems = props.list.map(item => <li key={item}>{item}</li>);
  return <ul>{listItems}</ul>;
}

问题

如果我在呈现列表之前就设置了组件的max-height,这种转换如何工作?我的意思是,idealHeight 是在 App 渲染期间设置的。我在想 longList 将在一个已经有 max-height = 124 的容器中呈现?如果发生这种情况,我们就不会看到过渡,对吧?

React 在这种情况下运行的事件顺序是什么?

显然它会先更新&lt;ul&gt;&lt;li&gt;'s,然后再从styled-component 容器更新div

内部组件的元素总是在外部组件的元素之前更新?


更新

刚刚发现 Dan Abramov 关于这个主题的这些推文:

https://twitter.com/dan_abramov/status/981869076166344704

【问题讨论】:

    标签: javascript reactjs react-hooks styled-components


    【解决方案1】:

    关于虚拟dom的计算,先渲染父组件,然后渲染子组件,再渲染子组件,以此类推。所有这些都使用 state 和 props 的最新值,因此 App 和各种子组件都知道列表更长。这个虚拟 dom 只是对您希望页面外观的内存描述。

    计算完虚拟 dom 后,react 会将之前的虚拟 dom 与新的虚拟 dom 进行比较,找出发生了哪些变化。在这种情况下,它发现有一个新的样式需要添加到 div 中,以及一些新的 li 需要插入到 ul 中。这些应用的确切顺序是一个实现细节,但它们是同步应用的,浏览器无法在两者之间进行绘制,因此不妨同时应用。

    【讨论】:

    • 谢谢!是否确定 DOM 更新是同步的,并且浏览器仅在它们全部完成后才绘制?
    • 是的,react 的提交阶段(我的第二段)保证是同步的。
    【解决方案2】:

    传递给 useState 的参数,在本例中为 shortList,是初始状态。所以第一次渲染ListContainerDIV时,是基于列表长度为3,所以ideaHeight = 70

    【讨论】:

    • 对不起,如果我不清楚。我明白了。第二个渲染(当列表更新时)是我没有得到的。如果我在呈现ListComponent 之前就设置了max-height,那么过渡如何工作?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 2015-12-19
    • 1970-01-01
    • 2017-07-02
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多