在 react 中,默認改變組件狀態或者屬性,是會整個組件所有從新渲染,可是 若是隻是修改一個地方,而所有渲染,就會浪費資源,大項目中會形成性能問題css
shouldComponentUpdatereact
shouldComponentUpdate 在 react生命週期中就是控制是否從新渲染組件的方法,而該方法默認返回true, 這意味着就算沒有改變組件的props或者state,也會致使組件的重繪。這就常常致使組件由於不相關數據的改變致使重繪,這極大的下降了React的渲染效率,這個問題,能夠測試出來的git
PureComponent 和 Component 的區別github
React.PureComponent 與 React.Component 幾乎徹底相同,但 React.PureComponent 會自動經過props和state的淺對比來控制是否從新渲染組件npm
若是在 PureComponent 組件中,重寫了 shouldComponentUpdate 方法 會根據 shouldComponentUpdate方法返回值判斷是否從新渲染segmentfault
PureComponent 優缺點api
優勢: 不須要開發者本身實現shouldComponentUpdate,就能夠進行簡單的判斷來提高性能。數組
缺點:可能會因深層的數據不一致而產生錯誤的否認判斷,從而shouldComponentUpdate結果返回false,界面得不到更新。less
例如:性能
在父組件中,給子組件 傳一個數組對象 var data = [{name:'zs',age: 23},{name:'ls',age: 26}],子組件用這個data 去渲染數據,
而後在父組件中 修改data,例如 data[0].age = 1, data.push({name:'ww',age: 30}), 這一系列操做,在 PureComponent 下,子組
件是不會更新的,可是咱們的數據倒是更改了,這就是它的弊端,在簡單數據類型是能夠的,引用類型數據的比較,會出現問題。
這個時候要優化渲染 就要用到 seamless-immutable
具體看這2個網站
https://www.npmjs.com/package/seamless-immutable
https://segmentfault.com/a/1190000010438089
這裏記錄下部分 使用api
// 一下2種方式 功能是相同的, 把js 的數據類型轉化成 不可改變的數據類型 Immutable.from([1, 2, 3]); let arr = Immutable([1, 2, 3]); // 轉成可修改的數據,才能夠修改數據 let data = Immutable.asMutable(arr) // 數組 data.push(5) //添加元素 data[0] = {name: "we", age: 10} // 對象 // 對象賦值 var obj = {}; let newObj = Immutable.setIn(obj, ['key'], data) var obj = {}; let newObj = obj.setIn(['key'], data)
shouldComponentUpdate 方法 配合 seamless-immutable 使用,就能夠控制複雜複雜數據類型的更新渲染了
父組件:
import React, { Component } from 'react'; import { connect } from 'dva'; import Immutable from 'seamless-immutable'; import styles from './IndexPage.css'; import Example from "../components/Example.js" class IndexPage extends Component{ constructor(props){ super(props) this.state = { flg: true, arr: Immutable.from([{name:'zs',age: 23},{name:'ls',age: 26}]) } } // handClick = () => { let { flg} = this.state this.setState({ flg: !flg }) } handClick1 = () => { const {arr} = this.state;
// 轉換成可修改的數據 let data = Immutable.asMutable(arr) let obj = data[0] //數組能夠直接賦值修改, 對象須要 setIn 方式修改,不可直接賦值修改,返回一個新對象 data[0] = obj.setIn(["age"], 99) console.log(data[0]) data.push({name:'ww',age: 30}) this.setState({ arr: Immutable(data) }) } render(){ const { flg, arr } = this.state; return( <div className={styles.normal}> <h1 className={styles.title} onClick={this.handClick}>Yay! Welcome to dva!</h1> <h1 className={styles.title} onClick={this.handClick1}>Yay! Welcome to dva!</h1> <div className={styles.welcome} /> { flg ? <ul className={styles.list}> <li>To get started, edit <code>src/index.js</code> and save to reload.</li> <li><a href="https://github.com/dvajs/dva-docs/blob/master/v1/en-us/getting-started.md">Getting Started</a></li> </ul> : "" } <Example data={arr}/> </div> ) } } IndexPage.propTypes = { }; export default connect()(IndexPage);
子組件:
import React, { Component } from 'react'; class Example extends Component{ constructor(props){ super(props) this.state = { } } shouldComponentUpdate(nextProps, nextState){ if (this.props.data == nextProps.data) { return false } return true } render(){ const { data } = this.props return( <div> { data.map((item,i)=> <div key={i}> <span>{item.name}</span> <span>{item.age}</span> </div> ) } </div> ) } } Example.propTypes = { }; export default Example;