PureComponent
是和 shouldComponentUpdate
这个生命周期息息相关的react
React
中,当父组件中触发setState
, 尽管未修改任何 state
中的值也会引发全部子组件的从新渲染, 更况且是修改了某个state
segmentfault
还有, 当父组件传给子组件的props
发生改变, 无论该props
是否被子组件用到, 都会去从新渲染子组件。浏览器
其实咱们也能够想获得, setState 会去触发 render, 因此父组件render
函数中的子组件都会被从新渲染, 所以也就无关state
与props
了
针对这个问题我实现了个例子, 来看一下下面这个例子性能优化
setState但未修改任何state
父组件触发 setState
方法, 但未更新任何state
dom
import TodoItem from './components/todoItem/todoItem' // 父组件代码 class TodoList extends Component { noChange() { console.log('触发setState') this.setState(() => ({ })) } render() { const { todoList } = this.state return ( <div className="wrap"> <button onClick={() => this.noChange()}>没有变化的setState</button> { todoList.map( (item,index) => <TodoItem key={index} data={item} /> ) } </div> ) } } // 子组件代码 class TodoItem extends Component { constructor(props) { super(props) } componentWillUpdate() { console.log('我被更新了') } render() { return ( <div> { this.props.data.thing } </div> ) } }
咱们在子组件中预留了componentWillUpdate
方法, 用来监测子组件是否被跟新函数
componentWillUpdate() { console.log('我被更新了') }
实验结果: 性能
咱们能够看到, 每一次的点击都引发了子组件的update
优化
无端的重复update
, 这会致使业务规模扩大后十分的影响性能.this
为此我监测了一下页面的重绘事件:spa
绿色区域是浏览器发成重绘的地方
能够看到todoList
其实并无引发浏览器的repaint
, 所以能够推测, 实际dom
并无更新这在渲染页面前被dom diff
给排除掉了, 所以性能损耗在了转换成Virtual DOM
的过程当中
shouldComponentUpdate(nextProps, nextState), 默认返回true
shouldComponentUpdate
是 React
中作性能优化的重要手段, 看这个英文翻译咱们大概也能猜出个一二来 --- '组件是否跟新?'
React
会根据 shouldComponentUpdate
的返回结果来决定该组件是否从新渲染, 若是返回True
就渲染, 若是返回False
就从新渲染
基于这个特性, 咱们来修改一下上面问题中的代码
// 父组件无变化, 所以省略 // 子组件代码 class TodoItem extends Component { // ...省略其余原有的代码 // --------- 新增代码 ------------- shouldComponentUpdate(nextProps, nextState) { // 判断下 当前 props传入的data.thing 是否和新传入的 data.thing 相同 return this.props.data.thing !== nextProps.data.thing } // --------- 新增代码 ------------- }
实验结果:
咱们能够看到update
事件确实消失了
看了shouldComponentUpdate
函数的做用, 就可以理解PureComponent
了? 它其实就是在帮咱们作这样一件事:
自动的帮咱们编写 shouldComponentUpdate
方法, 避免咱们为每一个组件都编写一次的麻烦
咱们只须要这样, 就能够一步到位
import React, { PureComponent } from 'react' class TodoItem extends PureComponent { }