class式组件的生命周期API
定义class组件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
1.需继承React.component
2.在 React.Component 的子类中有个必须定义的 render() 函数
class组件的生命周期-分为3大部分
下面常用的生命周期方法会被加粗。其余生命周期函数的使用则相对罕见。
挂载 -> (Mount):组件第一次在DOM树中渲染
当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:
- constructor(): 在 React 组件挂载之前,会调用它的构造函数
- static getDerivedStateFromProps()
- render():React渲染
- componentDidMount(): 在组件挂载后(插入 DOM 树中)立即调用。
1.constructor(props)
我们把组件渲染,并且构造DOM元素插入到页面的过程称为组件的挂载
在 React 组件挂载之前,会调用它的构造函数。在为 React.Component 子类实现构造函数时,在其他语句之前前调用 super(props)。否则,this.props 在构造函数中可能会出现未定义的 bug。
通常,react中,构造函数仅用于一下两种情况
1.给this.state 赋值对象初始化内部state (初始化state值)
2.为事件处理函数绑定实例
如果不初始化state或不进行方法绑定,则不需要为React组件实现构造函数
注意:
- 在constructor()函数中不要调用setState()方法,可直接为this.state赋初始值state
- 也只能在构造函数中直接为this.state赋值,其他方法中赋值应使用this.setState()
- 要避免在构造函数中引入任何副作用或订阅。如遇到此场景,请将对应的操作放置在 componentDidMount 中。
constructor(props){
super(props);
//不要在这里调用 this.setState()
this.state = {counter:0};
this.handleClick = this.handleClick.bind(this)
}
避免将 props 的值复制给 state!这是一个常见的错误:
constructor(props) {
super(props);
// 不要这样做
this.state = { color: props.color };
}
如此做毫无必要(你可以直接使用 this.props.color),同时还产生了 bug (更新 prop 中的 color 时,并不会影响 state)。
只有在你刻意忽略 prop 更新的情况下使用。此时,应将 prop 重命名为 initialColor 或 defaultColor。必要时,你可以修改它的 key,以强制“重置”其内部 state。
2.render()
render()方法是class组件中唯一必须实现的方法
1.初始化:React在应用初始化的时候,会渲染全部组件
2.setState()在任何情况下都会导致组件的重新渲染,即使state未发生变化
当一个组件调用了setState()函数时,不论state是否发生了变化,该组件都将被重新渲染。
3.只要父组件重新渲染了,那么子组件就会重新渲染。即使组件未发生变化,并且从父组件接收的props也没有发生变化,但是只要父组件重新渲染了,那么子组件就会重渲染。
当render被调用时,它会检查this.props和this.state的变化并返回一下类型之一
- React元素: JSX/自定义组件
- 数组或fragments:一个组件返回多个元素
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
- Portals:将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案
- 字符串或数值类型:在DOM中被渲染为文本节点
- 布尔类型或 null:什么都不渲染
render() 函数应该为纯函数,这意味着在不修改组件 state 的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。
如需与浏览器进行交互,请在 componentDidMount() 或其他生命周期方法中执行你的操作
注意:
如果 shouldComponentUpdate() 返回 false,则不会调用 render()。
React的组件重渲染机制,是一个严谨的做法,因为它避免了,状态更新后,手动去重渲染相关组件的操作。但是有些时候我们更新了某个组件的数据,但是并不想让与其相关的其他组件被重渲染,因为反复的重渲染未变化的组件,既耗时也会影响性能,此时就需要对React的重渲染进行优化
3.componentDidMount()
componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。
依赖于 DOM 节点的初始化应该放在这里。
如需通过网络请求获取数据,此处是实例化请求的好地方。
这个方法是比较适合添加订阅的地方。如果添加了订阅,请不要忘记在 componentWillUnmount() 里取消订阅(发布类似触发事件,订阅类似监听事件)
可以在 componentDidMount() 里直接调用 setState()。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 render() 两次调用的情况下,用户也不会看到中间状态。请谨慎使用该模式,因为它会导致性能问题。通常,你应该在 constructor() 中初始化 state。如果你的渲染依赖于 DOM 节点的大小或位置,比如实现 modals 和 tooltips 等情况下,你可以使用此方式处理
更新 -> (update):组件更新,重新渲染
-
static getDerivedStateFromProps() :不常用 获取派生状态
-
shouldComponentUpdate():偶尔用 当返回值为 false,则不会调用 componentDidUpdate()和render()。
-
render()
-
getSnapshotBeforeUpdate(): 不常用 获取更新前快照
-
componentDidUpdate():更新后会立即调用
组件更新相关函数,在组件初始挂载的时候都不会调用。
1.static getDerivedStateFromProps(props, state) 不常用
在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
此方法无权访问组件实例
2.shouldComponentUpdate(nextProps, nextState) 不常用
在组件接收到新的props或state时调用,通过返回值来确定是否重新渲染当前组件
默认行为是 state 每次发生变化组件都会重新渲染。
当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染render执行之前被调用。返回值默认为 true。首次渲染或使用 forceUpdate() 时不会调用该方法。
此方法仅作为性能优化的方式而存在。不要企图依靠此方法来“阻止”渲染,因为这可能会产生 bug。
一定要手动编写此函数,可以将 this.props 与 nextProps 以及 this.state 与nextState 进行比较,并返回 false 以告知 React 可以跳过更新。
请注意,返回 false 并不会阻止子组件在 state 更改时重新渲染。
不建议在 shouldComponentUpdate() 中进行深层比较或使用
JSON.stringify()。这样非常影响效率,且会损害性能。
目前,如果 shouldComponentUpdate() 返回 false,则不会调用 UNSAFE_componentWillUpdate(),render() 和 componentDidUpdate()
3.getSnapshotBeforeUpdate(prevProps, prevState)不常用
最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate()。
此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等。
4.componentDidUpdate(prevProps,prevState,snapshot)
componentDidUpdate() 在更新后会立即调用,首次渲染不会执行该方法,组件更新,重渲染完毕后调用,prevProps 和prevState ,分别表示组件更新前的props和state
当组件更新后,可以在此处对 DOM 进行操作。如果你对更新前后的 props 进行了比较,也可以选择在此处进行网络请求。(例如,当 props 未发生变化时,则不会执行网络请求)。
componentDidUpdate(prevProps){
//典型用法 (不要忘了比较props):
if(this.props.userID !== prevProps.userID){
this.fetchData(this.props.userID)
}
}
可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。
它还会导致额外的重新渲染,虽然用户不可见,但会影响组件性能。
如果组件实现了 getSnapshotBeforeUpdate() 生命周期(不常用),则它的返回值将作为 componentDidUpdate() 的第三个参数 “snapshot” 参数传递。否则此参数将为 undefined。
注意:
如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate()
卸载 ->(Unmount):组件从DOM树中删除
当组件从 DOM 中移除时会调用如下方法:
componentWillUnmount():组件卸载及销毁之前直接调用
1.componentWillUnmount()
componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等
componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。


本文详细解读了React组件的生命周期过程,包括挂载、更新和卸载阶段,重点介绍了constructor、render、componentDidMount、getDerivedStateFromProps、shouldComponentUpdate、getSnapshotBeforeUpdate和componentDidUpdate等核心方法的使用场景和注意事项。
894

被折叠的 条评论
为什么被折叠?



