初始渲染后极长的反应脚本冻结程序

时间:2017-03-03 18:27:37

标签: javascript html reactjs

我正在努力使用ReactJS创建Conway的生命游戏重制版。到目前为止,我只渲染了160个cols 120行的静态游戏区域,共计19,200个小div。

董事会好像很快就会出现问题,但由于某种原因,程序会挂起(在我将它放在一起的CodePen)一整分钟。当我查看Chrome开发工具(我还是非常新的)时,它似乎显示了一些渲染,然后如果编写完整的堆脚本则需要一分钟,然后再进行另一次快速渲染。脚本的键上给出的颜色与Listeners的颜色相同。

我不确定是什么可以挂起来,因为此时我的反应App中的所有内容都是静态的并且相对简单。

此设置是否有19,200个小div太多了?似乎不太可能。或者在分配大量事件监听器时,这个东西是否会冻结?我该如何解决这个问题?

请帮忙。我真的需要了解背景中发生的事情。 对任何有回答的人都有好的帮助,可以帮助我自己下次解决类似的问题。

/**
 *	@desc React Class Field renders game field
 *	@param {Array} state.fieldE - even iteration game board array
 *	@param {Array} state.fieldO - odd iteration game board array
 *	@param {Sting} props.config - default undefined. Name sets initial field config
 *	@param {Boolean} props.continue - Field continues to iterate while continue true
 *	@param {Number} props.speed - sets time between iterations
 *	@param {Number} props.zoom - sets board zoom in parent container
 *	@param {LifeGame~Callback} props.onReset - reset field and toggle parent reset state
 *	@param {LifeGame~Callback} props.incGen - reset field and toggle parent reset state
 *	@returns {HTML} playable game field
 */
class Field extends React.Component {
    constructor(props) {
      super(props)
      this.onReset = this.onReset.bind(this);

      this.state = ({
        fieldE: undefined,
        fieldO: undefined,
      });
    }

    ///Sets fieldE and fieldO in state to zero-filled arrays
    onReset() {
      const fieldE = [];
      fieldE.length = 19200;
      let i = 0;
      while (i < 19200) fieldE[i] = 0, i++;
      const fieldO = [...fieldE];

      this.setState({
        fieldE,
        fieldO
      });
    }

    componentWillMount() {
      this.onReset();
    }

    render() {
      console.log('props: ', this.props);
      console.log('state: ', this.state);

      //Converts appropriate field array to HTML for output
      const evenGen = (this.props.generation % 2 === 0);
      const fArr = evenGen ? [...this.state.fieldE] : [...this.state.fieldO];
      let len = fArr.length;
      let cols = Math.sqrt(4 / 3 * len);
      let field = fArr.map((el, i) => {
          if (i + 1 % cols === 0) {
            return <span id = 'f'
            className = 'c' > < /span>}
            return <span className = 'c' > < /span>;
          });
        let outField = [],
          i = 0,
          j = 0; outField.length = cols;

        //uses outField to separate field into rows encapsulated by divs
        while (j < len) {
          outField[i] = < div className = 'r' > {
            field.slice(j, j + cols)
          } < /div>;
          j += cols;
          i++;
        }

        return ( <
          div class = 'game-field' > {
            outField
          } <
          /div>
        );
      }

    }

    //Calls Field for render
    class LifeGame extends React.Component {
      constructor(props) {
        super(props);

        this.state = {
          config: undefined,
          isContinue: false,
          speed: 1,
          zoom: 0,
          generation: 0,
        }
      }

      render() {

        return ( <
          Field config = {
            this.state.config
          }
          isContinue = {
            this.state.continue
          }
          generation = {
            this.state.generation
          }
          speed = {
            this.state.speed
          }
          zoom = {
            this.state.zoom
          }
          />
        );
      }
    }

    ReactDOM.render( <
      LifeGame / > ,
      document.getElementById('root')
    );
html,
body,
div,
span,
ul,
ol,
h1,
h2,
h3,
h4 {
  margin: 0;
  padding: 0;
}

.game-field {
  display: flex;
  flex-shrink: 1;
  row-wrap: nowrap;
}

.c {
  display: inline-block;
  flex-shrink: 0;
  height: 4px;
  width: 4px;
  border-left: 1px solid rgba(192, 192, 192, 0.4);
  border-bottom: 1px solid rgba(192, 192, 192, 0.4);
  background: black;
  margin: 0;
  padding: 0;
}

.r {
  display: flex;
  flex-direction: row;
  flex-shrink: 1;
  flex-grow: 0;
  row-wrap: nowrap;
  position: relative;
  text-align: center;
  background: rgba(255, 255, 150, 0.6);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root">
  <!-- This div's content will be managed by React. -->
</div>

(编辑) 另外, 如果事实证明19,200个div太多了(即使它们快速渲染),其他人如何将游戏板与时间元素放在一起?我怎么能这样做?

看起来像React在渲染后执行querySelectorAll和CalculateNewProcessedItemsBySelector。这些似乎是Chrome DevTool的暗示,但如果是,我不知道该怎么做。

也许DevTool时间轴的图片会有用enter image description here

带有常量计算和查询选择器的事件日志,似乎没有运行我能看到的任何内容。 enter image description here

1 个答案:

答案 0 :(得分:0)

我刚刚注意到几年前的这个问题从未有人回答过。我对这个原始问题的解决方案——以及大多数人第一次遇到他们试图添加太多 html 元素的项目的解决方案——是使用 html5 canvas