React性能優化心得


本文是《深入React技術棧》讀書筆記,其中的很多都已經運用到實際項目中
更多筆記可以star我的github,上面基本都是平時的學習筆記,以及項目中的實踐心得,歡迎關注

影響網頁性能一個較大的因素是瀏覽器的重繪reflow和重排版repaint
我們通過拆分組件為子組件,進而對組件進行更細粒度的控制。這也是函數式變成的魅力之一,保持純凈的狀態;可以讓方法和組件更加專注,體積更小,更獨立,更有復用性和測試性

PureRender的本質

官方提供了react-addons-pure-render-mixin的插件,其原理為重新實現shouldComponentUpdate的方法,當前的stateprops與之前做淺比較,如果返回fales,就不會調用render方法
但是默認的shouldComponentUpdate方法是默認的深比較。但是深比較的代價十分昂貴,就如下面的代碼

shouldComponentUpdate(nextProps, nextState) {
    return isDeepEqual(this.props, nextProps) && isDeepEqual(this.state, nextState);   
}

然而PureRender只對值進行了淺比較,以下是shollowEqual的示例代碼

function shallowEqual(obj, newobj) {
    if(obj === newobj) {
        return true;
    }
}
const objkeys = Object.keys(obj);
const newobjkeys = Object.keys(newobj);
if(objkeys.length !== newobjkeys.length) {
    return false;
}

// 以下是關鍵代碼
return objkeys.every(key => {
    return newobj[key] === newobjkeys[key];
})

運用PureRender

利用createClass構建組件時,可以使用官方插件react-addons-pure-render-mixin

import PureRenderMixin from 'react-addons-pure-render-mixin';
class App extends Component {
    constructor(props) {
        super(props);
        this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
    }
    return <div className={this.props.className}>foo</div>
}

優化PureRender

  • 直接將props設置為對象或者數組

我們知道,每次調用React組件其實都會重新創建組件。就算傳入的數組或對象的值沒有改變,他們引用的地址也會改變

<Account style={{color: 'red'}} />

這樣設置的props每次渲染都會創建新對象。這樣的操作,我們只需要提前將其賦值為常量,不直接使用字面量即可

const defaultStyle = {};
<Account style={this.props.style || defaultStyle} />
  • 設置props方法並通過事件綁定在元素上面
// 事件綁定寫入到構造函數中
constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
}
  • 設置子組件
const NameItem = () => <Item><span>Arthur</span></Item>;
// 上面的組件翻譯過來其實是
const NameItem = () => 
    <Item 
        children={React.createElement('span', {}, 'Arthur')}
     />

顯然上面Item組件不管什么情況下都會直接渲染,那么如何避免這種情況

import React, {Component} from 'react';
import PureRenderMixin from 'react-addons-pure-render-mixin';

class NameItem extends Component {
    constructor(props) {
        super(props);
        this.shouldComponentUpdata = PureRenderMixin.shouldComponentUpdate.bind(this);
    }
    render() {
        return (
            <Item><spanArthur</span>></Item>
        )
    }
}

Immutable

Immutable Data就是一旦被創建,就不能更改的數據,對Immutable Data對象進行修改添加或者刪除操作,都會返回一個Immutable對象,實現的原理就是持久化數據結構。
Immutable使用舊數據創建新數據時,要保證舊的數據可用但是不可變,同時為了避免將所有的節點都復制一遍帶來的性能損耗,Immutable使用結構共享,即如果對象樹中一個節點發生變化,只修改這個節點和它受影響的父節點

  • Map 鍵值對的集合,對應於Object,ES6也有專門的Map對象
  • List 有序可重復對象,對應於Array
  • ArrayList 無序不可重復列表

Immutable.is

為了直接比較兩個對象的值,可以使用Immutable.is來作比較

let map1 = Immutable.Map({a: 1, b:2});
let map2 = Immutable.Map({a: 1, b:2});
Immutable.is(map1, map2); // true

Immutable.is比較的是兩個對象的hashCode或valueOf,由於immutable內部使用了trie數據接口來存儲,只要兩個對象的hashCode相等,值就是一樣的,這樣做的效率非常之高

react-addons-create-fragment

當有兩個子組件需要渲染時,我們沒辦法給他設置key。這個時候可以使用官方提供的插件

import React, {Component}   from 'react';
import {render}             from 'react-dom';
import createFragment       from 'react-addons-create-fragment';

const first = <li>first</li>;
const second = <li>second</li>;

const Rank = ({first, second}) => {
    const children = createFragment({
        first,
        second
    });
    return <ul>{children}</ul>;
};

render(<Rank first={first} second={second} />, document.getElementById('app'))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM