React中的生命周期函数
React中旧版本的生命周期函数
React的生命周期函数 ----旧版本
初始化阶段 -----挂载阶段
constructor()
componentWillMount ( )
render()
componentDidMount()
运行阶段 ----更新阶段
componentWillReaceiveProps()
shouldComponentUpdate()
ComponentWillUpdate()
render()
componentDidUpdate()
销毁阶段
componentWillUnmount()
错误异常处理阶段
componentDidcatch()
React中的新版本常用的8个生命周期函数
挂载阶段
1、constructor() 设定初始化的状态,以及定义事件,如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。 在 React 组件挂载之前,会调用它的构造函数。在为 React.Component 子类实现构造函数时,应在其他语句之前前调用 super(props)。否则,this.props 在构造函数中可能会出现未定义的 bug。 在 constructor() 函数中不要调用 setState() 方法。如果你的组件需要使用内部 state,请直接在构造函数中为 this.state 赋值初始 state:
2、render() 方法是 class 组件中唯一必须实现的方法。 当 render 被调用时,它会检查 this.props 和 this.state 的变化并返回以下类型之一 React 元素。通常通过 JSX 创建。例如,< div /> 会被 React 渲染为 DOM 节点, < MyComponent /> 会被 React 渲染为自定义组件,无论是 < div /> 还是 < MyComponent /> 均为 React 元素。 数组或 fragments。 使得 render 方法可以返回多个元素。欲了解更多详细信息,请参阅 fragments 文档。 Portals。可以渲染子节点到不同的 DOM 子树中。欲了解更多详细信息,请参阅有关 portals 的文档 字符串或数值类型。它们在 DOM 中会被渲染为文本节点 布尔类型或 null。什么都不渲染。(主要用于支持返回 test && < Child /> 的模式,其中 test 为布尔类型。) render() 函数应该为纯函数,这意味着在不修改组件 state 的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。
如需与浏览器进行交互,请在 componentDidMount() 或其他生命周期方法中执行你的操作。保持 render() 为纯函数,可以使组件更容易思考。
3、getDerivedStateFromProps () 一般不使用
getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。 此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props。例如,实现 < Transition> 组件可能很方便,该组件会比较当前组件与下一组件,以决定针对哪些组件进行转场动画。
派生状态会导致代码冗余,并使组件难以维护。 如果你需要执行副作用(例如,数据提取或动画)以响应 props 中的更改,请改用 componentDidUpdate。 如果只想在 prop 更改时重新计算某些数据,请使用 memoization helper 代替。 如果你想在 prop 更改时“重置”某些 state,请考虑使组件完全受控或使用 key 使组件完全不受控 代替。 此方法无权访问组件实例。如果你需要,可以通过提取组件 props 的纯函数及 class 之外的状态,在getDerivedStateFromProps()和其他 class 方法之间重用代码。
请注意,不管原因是什么,都会在每次渲染前触发此方法。这与 UNSAFE_componentWillReceiveProps 形成对比,后者仅在父组件重新渲染时触发,而不是在内部调用 setState 时。
4、componentDidMount() componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。
这个方法是比较适合添加订阅的地方。如果添加了订阅,请不要忘记在 componentWillUnmount() 里取消订阅
你可以在 componentDidMount() 里直接调用 setState()。它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 render() 两次调用的情况下,用户也不会看到中间状态。请谨慎使用该模式,因为它会导致性能问题。通常,你应该在 constructor() 中初始化 state。如果你的渲染依赖于 DOM 节点的大小或位置,比如实现 modals 和 tooltips 等情况下,你可以使用此方式处理
更新时阶段
1、componentDidUpdate(){ 有条件的请求数据,实例化,dom操作 } componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。 当组件更新后,可以在此处对 DOM 进行操作。如果你对更新前后的 props 进行了比较,也可以选择在此处进行网络请求。(例如,当 props 未发生变化时,则不会执行网络请求)。
componentDidUpdate(prevProps) {
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
你也可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。它还会导致额外的重新渲染,虽然用户不可见,但会影响组件性能。不要将 props “镜像”给 state,请考虑直接使用 props。 如果组件实现了 getSnapshotBeforeUpdate() 生命周期(不常用),则它的返回值将作为 componentDidUpdate() 的第三个参数 “snapshot” 参数传递。否则此参数将为 undefined。
注意 如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate()。
2、shouldCompntDidUpdate() 默认返回值为true–提升 react性能的关键 根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染。大部分情况下,你应该遵循默认行为。
当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。返回值默认为 true。首次渲染或使用 forceUpdate(强制更新) 时不会调用该方法。
此方法仅作为性能优化的方式而存在。不要企图依靠此方法来“阻止”渲染,因为这可能会产生 bug。你应该考虑使用内置的 PureComponent 组件,而不是手动编写 shouldComponentUpdate()。PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。
如果你一定要手动编写此函数,可以将 this.props 与 nextProps 以及 this.state 与nextState 进行比较,并返回 false 以告知 React 可以跳过更新。请注意,返回 false 并不会阻止子组件在 state 更改时重新渲染。
我们不建议在 shouldComponentUpdate() 中进行深层比较或使用 JSON.stringify()。这样非常影响效率,且会损害性能。
目前,如果 shouldComponentUpdate() 返回 false,则不会调用 UNSAFE_componentWillUpdate(),render() 和 componentDidUpdate()。后续版本,React 可能会将 shouldComponentUpdate 视为提示而不是严格的指令,并且,当返回 false 时,仍可能导致组件重新渲染。
销毁阶段
componentWillUnmount()
componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。
错误异常阶段
1、static getDerivedStateFromerror() 此生命周期会在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state
2、componentDidCatch()
此生命周期在后代组件抛出错误后被调用。 它接收两个参数: error —— 抛出的错误。 info —— 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息。
vue中的生命周期
1、beforeCreate
在实例初始化之后,数据观测(data,observer)和 event/wathcher事件配置之前被调用。
2、created
在实例创建完成后被立即调用,在这一步。实例已完成以下的配置:数据观测(data,observer),property和方法的运算,watch/event事件回调,然而,挂载阶段还没开始
3、beforeMount
在挂载之前被调用:相关的render函数首次被调用。 该钩子在服务器端渲染期间不被调用
4、mounted
实例被挂载后调用,这时el被新创建的vm.
e
l
替
换
了
,
如
果
根
实
例
挂
载
到
了
一
个
文
档
内
的
元
素
上
,
当
m
o
u
n
t
e
d
被
调
用
时
,
v
m
.
el替换了,如果根实例挂载到了一个文档内的元素上,当mounted被调用时,vm.
el替换了,如果根实例挂载到了一个文档内的元素上,当mounted被调用时,vm.el,也在文档内。注意mounted不会保证所有的子组件也都一起被挂载,如果你希望等到整个视图都渲染完毕,可以在mounted内部使用vm.$nextTick
5、beforeUpdate
数据更新时调用,这时el被新创建的vm. $ el替换了,如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.$el也在文档内。 注意mounted不会保证所有的子组件也都一起被挂载,如果你希望等到整个视图都渲染完毕,可以在mounted内部使用
该钩子在服务器端渲染期间不被调用
mounted: function () {
this.$nextTick(function () {
})
}
6、beforeUpdate
数据更新时调用,发生在虚拟DOM打补丁之前,这里适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器
该钩子在服务器端渲染期间不被调用,因为只有初次渲染在服务器端进行
7、Update
由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子 当这个钩子被调用时,组件DOM已经更新,所以你现在可以执行依赖于DOM的操作,然而在大多数情况下,你应该避免在此期间更改状态,如果要相应状态改变,通常最好使用计算属性或watcher取而代之 注意updated不会保证所有的子组件也都一起被重绘,如果你希望等到整个视图都重绘完毕,可以在updated里使用 该钩子在服务器端渲染期间不被调用
8、activated
被keep-alive缓存的组件激活时调用 该钩子在服务器端渲染期间不被调用
9、deactivated
被keep-alive缓存的组件停用时调用
10、beforeDestroy
实例销毁之前调用,在这一步,实例仍然完全可用。 该钩子在服务器渲染期间不被调用
11、destoryed
实例销毁后调用,该钩子被调用后,对应Vue实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
该钩子在服务器端渲染期间不被调用
12、errorCaptured
当捕获一个来自子孙组件的错误时被调用,此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串,此钩子可以返回false以阻止该错误继续向上传播
(err: Error, vm: Component, info: string) => ?boolean
错误传播规则: 1、默认情况下,如果全局的config.errorHandler被定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报
2、如果一个组件的继承或父级从属链路中存在多个errorCaptured钩子,则他们将会被相同的错误逐个唤起
3、如果此errorCaptured钩子自身抛出一个错误,则逐个新错误和原本被捕获的错误都会发送给全局的config.errorHandler
4、一个errorCaptured钩子能够返回false以阻止错误继续向上传播,本质上是说“逐个错误已经被搞定了,且应该被忽略”,他会阻止其他任何会被这个错误唤起的errorCaptured钩子和全局的config.errorHandler.
|