React-API
React.Component
React.Component 是使用 ES6 classes 方式定义 React 组件的基类:
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
React.PureComponent纯组件
React.PureComponent 与 React.Component 很相似。两者的区别在于 React.Component 并未实现 shouldComponentUpdate(),而 React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了该函数。
如果赋予 React 组件相同的 props 和 state,render() 函数会渲染相同的内容,那么在某些情况下使用 React.PureComponent 可提高性能。
注意
React.PureComponent中的shouldComponentUpdate()仅作对象的浅层比较。如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果。仅在你的 props 和 state 较为简单时,才使用React.PureComponent,或者在深层数据结构发生变化时调用forceUpdate()来确保组件被正确地更新。你也可以考虑使用 immutable 对象加速嵌套数据的比较。此外,
React.PureComponent中的shouldComponentUpdate()将跳过所有子组件树的 prop 更新。因此,请确保所有子组件也都是“纯”的组件。
React.PureComponent的深浅比较
浅比较只会比较 props 的第一层,如果传入的 props 是数组或对象,那么你需要格外小心。因为即使数组更新了,纯组件会在浅比较时认为新旧 props 是相同引用,因此不触发渲染。
可以使用JSON.parse和JSON.stringify对对象或者是数组进行深拷贝
父组件
import React, { Component } from 'react';
import Son from './Son'
class Father extends Component {
constructor(props){
super(props)
this.state={array:[1,2,3,4,5]}
}
onClick=()=>{
this.state.array.push(this.state.array.length+1)
this.setState({
array:this.state.array
})
}
render() {
return (<div>
<button onClick={this.onClick}>btn</button>
<Son array={this.state.array}
name='Bruce Lee'>
</Son>
</div>);
}
}
export default Father;
子组件
import React, { PureComponent, Component } from 'react';
import PropTypes from 'prop-types';
class Son extends PureComponent {
static propTypes = {
array: PropTypes.array,
name: PropTypes.string
}
NumberList (array) {
// key 必须有,否则产生警告。key 一般用id,提高渲染效率。万不得已使用 index
const listItem = array.map((number) => <li key={number.toString()}>{number}</li>)
return (
<ul>{listItem}</ul>
)
}
render() {
console.log('son ',this.props.array)
return (<div>
{this.props.name}
<div>
{this.NumberList(this.props.array)}
</div>
</div> );
}
}
export default Son;
父组件的click
onClick=()=>{
let newArray = JSON.parse(JSON.stringify(this.state.array));
newArray.push(this.state.array.length+1)
this.setState({
array:newArray
})
}
另外,当父组件传入子组件的 props 有函数时,你可能也会遇到一些问题,比如:
父组件为:
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import MyButton from './MyButton'
class Father extends PureComponent {
constructor(props) {
super(props);
this.state = { value:123 }
}
onClick=()=>{
this.setState({
value:this.state.value+1
})
}
render() {
return (
<div>
<p>{this.state.value}</p>
<MyButton
callback={()=>this.onClick()}/>
</div>);
}
}
export default Father;
子组件为:
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
class MyButton extends PureComponent {
static propTypes={
callback:PropTypes.func
}
constructor(props) {
super(props);
this.state = { }
}
render() {
console.log('son')
return (<button onClick={this.props.callback}>btn</button>);
}
}
export default MyButton;
注意,这个时候,父组件传入子组件的 props callback 的写法是:
callback={()=>this.onClick()}
这种写法导致,每次传入子组件的 callback 都是一个新的函数对象,因此,每次父组件 render 时,子组件都会重新 render,效果为:
因此,我们修改为下面这种写法,即,每次传入子组件的 callback 都对应同一个对象,因此,子组件不重新进行渲染。我们修改父组件:
callback={this.onClick}这样传入的是函数
callback={()=>this.onClick()}表示的是把this.onClick()返回的结果作为匿名箭头函数的返回值,即每传入一次调用一次新的