我正在学习ReactJS并尝试在其上构建一些应用程序。
当我尝试修改状态和渲染时,页面冻结,并且在组件变大时渲染完成之前无法执行任何操作。
我发现我可以shouldComponentUpdate用来优化代码,但是我想到的问题是:我可以使此渲染过程成为非阻塞的吗?因此,我可以告诉用户该页面正在处理一些繁重的执行工作,请等待,或者显示执行进度?或者,例如,如果用户可以取消实时编辑器的渲染,则如果用户编辑编辑器的内容,则“预览”部分将停止渲染旧内容并尝试渲染新内容而不会阻塞编辑器UI?
shouldComponentUpdate
这是繁重的示例代码:
<!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哪个用户可以取消渲染并清除所有框的按钮?
Start
Box
Cancel
这是一个很大的问题,也是一个理想的用例setTimeout,可以为该事件安排下一个事件循环的更新。
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个批次中,基本的包装盒组件不会阻塞,您可以轻松地将装载微调器扔到那里。