前言
文章目录
1. 组件优化
Component的2个问题
效率高的做法
原因
重写shouldComponentUpdate()方法
export default class Parent extends Component {
state = { carName: '奔驰' }
changeCar = () => {
this.setState({})
}
shouldComponentUpdate(nextProps, nextState) {
console.log(this.props, this.state) //目前的props和state
console.log(nextProps, nextState) //接下来要变化的目标props,目标state
if (this.state.carName === nextState.carName) return false
else return true
}
render() {
console.log('parent--render')
return (
<div className='parent'>
<h3>我是Parent组件</h3>
<span>我的车名字是:{this.state.carName}</span><br />
<button onClick={this.changeCar}>点我换车</button>
</div>
)
}
}
效果
问题2
和问题1一样重写shouldComponentUpdate()方法
import React, { Component } from 'react'
import './index.css'
export default class Parent extends Component {
state = { carName: '奔驰' }
changeCar = () => {
this.setState({ carName: '宝马' })
}
shouldComponentUpdate(nextProps, nextState) {
// console.log(this.props, this.state) //目前的props和state
// console.log(nextProps, nextState) //接下来要变化的目标props,目标state
if (this.state.carName === nextState.carName) return false
else return true
}
render() {
console.log('parent--render')
return (
<div className='parent'>
<h3>我是Parent组件</h3>
<span>我的车名字是:{this.state.carName}</span><br />
<button onClick={this.changeCar}>点我换车</button>
<Child carName='奥拓' />
</div>
)
}
}
class Child extends Component {
shouldComponentUpdate(nextProps, nextState) {
console.log(this.props, this.state) //目前的props和state
console.log(nextProps, nextState) //接下来要变化的目标props,目标state
if (this.props.carName === nextProps.carName) return false
else return true
}
render() {
console.log('child--render')
return (
<div className='child'>
<h3>我是Child组件</h3>
<span>我接到的车是:{this.props.carName}</span>
</div>
)
}
}
效果
使用PureComponent
当state状态里有多组数据,那么shouldComponentUpdate()里就要进行多个判断,这样显然在真正开发里是不可行的。所以我们可以不用手动写shouldComponentUpdate()方法, 使用PureComponent, 可以重写shouldComponentUpdate()里的逻辑, 只有state或props数据有变化才返回true。(项目中一般使用PureComponent来优化)
import React, { PureComponent } from 'react'
...
export default class Parent extends PureComponent{}
...
class Child extends PureComponent{}
...
注意! 🔥 PureComponent只是进行state和props数据的浅比较
,如果只是数据对象内部数据变了,返回false。 不要直接修改state数据, 而是要产生新数据
//错误写法
const obj = this.state
obj.carName = '宝马'
this.setState(obj)
//正确写法
this.setState({ carName: '宝马' })
2. render props
如何向组件内部动态传入带内容的结构(标签)?
Vue中:
<A>
<B/>
</A>
React中:
children props
<A>
<B>xxxx</B>
</A>
{this.props.children}
问题: 如果B组件需要A组件内的数据, ==> 做不到
export default class Parent extends Component {
render() {
return (
<div className='parent'>
<h3>我是parent组件</h3>
<A>
<B />
</A>
</div>
)
}
}
class A extends Component {
render() {
console.log(this.props)
return (
<div className='a'>
<h3>我是A组件</h3>
{this.props.children}
</div>
)
}
}
class B extends Component {
render() {
return (
<div className='b'>
<h3>我是B组件</h3>
</div>
)
}
}
效果
render props
<A render={(data) => <C data={data}></C>}></A>
A组件: {this.props.render(内部state数据)}
C组件: 读取A组件传入的数据显示 {this.props.data}
如果在children props写法的基础上, 若要将A组件state身上的name属性传给B组件, 我们就需要使用render props来写:
export default class Parent extends Component {
render() {
return (
<div className='parent'>
<h3>我是parent组件</h3>
<A render={(name) => <B name={name} />} />
</div>
)
}
}
class A extends Component {
state = { name: 'jack' }
render() {
console.log(this.props)
const { name } = this.state
return (
<div className='a'>
<h3>我是A组件</h3>
{this.props.render(name)}
</div>
)
}
}
class B extends Component {
render() {
return (
<div className='b'>
<h3>我是B组件,{this.props.name}</h3>
</div>
)
}
}
效果
3. 错误边界Error boundary
理解
错误边界(Error boundary):把错误控制在一定范围内,比如后端返回来的数据类型出错,或者一些其他的错误,我们可以在界面中提示用户一些“网络繁忙请稍后重试”信息,错误边界Error boundary就是用来捕获后代组件错误,渲染出备用页面。
错误边界一般是在容易发生错误的组件的父组件中处理。
特点
只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误。
使用方式
getDerivedStateFromError配合componentDidCatch
export default class Parent extends Component {
state = {
hasError: '' //用于标识子组件是否产生错误
}
// 如果Parent组件的子组件出现了任何的报错,都会调用这个钩子函数,调用的时候传入error错误信息
static getDerivedStateFromError(error) {
console.log(error)
return { hasError: error }// 返回新的state
}
render() {
return (
<div>
<h2>我是Parent组件</h2>
{this.state.hasError ? <h2>当前网络不稳定,请稍后再试</h2> : <Child />}
</div>
)
}
}
// 如果组件在渲染的整个过程中,由于子组件出现了问题,引发一些错误,
//就会调用此函数,用来统计错误,反馈给服务器,用于通知编码人员进行bug的解决
componentDidCatch(error, info) {
// 统计页面的错误。发送请求发送到后台去
console.log(error, info);
}
效果
4. 组件通信方式总结
组件间的关系
- 父子组件
- 兄弟组件(非嵌套组件)
- 祖孙组件(跨级组件)
几种通信方式
- props:
- children props
- render props
- 消息订阅-发布:
- pubs-sub、event等等
- 集中式状态管理:
- redux、dva等等
- conText:
- 生产者-消费者模式