1.引出生命周期
unmountComponentAtNode() 卸载组件
componentDidMount()组件挂载完毕
componentWillReceiveProps () 组件将要接受参数 (子组件将要接受新参数时触发的生命周期函数)
shouldComponentUpdate() 是否可以组件更新,必须有 Boolean 值得返回,如果为 true 则继续生命周期,如果为 false 则不执行任何后续操作,相当于更新操作的阀门
componentWillUpdate () 组件即将要更新
componentDidUpdate()组件更新完成
render()初始化渲染、状态更新之后执行人 render
componentWillUnmount()组件将要卸载
旧版本生命周期函数:
挂载时:(初始化操作时)
constructor => componentWillMount => render => componentDidMount => componentWillUnmount(卸载组件时触发更新)
更新时:(有三条路线)
-
正常更新操作时:setState 执行更新操作
constructor => componentWillMount => render => componentDidMount => (setState 执行更新操作)=> shouldComponentUpdate => componentWillUpdate => render => componentDidUpdate => componentWillUnmount
-
强制更新操作:forceUpdate() 状态无更新,强制更新,不受 shouldComponentUpdate 阀门控制
constructor => componentWillMount => render => componentDidMount => (forceUpdate 强制执行更新操作) => componentWillUpdate => render => componentDidUpdate => componentWillUnmount
-
父组件 render :当组件内部接收新参数时会触发 componentWillReceiveProps
constructor => componentWillMount => render => componentDidMount => componentWillReceiveProps => shouldComponentUpdate => componentWillUpdate => render => componentDidUpdate => componentWillUnmount
总结:react 的生命周期分三个阶段执行:
1. 初始化阶段: 由ReactDOM.render()触发—初次渲染
1). constructor()
2). componentWillMount()
3). render()
4). componentDidMount() =====> 常用
=> 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
2. 更新阶段: 由组件内部this.setSate()或父组件render触发
1). shouldComponentUpdate()
2). componentWillUpdate()
3). render() =====> 必须使用的一个
4). componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
1). componentWillUnmount() =====> 常用
=> 一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
新版本生命周期函数:
新版本生命周期更改了 componentWillReceiveProps ,componentWillMount,componentWillUpdate 的使用,使用时需增加前缀UNSAFE_
标记生命周期方法“过时”。这些方法仍然有效,但不建议在新代码中使用它们。增加了 static getDerivedStateFromProps()
静态方法,getSnapshotBeforeUpdate()
- static getDerivedStateFromProps(props, state):
getDerivedStateFromProps
会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回null
则不更新任何内容。此方法适用于罕见用例,即 state 的值在任何时候都取决于 props。但是派生状态会导致代码冗余,并使组件难以维护,不推荐使用 - getSnapshotBeforeUpdate(prevProps, prevState):
getSnapshotBeforeUpdate()
在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给componentDidUpdate()
。此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等。该生命周期应返回 snapshot 的值(或null
)。
总结:
1. 初始化阶段: 由ReactDOM.render()触发—初次渲染
1). constructor()
2). getDerivedStateFromProps ()
3). render()
4). componentDidMount() =====> 常用
一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
1). getDerivedStateFromProps()
2). shouldComponentUpdate()
3). render()
4). getSnapshotBeforeUpdate()
5). componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
1). componentWillUnmount() =====> 常用
一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
常用生命周期函数:
\1. render:初始化渲染或更新渲染调用
\2. componentDidMount:开启监听, 发送ajax请求
\3. componentWillUnmount:做一些收尾工作, 如: 清理定时器
即将废弃的生命周期函数:
\1. componentWillMount
\2. componentWillReceiveProps
\3. componentWillUpdate
现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。
DOM 的 diffing 算法:
对比的最小粒度是标签,标签的内容会更新,但是标签内部的标签会作比较,未改变则不会更新,
key 的作用(内部原理):index 不建议使用,在某些条件下会有问题
经典面试题:
1). react/vue中的key有什么作用?(key的内部原理是什么?)
2). 为什么遍历列表时,key最好不要用index?
\1. 虚拟DOM中key的作用:
1). 简单的说: key是虚拟DOM对象的标识, 在更新显示时key起着极其重要的作用。
2). 详细的说: 当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】,
随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:
a. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
(1).若虚拟DOM中内容没变, 直接使用之前的真实DOM
(2).若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
b. 旧虚拟DOM中未找到与新虚拟DOM相同的key
根据数据创建新的真实DOM,随后渲染到到页面
\2. 用index作为key可能会引发的问题:
\1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
\2. 如果结构中还包含输入类的DOM:
会产生错误DOM更新 ==> 界面有问题。
\3. 注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,
仅用于渲染列表用于展示,使用index作为key是没有问题的。
\3. 开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
\3. 注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,
仅用于渲染列表用于展示,使用index作为key是没有问题的。
\3. 开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
2.如果确定只是简单的展示数据,用index也是可以的。