閒來無事,想把之前一直想作的事驗證一下,react的性能到底怎樣?
和原生js相比呢?
下面老張從兩個方面進行簡單的測試
【數據渲染、數據更新】,
測試維度比較簡單、結果僅供參考,歡迎交流拍磚!
複製代碼
mac i5 8g 、chrome 68.0.3440、react 16.2html
渲染條數1w條,爲何是1w,數據量過小不容易看到差距,真實場景不會有這樣的場景,都是經過分頁展現不多的數據,因此得出的結果並不實際;node
react 代碼先行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>
}
}
複製代碼
原生代碼chrome
//也是基於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>
}
}
複製代碼
請看測試結果bash
這個測試結果看似差距很大,可是實際狀況不會有直接渲染1w條的狀況,若是將數據量再縮小後,差距也存在,可是性能是能夠接受的!less
點擊其中一條數據後標題改變,我們來看看執行須要多長時間,仍是基於1w的數據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')
}
});
}
複製代碼
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,不用過多的考慮性能問題也能開發出性能差很少,過的去的應用;
僅供參考,歡迎交流和指正。