前言
PureComponent
通过浅比较props和state来防止页面不必要的渲染,本文是实验篇,通过React例子,以实验的方式验证PureComponent
一些优化以及规避方式
实验
渲染过滤
PureComponent
能阻止组件进行不必要的渲染
import React, {Component, PureComponent} from 'react'; import './App.css'; class App extends Component { state = { text: 0 } render() { console.log('父组件输出') return ( <div onClick={() => { this.setState({ text: this.state.text + 1 }) }}> <span>你好世界{this.state.text}</span> <ChildComponent/> </div> ) } } class ChildComponent extends Component{ render() { console.log('子组件输出') return ( <div> <span>这是一个子组件</span> </div> ) } } // 点击你好世界控制台会输出 // 父组件输出 // 子组件输出
import React, {Component, PureComponent} from 'react'; import './App.css'; class App extends Component { state = { text: 0 } render() { console.log('父组件输出') return ( <div onClick={() => { this.setState({ text: this.state.text + 1 }) }}> <span>你好世界{this.state.text}</span> <ChildComponent/> </div> ) } } class ChildComponent extends PureComponent{ render() { console.log('子组件输出') return ( <div> <span>这是一个子组件</span> </div> ) } } // 点击你好世界控制台会输出 // 父组件输出
地址更新触发渲染
如果组件的props和state中存在引用地址,引用地址中属性值的改变不会触发重新渲染,引用地址的改变才会触发重新渲染
import React, {Component, PureComponent} from 'react'; import './App.css'; let valueObj = { value: 0 } class App extends Component { state = { text: 0 } render() { console.log('父组件输出') return ( <div onClick={() => { valueObj.value ++ this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> <ChildComponent value={valueObj}/> </div> ) } } class ChildComponent extends Component{ render() { console.log('子组件输出'+this.props.value.value) return ( <div> <span>这是一个子组件{this.props.value.value}</span> </div> ) } } export default App; // 点击你好世界控制台会输出 // 父组件输出 // 子组件输出1
import React, {Component, PureComponent} from 'react'; import './App.css'; let valueObj = { value: 0 } class App extends Component { state = { text: 0 } render() { console.log('父组件输出') return ( <div onClick={() => { valueObj.value ++ this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> <ChildComponent value={valueObj}/> </div> ) } } class ChildComponent extends PureComponent{ render() { console.log('子组件输出'+this.props.value.value) return ( <div> <span>这是一个子组件{this.props.value.value}</span> </div> ) } } export default App; // 点击你好世界控制台会输出 // 父组件输出
import React, {Component, PureComponent} from 'react'; import './App.css'; let valueObj = { value: 0 } class App extends Component { state = { text: 0 } render() { console.log('父组件输出') return ( <div onClick={() => { valueObj = { value: 0 } this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> <ChildComponent value={valueObj}/> </div> ) } } class ChildComponent extends PureComponent{ render() { console.log('子组件输出'+this.props.value.value) return ( <div> <span>这是一个子组件{this.props.value.value}</span> </div> ) } } export default App; // 点击你好世界控制台输出 // 父组件输出 // 子组件输出0
避免render中声明
render函数中声明对象会导致不必要的渲染
import React, {Component, PureComponent} from 'react'; import './App.css'; let valueObj = { value: 0 } class App extends Component { state = { text: 0 } render() { console.log('父组件输出') return ( <div onClick={() => { this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> <ChildComponent value={valueObj}/> </div> ) } } class ChildComponent extends PureComponent{ render() { console.log('子组件输出'+this.props.value.value) return ( <div> <span>这是一个子组件{this.props.value.value}</span> </div> ) } } export default App; // 点击你好世界控制台输出 // 父组件输出
import React, {Component, PureComponent} from 'react'; import './App.css'; class App extends Component { state = { text: 0 } render() { console.log('父组件输出') return ( <div onClick={() => { this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> <ChildComponent value={{value:0}}/> </div> ) } } class ChildComponent extends PureComponent{ render() { console.log('子组件输出'+this.props.value.value) return ( <div> <span>这是一个子组件{this.props.value.value}</span> </div> ) } } export default App; // 点击你好世界控制台输出 // 父组件输出 // 子组件输出0
避免匿名函数
import React, {Component, PureComponent} from 'react'; import './App.css'; class App extends Component { state = { text: 0 } render() { console.log('父组件输出') return ( <div> <div onClick={() => { this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> </div> <ChildComponent onChildrenClick={(param) => { console.log(param) }}/> </div> ) } } class ChildComponent extends PureComponent { onClickListen = () => { this.props.onChildrenClick('这是参数') } render() { console.log('子组件输出') return ( <div onClick={this.onClickListen}> <span>这是一个子组件</span> </div> ) } } export default App; // 点击你好世界控制台输出 // 父组件输出 // 子组件输出 // 点击这是一个子组件控制台输出 // 这是参数
import React, {Component, PureComponent} from 'react'; import './App.css'; class App extends Component { state = { text: 0 } onChildrenClickListen = (param) => { console.log(param) } render() { console.log('父组件输出') return ( <div> <div onClick={() => { this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> </div> <ChildComponent onChildrenClick={this.onChildrenClickListen}/> </div> ) } } class ChildComponent extends PureComponent { onClickListen = () => { this.props.onChildrenClick('这是参数') } render() { console.log('子组件输出') return ( <div onClick={this.onClickListen}> <span>这是一个子组件</span> </div> ) } } export default App; // 点击你好世界控制台输出 // 父组件输出 // 点击这是一个自组件控制台输出 // 这是参数
map遇上回调函数
当render中组件时涉及map循环遍历,同时map中返回的内容需要绑定回调事件,那么将map中返回的内容单独抽离成组件可以激活筛选渲染
import React, {Component, PureComponent} from 'react'; import './App.css'; const dataArray = [1,2] class App extends Component { state = { text: 0 } onChildrenClickListen = (param) => { console.log(param) } render() { console.log('父组件输出') return ( <div> <div onClick={() => { this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> </div> { dataArray.map((item, index) => { return ( <ChildComponent onChildrenClick={() => { this.onChildrenClickListen(item) }}/> ) }) } </div> ) } } class ChildComponent extends PureComponent { render() { console.log('子组件输出') return ( <div onClick={this.props.onChildrenClick}> <span>这是一个子组件</span> </div> ) } } export default App; // 点击你好世界控制台输出 // 父组件输出 // 子组件输出 // 子组件输出 // 点击第一个这是一个子组件控制台输出 // 1
import React, {Component, PureComponent} from 'react'; import './App.css'; const dataArray = [1,2] class MyMapItem extends PureComponent { onChildrenClickListen = () => { this.props.onChildrenClickListen(this.props.item) } render(){ return ( <ChildComponent onChildrenClick={this.onChildrenClickListen}/> ) } } class App extends Component { state = { text: 0 } onChildrenClickListen = (param) => { console.log(param) } renderMap = (item, index) => { return <MyMapItem item={item} onChildrenClickListen={this.onChildrenClickListen}/> } render() { console.log('父组件输出') return ( <div> <div onClick={() => { this.setState({ text: this.state.text + 1 }) }} > <span>你好世界{this.state.text}</span> </div> { dataArray.map(this.renderMap) } </div> ) } } class ChildComponent extends PureComponent { render() { console.log('子组件输出') return ( <div onClick={this.props.onChildrenClick}> <span>这是一个子组件</span> </div> ) } } export default App; // 点击你好世界控制台输出 // 父组件输出 // 点击第一个这是一个子组件控制台输出 // 1