Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PureComponent && immutable #9

Open
RachelRen opened this issue Aug 2, 2018 · 0 comments
Open

PureComponent && immutable #9

RachelRen opened this issue Aug 2, 2018 · 0 comments

Comments

@RachelRen
Copy link
Owner

PureComponent

PureComponent可以减少不必要的 render 操作的次数,从而提高性能,而且可以少写 shouldComponentUpdate 函数,节省了点代码。

class Normal extends Component {
	state = {
	    items: [1, 2, 3]
	}
	handleClick = () => {
	    const { items } = this.state;
	    items.pop();
	    this.setState({ items: [].concat(items) });
	}
	render(){
		return (
			<div> Normal
		      <ul>
		        {this.state.items.map(i => < li key={i}>{i}< /li>)}
		      </ul>
		      <button onClick={this.handleClick}>delete< /button>
		      <Child />
		    </div>
		)
	}
}

像上面那种情况,如果改变了state的值,但是Child这个子组件也会去render一下的。但是Child压根就没有改变。

如果用PureComponent的话,如果state的值改变了,子组件是不会用render的。

原理

当更新组件时,如果组件中的propsstate都没有发生改变,那么render方法是不会触发的,省去了Virtual DOM的生成和比对过程,达到性能提升。

if (this._compositeType === CompositeTypes.PureClass) {
  shouldUpdate = !shallowEqual(prevProps, nextProps)
  || !shallowEqual(inst.state, nextState);
}

shallowEqual又做了什么呢?


使用中的优化

不变数据使用一个引用

函数属性

如果从父组件中传一个方法过来,传方法的方式有多种,

< MyInput onChange={e => this.props.update(e.target.value)} />
//或者
update(e) {
  this.props.update(e.target.value)
}
render() {
  return < MyInput onChange={this.update.bind(this)} />
}

每次父组件render的时候,因为MyInput中的引用函数都返回一个新的函数,引用地址不一样,那么子组件就会相应的render一下。所以需要给成下面这种方式。

update = (e) => {
  this.props.update(e.target.value)
}
render() {
  return < MyInput onChange={this.update} />
}

空对象或空数组

当传一个对象到子组件的时候,如果这个对象为null,为了容错,那么会给这个对象赋值为空对象,有时候会这样实现.

< Item store={this.store} key={k} id={k} data={i || {}} />)

这样的问题会使如果他一直是null,那么{} ==={}是false的,这样子组件又需要重新render了。

这种情况最好设置一个defaultValue,

defaultValue = {}
< Item store={this.store} key={k} id={k} data={i || defaultValue} />

shallowEqual和JS References

immutable


对添加到里面的数据,必须也是immutable的

Immutable Data

immutable data 一旦创建,就不能再被更改的数据。对immutable对象的任何修改或者添加删除操作都会返回一个新的immutable对象。他的实现原理是持久化数据结构,也就是使用旧数据创建新数据时,要保证旧数据可用且不变。还采用了结构共享,为了避免把所有节点都复制一遍带来的性能损耗。

优点:

  1. 节省内存
  2. 并发安全
  3. 拥抱函数式编程

使用时需要注意的点:

  1. 获取数据时,必须使用getgetIn,原生的直接用.是有差别的

  2. 修改数据时,也和原生的不一样:

    this.setState(({data}) => ({
      data: data.update('items', list => list.push(data.get('count')))
    }));
    
    
    this.setState(({data}) => ({
    	data: data.updateIn(['a','b'], ()=>test)
    }));
    
  3. 当给数组中增加一个对象数据时,要保证这个对象是immutable对象

immutable和pureCompoent需要一起使用的原因:

  1. pureComponent需要state和props都改变的时候,才会去re-render。但是如果是一个对象的话,修改对象的值,对象的引用值不变,那么修改的值就不能显示在页面上
  2. 因为immutable具有结构共享的特性,那么没有被修改到的数据,相应的pureComponent就不会去re-render
  3. 当需要修改immutable的数据时,其实他时返回了一个新的immutable对象(里面有些数据是公用的),所以保证了对象的引用地址的修改,那么就会去触发re-render

immutable的参考文章:
Immutable as React state

不错的例子
facebook immutable.js 意义何在,使用场景?
Immutable 常用API简介

immutable和pureComponent的参考文章

React 的性能优化(一)当 PureComponent 遇上 ImmutableJS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant