简测-react 性能 vs 原生js

1,410 阅读3分钟
闲来无事,想把以前一直想做的事验证一下,react的性能到底怎样?
和原生js相比呢?
下面老张从两个方面进行简单的测试
【数据渲染、数据更新】,
测试维度比较简单、结果仅供参考,欢迎交流拍砖!

测试环境

mac i5 8g 、chrome 68.0.3440、react 16.2

下面开始进行测试

测试1 数据渲染

渲染条数1w条,为什么是1w,数据量太小不容易看到差距,真实场景不会有这样的场景,都是通过分页展示很少的数据,所以得出的结果并不实际;

react 代码先行

import './performence.less';
import React,{Component} from 'react';
import TestItem from './components/TestItem';//子组件

export default class Performance extends Component{
    constructor(props){
        super(props);
        this.state={
            page:'性能测试',
            itemArr:[],//要渲染的数据列表
        }
    }

   init={
       max:10000,//渲染的条数
       initMountTime:0//初始时间毫秒
   }

    //填充数据 ,更改数据
    componentDidMount=()=>{
        this.init.initMountTime=+new Date();
        let max=this.init.max;
        let i=0;
        let itemArr=this.state.itemArr;
        for(;i<max;i++){
            itemArr.push({
                title:'我是第'+i+'项'
            });
        }
        this.setState({
            itemArr:itemArr
        })
    }

    //每一条数据单机事件,改变当前的title
    itemClick=(index)=>{
        let oldArr=this.state.itemArr;
        oldArr[index].title="我被选中了------"+index;
        this.setState({
            itemArr:oldArr
        })
    }

    componentWillUpdate=()=>{
        this.init.initMountTime=+new Date();
    }

    componentDidUpdate=()=>{
        console.log(this.init.max,'条react渲染所需时间',(+new Date()) - this.init.initMountTime,'ms');
    }

    render(){
        return <main className="common-con-top">
                
            {this.state.itemArr.map((item, index) => <TestItem key={index} title={item.title} index={index} itemClick={this.itemClick}></TestItem>)}
             </main>
    }
}

//子组件
import React  from 'react';

export default class TestItem extends React.Component{
    constructor(props) {
        super(props);
    }

    render(){
        return <div onClick={this.props.itemClick.bind(this, this.props.index)} className="testItem"><span>{this.props.title}</span></div>
    }
}

原生代码

//也是基于react 进行编写和初始化,只是数据项用原生渲染
 
import './performence1.less';
import React, { Component } from 'react';

export default class Performance1 extends Component {
    constructor(props) {
        super(props);
        this.state = {
            page: '性能测试',
            itemArr: []
        }
    }

    init = {
        max: 10000,
        initMountTime: 0 
    }
    //原生js生成数据项
    componentDidMount = () => {
        this.init.initMountTime = +new Date();
        let max = this.init.max;
        let i = 0;
        let html='';
        for (; i < max; i++) {
            html +='<div class="testItem"><span>我是第'+i+'项</span></div>'
        }
      
        document.getElementById('div_demo_id').innerHTML=html;
        console.log(this.init.max, '条原生渲染所需时间', (+new Date()) - this.init.initMountTime,'ms');
    }
    componentWillUpdate = () => {

    }

    componentDidUpdate = () => {
    }


    render() {
        return  <div id="div_demo_id"></div>
    }
}

请看测试结果

这个测试结果看似差距很大,但是实际情况不会有直接渲染1w条的情况,如果将数据量再缩小后,差距也存在,但是性能是可以接受的!

测试2 更新数据

点击其中一条数据后标题改变,咱们来看看执行需要多长时间,还是基于1w的数据

react 事件处理代码 以及 用时计算

itemClick=(index)=>{
        let oldArr=this.state.itemArr;
        oldArr[index].title="我被选中了------"+index;
        //oldArr.splice(index,1);
        this.setState({
            itemArr:oldArr
        })
    }
    componentWillUpdate=()=>{
        this.init.initMountTime=+new Date();
    }

    componentDidUpdate=()=>{
        console.log(this.init.max,'条react渲染所需时间',(+new Date()) - this.init.initMountTime,'ms');
    }

原生事件处理

 componentDidMount = () => {
        this.init.initMountTime = +new Date();
        let max = this.init.max;
        let i = 0;
        let html='';
        for (; i < max; i++) {
            html +='<div dataindex="'+i+'" class="testItem">我是第'+i+'项</div>'
        }
      
        document.getElementById('div_demo_id').innerHTML=html;
        console.log(this.init.max, '条原生渲染所需时间', (+new Date()) - this.init.initMountTime,'ms');
        
        document.getElementById('div_demo_id').addEventListener('click',(e)=>{
            if (e.target.nodeName === 'DIV'){
                e.target.innerHTML='我被选中了----'+e.target.getAttribute('dataindex')
            }
        });
    }

react 执行结果

原生的处理时间我没贴,因为使用的是事件代理 直接修改的当前的节点,耗时可以忽略不计了;

react的这个耗时貌似有点高,那有没有可以优化的手段呢? react其实已经提供了,那就是shouldComponentUpdate

看代码

// 在子组件内部增加一个方法 刚才咱们修改的是标题,那就通过标题来进行处理
 shouldComponentUpdate(nextProps,nextState){
        if(nextProps.title!==this.props.title){
            return true;
        }
        return false;
    }
// 下面在看下测试结果

进行简单的优化后性能有所提升,提升了50-70ms ,这也是我什么要提取一个子组件出来;

个人结论 通过上面的两个简单的测试,发现react性能和原生性能存在一定的差距,同时react提供我们可以优化的空间,react给到的是相对差不多的性能,并不是说虚拟dom比原生的快,只是react的组件化思想是一种全新得突破,让我们尽可能的少的操作dom,不用过多的考虑性能问题也能开发出性能差不多,过的去的应用;

仅供参考,欢迎交流和指正。