生命周期
最后更新于
这有帮助吗?
最后更新于
这有帮助吗?
挂载
更新
卸载
一个完整的生命周期:
挂载: constructor: 在 React 组件挂载之前,会调用它的构造函数。 getDerivedStateFromProps(): 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。 render: render()方法是 class 组件中唯一必须实现的方法 componentDidMount: 在组件挂载后(插入 DOM 树中)立即调用。
更新:
shouldComponentUpdate 当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。 render: render()方法是 class 组件中唯一必须实现的方法. getSnapshotBeforeUpdate(): 在最近一次渲染输出(提交到 DOM 节点)之前调用。 componentDidUpdate: 在更新后会被立即调用。
卸载 componentWillUnmount(): 在组件卸载及销毁之前直接调用。
shouldComponentUpdate(nextProps, nextState)
這個函數的功用像是守門員,用來做確認是不是真的要 update 。這個函數要 return 一個布林值。當函數回傳 false 時,元件就不會更新,也不會繼續執行接下來的 render()以及剩下的 update 生命週期函數。預設會回傳 true。
在這邊,this.props 和 this.state 是更新之前的,新的 props 和 state 在參數中以 nextProps 和 nextState 存在。你可以在這裡對這四者做比較
1、直接使用 这种方式,父组件改变 props 后,子组件重新渲染,由于直接使用的 props,所以我们不需要做什么就可以正常显示最新的 props
2、转换成自己的 state 这种方式,由于我们使用的是 state,所以每当父组件每次重新传递 props 时,我们需要重新处理下,将 props 转换成自己的 state,这里就用到了 componentWillReceiveProps。
关于你提到的不会二次渲染是这样的:每次子组件接收到新的 props,都会重新渲染一次,除非你做了处理来阻止(比如使用:shouldComponentUpdate),但是你可以在这次渲染前,根据新的 props 更新 state,更新 state 也会触发一次重新渲染,但 react 不会这么傻,所以只会渲染一次,这对应用的性能是有利的。
componentDidMount: 在组件挂载后(插入 DOM 树中)立即调用。
总结一下不建议在 constructor 和 componentWillMount 里写的原因是
会阻碍组件的实例化,阻碍组件的渲染
如果用 setState,在 componentWillMount 里面触发 setState 不会重新渲染
React16 之后采用了 Fiber 架构,只有 componentDidMount 声明周期函数是确定被执行一次的,类似 ComponentWillMount 的生命周期钩子都有可能执行多次,所以不加以在这些生命周期中做有副作用的操作,比如请求数据之类。
在生产时, componentDidMount 生命周期函数是最好的时间去请求数据, 其中最重要原因: 使用 componentDidMount 第一个好处就是这个一定是在组件初始化完成之后, 再会请求数据, 因此不会报什么警告或者错误, 我们正常请教数据完成之后一般都会 setState
顺便说一句在 es6 中, 使用 extend component 的方式里的 constructor 函数和 componentWillMount 是通用的作用, 所以你在构造函数里初始化了组件的状态就不必在 WillMount 做重复的事情了.
componentWillReceiveProps() 在生命周期的第一次 render 后不会被调用,但是会在之后的每次 render 中被调用 = 当父组件再次传送 props。
该方法当 props 发生变化时执行,初始化 render 时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用 this.setState()来更新你的组件状态,旧的属性还是可以通过 this.props 来获取, 这里调用更新状态是安全的,并不会触发额外的 render 调用。
在父组件更新 自身状态变化 自身强制更新
• componentWillReceiveProps() • shouldComponentUpdate() • componentWillUpdate() • render() • componentDidUpdate()
当自身状态发生变化, 就是调用 setState 时, 会触发下面的函数 • shouldComponentUpdate() • componentWilIUpdate() • render() • componentDidUpdate()
调用 forceUpdate 会发生强制更新,此时会触发下面的函数 • componentWillUpdate() • render() • componentDidUpdate() should Component Up ate 可以用来提升性能, componentWillReceiveProps 般用来将新的 props 步到 tate
REACT 事件的优点:
e.preventDefault // 阻止默认事件
e.nativeEvent //原生事件对象
父子组件通信
初始化时的参数传递
实例化阶段的方法调用
回调函数
子组件部署消息接口
创建更新的方式 ReactDOM.render || hydrate setState forceUpdate
步骤 创建 reactRoot 创建 fiberRoot 和 RootFiber 创建更新
对一些名词的理解: currentTime
再一次渲染中产生的更新需要使用相同的时间 一次批处理的更新应该得到相同的时间 挂起任务用于记录的时候应该相同
每个更新到来后,生成一个 Update 对象,放到 ReactRoot 的 updateQueue 里。
中间一系列计算过期时间后更新 ReactRoot 的过期时间并将它添加到 ReactFiberScheduler 的 ScheduledRoot 链表里。
判断这次更新是批量/批量,同步/异步,如果是异步任务,就执行 scheduleCallbackWithExpirationTime(root, expirationTime);进而执行 callbackID = scheduleDeferredCallback(performAsyncWork, {timeout});
scheduleDeferredCallback 在 Scheduler 里,会对应生成一个 callbackNode,并对这个 callbackNode 安排更新。
更新机制 什么是 Fiber 以及作用 React 实现路更新任务的调度,如何实现的
虚拟 Dom 控制在组件级,最早 Vue3 的提案其实是包含时间切片方案的,最后废弃的主要原因,是时间切片解决的的问题,Vue3 基本碰不到
Vue3 把虚拟 Dom 控制在组件级别,组件之间使用响应式,这就让 Vue3 的虚拟 Dom 不会过于庞大
Vue3 虚拟 Dom 的静态标记和自动缓存功能,让静态的节点和属性可以直接绕过 Diff 逻辑,也大大减少了虚拟 Dom 的 Diff 事件
时间切片也会带来额外的系统复杂性