哈哈,打脸了-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有多快了,小项目没事,你试试搞个大的玩玩。真不需要优化的话那你就是最帅的地球人。


目录
相关文章
|
消息中间件 存储 Kafka
RabbitMQ、RocketMQ和Kafka全面对决,谁是最佳选择?
1、应用场景 1.RabbitMQ: 适用于易用性和灵活性要求较高的场景 异步任务处理:RabbitMQ提供可靠的消息传递机制,适用于处理异步任务,例如将耗时的任务放入消息队列中,然后由消费者异步处理,提高系统的响应速度和可伸缩性。 解耦系统组件:通过使用RabbitMQ作为消息中间件,不同的系统组件可以通过消息进行解耦,实现松耦合的架构,提高系统的可维护性和灵活性。 事件驱动架构:RabbitMQ的发布-订阅模式可以用于构建事件驱动架构,将系统中的事件作为消息发布到相应的主题,不同的消费者可以订阅感兴趣的主题进行相应的处理。
1872 2
|
负载均衡 应用服务中间件 Docker
Docker Service 创建
Docker Service 创建
|
编解码 API 开发工具
|
11月前
|
SQL 调度 数据库
开发YashanDB数据库?用 DBeaver for YashanDB 更顺手
数据库开发复杂易错,尤其在企业级场景中。为提升效率,YashanDB 团队基于 DBeaver 开源工具打造专属解决方案——DBeaver for YashanDB。它支持多类型数据库对象管理(表、视图、函数等),适配 YashanDB 特有表结构(HEAP、LSC),提供智能补全、语法高亮、SQL 调试等功能,让开发更高效流畅。推荐用于数据库应用开发团队、高频调试用户及中大型企业统一工具栈场景。
|
传感器 数据采集 存储
项目实战:嵌入式系统应用开发
项目实战:嵌入式系统应用开发
|
JavaScript
Vue3上传(Upload)
这是一个基于 Vue 3 的文件上传组件,提供了丰富的自定义选项,包括接受的文件类型、是否支持多选文件、上传数量限制、预览图片缩放规则等。组件还集成了多种功能,如拖拽上传、预览图片、自定义上传行为等,并支持不同类型的文件预览图标。组件使用了 `Space`、`Spin`、`Image` 和 `Message` 等子组件来实现多样化的布局和交互效果。此外,通过 `beforeUpload` 钩子可以对上传文件进行预处理,如限制文件大小和类型。整体设计简洁实用,适用于多种应用场景。
651 1
Vue3上传(Upload)
|
存储 关系型数据库 分布式数据库
[PolarDB实操课] 01.PolarDB分布式版架构介绍
《PolarDB实操课》之“PolarDB分布式版架构介绍”由阿里云架构师王江颖主讲。课程涵盖PolarDB-X的分布式架构、典型业务场景(如实时交易、海量数据存储等)、分布式焦点问题(如业务连续性、一致性保障等)及技术架构详解。PolarDB-X基于Share-Nothing架构,支持HTAP能力,具备高可用性和容错性,适用于多种分布式改造和迁移场景。课程链接:[https://developer.aliyun.com/live/253957](https://developer.aliyun.com/live/253957)。更多内容可访问阿里云培训中心。
325 0
[PolarDB实操课] 01.PolarDB分布式版架构介绍
|
存储 Linux 图形学
深度探索Linux操作系统 —— Linux图形原理探讨1
深度探索Linux操作系统 —— Linux图形原理探讨
578 7
|
存储 数据管理 测试技术
构建Python构建自动化测试框架(原理与实践)
当谈到软件质量保证时,自动化测试是一个不可或缺的步骤。Python作为一种简单易学的编程语言,具有丰富的测试框架和库,使得构建自动化测试框架变得相对简单。本文将介绍如何使用Python构建自动化测试框架,包括选择合适的测试框架、编写测试用例、执行测试和生成报告等方面。
构建Python构建自动化测试框架(原理与实践)
|
消息中间件 Java 中间件
Java面试题:解释分布式事务的概念,讨论常见的分布式事务解决方案。
Java面试题:解释分布式事务的概念,讨论常见的分布式事务解决方案。
331 1

热门文章

最新文章