哈哈,打脸了-react原来不是快

简介: 很多人都知道react很快,甚至觉得用react完全不用考虑性能问题。为什么这么人为呢?因为他有visual dom 啊,是不是吧。那visual dom是什么来着?当然咱们这里不说他是个什么玩意儿,咱们就来测下react到底快不快!

b958ce0edd9a529eb2b890ee71f70750_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

很多人都知道react很快,甚至觉得用react完全不用考虑性能问题。为什么这么人为呢?因为他有visual dom 啊,是不是吧。那visual dom是什么来着?当然咱们这里不说他是个什么玩意儿,咱们就来测下react到底快不快!

总不能上来就上代码吧。那多low。我怎么也得铺垫一下,给大家缓冲一下哈。

看我临时编个故事来,如果表达的有些尴尬请大家尽量挺住。实在挺不住,那就使劲鼓掌。很久很久以前,小黑和老白聊天,小黑说你这react东西就是好用啊,直接可以再js里写html,而且没有dom操作,总算是抛弃当前年的jq了,而且我随便怎么写都是渲染的那么快,这性能果然是快啊。老白深深叹了一口气,感觉这孩子没救了。react性能真的那么高吗?他比jq速度快?你这只是开发感受而已,况且你做的那个东西以为我不知道吗,一个页面上没几个东西,你就自己骗自己吧。老白是小黑的领导,当然是不敢直言反驳了,弱弱的回答一句这react的特点不就是挺快的吗。。。不过小黑没在说,他是挺聪明的自己赶紧去做个测试去了,到底是原生快还是react快。

小黑给自己定了两个测试维度【初次渲染、更新渲染】。

测试环境如下:

mac i5 8g 、chrome 68.0.3440、react 16.2

小黑的机器还可以啊。小土豪啊。


下面开始进行测试


首次数据渲染

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

react 代码先行 渲染1w

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>
    }
}

原生代码 渲染1w

//也是基于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>
    }
}

小黑鼓捣了半天,终于运行出结果来。【这家伙比较懒,得先弄react的环境

e93824b2a067c7d1e0bd14be9f08dfc1_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

看了结果之后,小黑有点呆了。竟然差距那么大。之前的主观判断还真是打脸啊,现在更疼了。

别急咱还没测完呢。


更新数据

点击其中一条数据后标题改变,咱们来看看执行需要多长时间,还是基于1w的数据,毕竟react的更新的思路和咱们以往的操作dom是不同的,所以有必要看下。

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')
            }
        });
    }


结果出炉了,这次小黑想死的心都有了,以后和老白见面了还有何脸面。

39c947b692dff04b380a1b026b9782ab_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg

上面只是react的耗时,原生的我没贴。我不好意思贴。想看结果自己运行昂。

小黑虽然脸疼,但是干的越来越带劲儿。

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

code哪里跑


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


结果发生了稍微的变化,但是小黑顿悟了。


a641e5f75105c74393276457eb5e90a1_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.jpg


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

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

小黑长叹一口气,react还真是让人脑瓜疼啊。还得继续研究啊。不巧的是碰到了老白,微微一笑然后走开,不带走一丝尘埃。


故事到此结束!


总结


其实很多时候我们虽然接受了一个新事物,但是我们对他的了解只是表面的肤浅的。更深层次的东西需要我们花更多的精力去探索。代码写的一般般,不过瑕不掩瑜哈,能说明问题。代码不重要,重要的是对他的认知和理解。从这里开始,不要再觉得react有多快了,小项目没事,你试试搞个大的玩玩。真不需要优化的话那你就是最帅的地球人。


目录
相关文章
|
2月前
|
前端开发 JavaScript Java
React 速通笔记
【7月更文挑战第17天】
35 1
|
4月前
|
资源调度 前端开发 网络架构
【掰开揉碎】React Router——React应用导航(一)
【掰开揉碎】React Router——React应用导航(一)
|
4月前
|
前端开发
【掰开揉碎】React Router——React应用导航(二)
【掰开揉碎】React Router——React应用导航(二)
|
4月前
|
前端开发 JavaScript
你可能需要的React开发小技巧!(下)
你可能需要的React开发小技巧!(下)
|
4月前
|
前端开发 API
你可能需要的React开发小技巧!(上)
你可能需要的React开发小技巧!(上)
|
11月前
|
编解码 前端开发 JavaScript
分享几个上千的React开源库助你玩转React
分享几个上千的React开源库助你玩转React
|
JavaScript 前端开发 算法
|
移动开发 前端开发 JavaScript
React系列(一) -邂逅React开发
我个人一直喜欢使用邂逅这个词,我希望每个人在和一个新技术接触的时候,都是一场美丽的邂逅。 而React本身绝对是优雅和美丽的,所以从这里开始,我们和React来一场美丽的邂逅吧!
154 0
React系列(一) -邂逅React开发
|
存储 缓存 JavaScript
React系列十五 - Redux(一)初见
在React的开发过程中,Redux对于我们是非常重要的。 但是对于很多人来说,初次接触redux会感觉redux的学习坡度非常陡峭,难度比较大。 在接下来,我会通过一个系列的方式循循渐进、层层深入的方式来讲解Redux:从redux的独立使用过程、到redux的结构划分、到redux结合react的过程、到redux中异步操作、到复杂数据的结构处理、到结合immutable的使用。 整个过程,都是在现有知识的基础之上层层递增、一步步掌握redux的使用!
149 0
React系列十五 - Redux(一)初见
|
前端开发 JavaScript Java
初窥 React Fiber
初窥 React Fiber
202 0
初窥 React Fiber