小编典典

ReactJS中的非阻塞渲染

reactjs

我正在学习ReactJS并尝试在其上构建一些应用程序。

当我尝试修改状态和渲染时,页面冻结,并且在组件变大时渲染完成之前无法执行任何操作。

我发现我可以shouldComponentUpdate用来优化代码,但是我想到的问题是:我可以使此渲染过程成为非阻塞的吗?因此,我可以告诉用户该页面正在处理一些繁重的执行工作,请等待,或者显示执行进度?或者,例如,如果用户可以取消实时编辑器的渲染,则如果用户编辑编辑器的内容,则“预览”部分将停止渲染旧内容并尝试渲染新内容而不会阻塞编辑器UI?

这是繁重的示例代码:

<!DOCTYPE html>

<html>

  <head>

    <meta charset="utf-8" />

    <title>React Tutorial</title>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>

  </head>

  <body>

    <div id="content"></div>

    <script type="text/babel">

      var Box = React.createClass({

        render: function() {

          return (

            <div>Box</div>

          );

        }

      });



      var CommentBox = React.createClass({

        getInitialState: function() {

          return {box_count: 5};

        },



        heavyLoadRender: function() {

          this.setState({box_count: 40000});

        },



        render: function() {

          var render_box = [];

          for (var i=0; i<this.state.box_count; i++) {

            render_box.push(<Box />);

          }

          return (

            <div>

              {render_box}

              <button onClick={this.heavyLoadRender}>Start</button>

            </div>

          );

        }

      });



      ReactDOM.render(

        <CommentBox />,

        document.getElementById('content')

      );

    </script>

  </body>

</html>

当我按时Start,页面将冻结,并且直到全部Box呈现后才响应。是否可以添加一个名为Cancel哪个用户可以取消渲染并清除所有框的按钮?


阅读 358

收藏
2020-07-22

共1个答案

小编典典

这是一个很大的问题,也是一个理想的用例setTimeout,可以为该事件安排下一个事件循环的更新。

与其存储要渲染的组件数量,不如存储一个组件数组并直接渲染它们。
jsfiddle

 var CommentBox = React.createClass({
    getInitialState: function() {
      return { boxes: [<Box key="first" />] };
    },

    heavyLoadRender: function() {
      setTimeout(() => {
        if (this.state.boxes.length < 50000) {
          this.setState({ 
            boxes: this.state.boxes.concat(<Box key={this.state.boxes.length} />)
          })
          this.heavyLoadRender()
        }
      })
    },

    render: function() {
      return (
        <div>
          <button onClick={this.heavyLoadRender}>Start</button>
          {this.state.boxes}
        </div>
      )
    }
  })

更新:

如果只想在阵列填满后显示状态,则在达到该大小之前不显示任何内容:

这不起作用:

{ this.state.boxes.length === 50000 && this.state.boxes }

希望并没有失去!使用风格!

<div style={{ display: this.state.boxes.length === 50000 ? 'block' : 'none' }}>
  { this.state.boxes }
</div>

如果要提高速度,则可以按 setTimeout

var newBoxes = []
for (var i = 0; i < 5; i++) {
   newBoxes.push(<Box />)
}
this.setState({ 
  boxes: this.state.boxes.concat(newBoxes)
})

更新小提琴。我认为整个问题类别都需要花费一些时间来执行。在10,000个批次中,基本的包装盒组件不会阻塞,您可以轻松地将装载微调器扔到那里。

2020-07-22