javascript - 如何提高Reactjs中大状态的性能?

标签 javascript reactjs

这是我在react中写的。它叫做生命游戏。

我将一个单元格设置为div,并将所有单元格存储在一个state对象中,每个单元格的单元格名称类似于“0_0”,“0_1”,“0_2"....并拥有自己的存活状态和邻居。所以 App state 看起来像这样:

enter image description here

我做了一个时间循环来检查每个单元格的状态。

但正如您所看到的,尽管在这种情况下没有那么多单元格,但它的性能非常差。

我认为虚拟 dom 会获得良好的性能。

那么在这种情况下如何提高性能呢?

   
class Cell extends React.Component {
    constructor(props) {
        super(props);
    }
    shouldComponentUpdate(nextProps, nextState) {
        return nextProps.alive !== this.props.alive;
    }

    render() {
        let className = ['life'];
        if (this.props.alive) {
            className.push('alive');
        }

        return (
            <div className={className.join(' ')}></div>
        );
    }
}

let lifeSize = 5;
let w = 150;
let h = 150;
let chance = 0.75;
let stopTime = 333;
class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
        //this.cellsDiv=[];
        //console.log(store);
        this.checkAlive = this.checkAlive.bind(this);
        this.tick = this.tick.bind(this);
        this.runTime = 1;


        //per_width = per_width < 5 ? 10 : per_width;
        for (let i = 0; i < parseInt(h / lifeSize); i++) {
            for (let j = 0; j < parseInt(w / lifeSize); j++) {
                let neighborCells = [];
                neighborCells.push((i - 1) + '_' + (j - 1));
                neighborCells.push((i - 1) + '_' + (j + 1));
                neighborCells.push((i + 1) + '_' + (j - 1));
                neighborCells.push((i + 1) + '_' + (j + 1));
                neighborCells.push(i + '_' + (j - 1));
                neighborCells.push(i + '_' + (j + 1));
                neighborCells.push((i + 1) + '_' + j);
                neighborCells.push((i - 1) + '_' + j);
                this.state[i + '_' + j] = {};
                this.state[i + '_' + j]['alive'] = (Math.random() > chance);
                this.state[i + '_' + j]['neighbor'] = neighborCells;
            }
        }



    }
    checkAlive(cellName) {

        //console.log(neighborCells);
        let o = this.state[cellName];
        //console.log(i,j);
        let neighborCells = o['neighbor'];

        let alivecount = 0;
        for (let cell in neighborCells) {
            //console.log(neighborCells[cell],this.state[neighborCells[cell]]);
            if (this.state[neighborCells[cell]]) {
                if (this.state[neighborCells[cell]]['alive']) {
                    alivecount++;
                }
            }
        }
        //let alive = this.state[i + '_' + j]['alive'];
        //console.log(alive,alivecount);
        if (o['alive']) {
            if (alivecount < 2 || alivecount > 3) {
                o['alive'] = false;
            }
        } else {
            if (alivecount == 3) {
                o['alive'] = true;
            }
        }
        //console.log(o);
        let cells = {};
        cells[cellName] = {};
        cells[cellName]['alive'] = o['alive'];
        cells[cellName]['neighbor'] = o['neighbor'];
        this.setState(cells);
    }


    tick() {
        //console.log(this.runTime,stopTime);
        if (this.runTime >= stopTime) {
            clearInterval(this.timer);
        }
        
        //console.log(this.state);
        for (let cellName in this.state) {
            this.checkAlive(cellName);
        }

		this.runTime++;
        //console.log(this.state);
        //this.setState({alive:alive});
    }

    componentDidMount() {
        this.timer = setInterval(this.tick, 1000);
    }

    componentWillUnmount() {
        clearInterval(this.timer);
    }

    render() {
    
        return (
            <div id="show">
            { Object.keys(this.state).map((k, index) => <Cell key={k} alive={this.state[k]['alive']}/>) }
			
			</div>
        );

    }
}

ReactDOM.render(
    <App/>,
    document.getElementById('app')
);
#show {
  width: 150px;
  height: 150px;
  border: 1px solid black;
  xbackground: #f0f0f0;
  margin: 0;
  padding: 0;
}
.life {
  width: 5px;
  height: 5px;
  xborder: 1px solid black;
  background: white;
  float: left;
  xmargin: 1px;
}
.alive {
  background: black;
}
body {
  margin: 0;
  padding: 0;
  xbackground: black;
}
<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="app"></div>

最佳答案

您正在为每个单元格调用 this.setState。

每次调用 this.setState 时,都会调用 render。您应该推迟此通话。

类似这样的事情:

let newState = {};
for (let cellName in this.state) {
    newState = {...newState, this.checkAlive(cellName)}; //remember removing the setState from checkAlive
}
this.setState(newState);

关于javascript - 如何提高Reactjs中大状态的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41297504/

相关文章:

jquery - WordPress/Elementor 实现类似 React 的 Framer's Motion 的页面过渡效果

jquery - React-Redux 中的简单背景颜色更改

javascript - JavaScript 中 reduceRight 的原生实现是错误的

JavaScript,检查嵌套对象属性是否为 null/undefined 的优雅方式

javascript - 非常简单的事件驱动 jQuery 插件设计模式

javascript - Bootstrap 表在 Jsfiddle React 代码中无法正确显示

css - 在 React 中使用 webpack 和 url-loader 加载内嵌图片

javascript - React 和 React Native 意义上的父组件和子组件是什么意思?

javascript - 如何渲染 jquerymobile 页面?

javascript - 从 Highcharts 工具提示中删除 UTC 日期