3

我希望具有大量内容的网页具有最佳性能。特别有趣的是,在移动设备上,我希望用户尽快看到首屏内容,然后让应用程序尽快启动。

我有一个在浏览器环境中但在服务器环境中isBrowser的变量。考虑以下渲染函数:truefalse

render() {
  return (
    <div>
      <ContentAboveTheFold />
      { isBrowser && <ContentBelowTheFold /> }
    </div>
  )
}

请注意,通过render()这种方式构建,服务器要渲染的标记更少,通过网络传输的数据更少,浏览器在第一次通过时要渲染的标记也更少。

这工作正常,但在控制台反应警告

React 尝试在容器中使用重用标记,但校验和无效。这通常意味着您正在使用服务器渲染,并且在服务器上生成的标记不是客户端所期望的。React 注入了新的标记来补偿哪些工作,但是您已经失去了服务器渲染的许多好处。相反,要弄清楚为什么生成的标记在客户端或服务器上是不同的。

在服务器上,React 使用作为属性嵌入到顶级元素(例如 ex data-react-checksum="941190765")中的校验和来呈现标记。然后在客户端,react 在第一次渲染后计算校验和,如果它与服务器的校验和不同,它会完全丢弃服务器生成的标记并用客户端生成的标记替换它。

作为一种解决方法,我发现在我的顶级组件的componentDidMount生命周期方法中,我可以在下一个动画帧上安排以下操作:

componentDidMount() {
  requestAnimationFrame(() => {
    appIsMounted = true;
    this.forceUpdate();
  });
}

然后我可以像这样编写我的渲染方法并且反应没有产生任何关于校验和的警告:

render() {
  return (
    <div>
      <ContentAboveTheFold />
      { appIsMounted && <ContentBelowTheFold /> }
    </div>
  )
}

这样做有什么明显的性能优势吗?无论哪种情况,首屏内容都会以同样快的速度出现,对吧?额外的复杂性是否合理?

4

1 回答 1

4

是的,使用 requestAnimationFrame/setTimeout 进行更新是正确的方法。

不过,我会将其置于状态,而不是使用变量和 forceUpdate。

于 2015-02-14T21:53:35.690 回答