本文已参与「新人创作礼」活动,一起开启掘金创作之路。
组件的生命周期
1.概述
- 意义:组件的生命周期有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误原因等
- 只有类组件才有生命周期
2.生命周期的三个阶段
-
创建时(挂载阶段)
-
执行时机:组件创建时(页面加载时)
-
执行顺序:
graph LR A(constructor)-->B(render)-->C(componentDidMount)钩子函数 触发时机 作用 constructor 创建组件时,最先执行 1. 初始化state
2.为事件处理程序绑定thisrender 每次组件渲染都会触发 渲染UI(注意:不能调用setState()) componentDidMount 组件挂载(完成DOM渲染)后 1. 发送网络请求
2. DOM操作
-
-
更新时(更新阶段)
-
执行时机:1.setState() 2.forceUpdate() 3.组件接收到新的props
-
执行顺序:
graph LR A(render)-->B(componentDidUpdate)钩子函数 触发时机 作用 render 每次组件渲染都会触发 渲染UI(注意:不能调用setState()) componentDidUpdate 组件更新(完成DOM渲染)后 1. 发送网络请求
2. DOM操作
注意:如果要setState()必须要放在一个if条件中
-
-
卸载时(卸载阶段)
-
执行时机:组件从页面消失
钩子函数 触发时机 作用 componentWillUnmount 组件卸载(从页面消失) 执行清理工作(比如:清理定时器)
-
render props和高阶组件
1.React组件复用概述
- 当有两个组件存在相似/相同功能时,考虑复用该功能(封装)
- 两种方式:1. render props模式 2.高阶组件(HOC)
- 注意:这两种模式不是新的API,而是利用React自身特点的编码技巧,演化而成的固定模式
2.render props模式
/*
1. 实现时,添加一个值为函数的prop,通过函数参数来获取
*/
Mouse.propTypes = {
children: PropTypes.func.isRequired
}
class Mouse extends React.Component{
state = {
x: 0,
y: 0
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
componentDidMount(){
window.addEventListener('mousemove', this.handleMouseMove)
}
componentWillUnmount(){
window.removeEventListener('mousemove', this.handleMouseMove)
}
render(){
return this.props.children(this.state)
}
}
3.高阶组件
-
概述:实现状态逻辑复用
-
采用包装(装饰)模式
-
高阶组件(HOC,Higher-Order Conponent)是一个函数,接收要包装的组件,返回增强后的组件
-
高阶组件内部创建一个类组件,在这个类组件中提供复用的逻辑状态代码,通过prop将复用的状态传递给被包装组件WrappedComponent
function withMouse(WrappedComponent){ Class Mouse extends React.Component{ state ={ x: 0, y: 0 } handleMouseMove = e => { this.setState({ x: e.clientX, y: e.clientY }) } componentDidMount(){ window.addEventListener('mousemove', this.handleMouseMove) } componentWillUnmount(){ window.removeEventListener('mousemove', this.handleMouseMove) } return <WrappedComponent{...this.state} /> } return Mouse } -
设置displayName
使用高阶组件存在问题:得到两个组件名称相同
原因:默认情况下,React使用组件名称作为displayName
为 高阶组件 设置 displayName,用于区分组件的不同实现
Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}` function getDisplayName(WrappedComponent){ return WrappedComponent.displayName || WrappedComponent.name || 'Component' } -
传递props
{...this.props}