一、组件的生命周期
1. 理解
1、组件从创建到死亡它会经历一些特定的阶段。
2、React组件中包含一系列钩子函数(生命周期回调函数), 会在特定的时刻调用。
3、我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
4、(名称、叫法)生命周期回调函数<=> 生命周期钩子函数<=>生命周期函数<=>生命周期钩子
5、挂载 mount: 组件第一次被渲染到DOM中的时候,叫挂载 ReactDOM.render(<Life/>, document.querySelector('test'))
6、卸载 unmount:组件被删除时,在react中被称为卸载 ReactDOM.unmountComponentAtNode(document.querySelector('test'))
2. 生命周期流程图(旧)
3. 生命周期的三个阶段(旧)
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():组件即将卸载,常用,一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
4. 生命周期流程线路
l线路1(初始化页面时)
constructor构造器 =》componentWillMount(组件即将挂载)=》render(挂载)=》componentDidMount(组件挂载完成)=》componentWillUnmount(组件将要卸载)
<script type="text/babel">
class Count extends React.Component{
//构造器
constructor(props) {
console.log("Count===构造器constructor执行")
super(props);
//初始化数据
this.state={
count:0
}
}
//函数点我加1
add = ()=>{
const {count} = this.state
this.setState({count:count+1})
}
//函数卸载组件
death = ()=>{
ReactDOM.unmountComponentAtNode(document.getElementById("test"))
}
//函数强制更新
force = ()=>{
this.forceUpdate()
}
//==============生命周期钩子函数===============
//组件即将挂载
componentWillMount(){
console.log('count====componentWillMount组件即将挂载钩子函数执行')
}
//组件挂载完毕
componentDidMount(){
console.log('count====componentDidMount组件挂载完成钩子函数执行')
}
//组件将要卸载
componentWillUnmount(){
console.log('count====componentWillUnmount组件卸载钩子函数执行')
}
render() {
console.log("Count===render组件执行")
const {count} = this.state
return (
<div>
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
</div>
);
}
}
ReactDOM.render(<Count/>, document.getElementById('test'))
</script>
点击卸载组件
l 线路2(数据进行更新)
setState()修改数据 =》shouldComponentUpdate(组件更新)=》componentWillUpdate(组件将要更新)=》render(组件渲染)=》componentDidUpdate(组件更新完成)
<script type="text/babel">
class Count extends React.Component{
//构造器
constructor(props) {
console.log("Count===构造器constructor执行")
super(props);
//初始化数据
this.state={
count:0
}
}
//函数点我加1
add = ()=>{
console.log('add函数执行')
const {count} = this.state
this.setState({count:count+1})
}
//函数卸载组件
death = ()=>{
ReactDOM.unmountComponentAtNode(document.getElementById("test"))
}
//函数强制更新
force = ()=>{
this.forceUpdate()
}
//==============生命周期钩子函数===============
//组件即将挂载
componentWillMount(){
console.log('count====componentWillMount组件即将挂载钩子函数执行')
}
//组件挂载完毕
componentDidMount(){
console.log('count====componentDidMount组件挂载完成钩子函数执行')
}
//组件将要卸载
componentWillUnmount(){
console.log('count====componentWillUnmount组件卸载钩子函数执行')
}
//=================更新数据============
//更新组件 返回boole值
shouldComponentUpdate(){
console.log('count====shouldComponentUpdate组件更新钩子函数执行')
//如果返回false,后面的更新操作将不在执行
return true
}
//组件即将更新
componentWillUpdate(){
console.log('count====componentWillUpdate组件即将更新钩子函数执行')
}
//组件更新完成
componentDidUpdate(){
console.log('count====componentDidUpdate组件更新完成钩子函数执行')
}
render() {
console.log("Count===render组件执行")
const {count} = this.state
return (
<div>
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
</div>
);
}
}
ReactDOM.render(<Count/>, document.getElementById('test'))
</script>
l 线路3(强制更新)
forceUpdate()强制更新 =》componentWillUpdate(组件将要更新)=》render(组件渲染)=》componentDidUpdate(组件更新完成)
l 线路4(父子组件数据传递)
父组件render() =》componentWillReceiveProps(子组件:组件将要接收props参数)=》shouldComponentUpdate(子组件:组件更新)=》componentWillUpdate(子组件:组件即将更新)=》componentDidUpdate(子组件:组件更新完成)
<script type="text/babel">
class A extends React.Component{
state = {
carName:'奔驰'
}
changeCar = ()=>{
this.setState({carName:'宝马'})
}
render() {
console.log("A===render组件执行")
return (
<div>
<div>我是A组件</div>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName}/>
</div>
);
}
}
class B extends React.Component{
//组件将要接收新的props的钩子函数
componentWillReceiveProps(props){
console.log("B===componentWillReceiveProps组件执行",props)
}
//组件更新
shouldComponentUpdate(){
console.log("B===shouldComponentUpdate组件执行")
return true
}
//组件即将更新
componentWillUpdate(){
console.log("B===componentWillUpdate组件执行")
}
//组件更新完成
componentDidUpdate(){
console.log("B===componentDidUpdate组件执行")
}
render() {
console.log("B===render组件执行")
return (
<div>
<div>我是B组件,接收到的车是:{this.props.carName}</div>
</div>
);
}
}
ReactDOM.render(<A/>, document.getElementById('test'))
</script>
注意:
shouldComponentUpdate返回值必须为true或false,若不写,默认为true
forceUpdate():强制更新。不更改任何状态中的数据,强制更新一下
5. 生命周期流程图(新)
17及以上版本
6. 生命周期的三个阶段(新)
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
(1) constructor()
(2) getDerivedStateFromProps:从props中获取状态
(3) render()
(4) componentDidMount() => 常用,一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
(1) getDerivedStateFromProps
(2) shouldComponentUpdate()
(3) render()
(4) getSnapshotBeforeUpdate 在更新之前获取快照,返回值传递给
(5) componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
(1) componentWillUnmount() => 常用,一般在这个钩子中做一些收尾的事,
例如:关闭定时器、取消订阅消息
<script type="text/babel">
class Count extends React.Component{
//构造器
constructor(props) {
console.log("Count===构造器constructor执行")
super(props);
//初始化数据
this.state={
count:0
}
}
//函数点我加1
add = ()=>{
console.log('add函数执行')
const {count} = this.state
this.setState({count:count+1})
}
//函数卸载组件
death = ()=>{
ReactDOM.unmountComponentAtNode(document.getElementById("test"))
}
//函数强制更新
force = ()=>{
console.log("count====force函数执行")
this.forceUpdate()
}
//==============生命周期钩子函数===============
//若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
static getDerivedStateFromProps(props, state){
console.log('count====getDerivedStateFromProps 钩子函数执行',props, state)
return null
}
//组件挂载完毕
componentDidMount(){
console.log('count====componentDidMount组件挂载完成钩子函数执行')
}
//组件将要卸载
componentWillUnmount(){
console.log('count====componentWillUnmount组件卸载钩子函数执行')
}
//=================更新数据============
//更新组件 返回boole值
shouldComponentUpdate(){
console.log('count====shouldComponentUpdate组件更新钩子函数执行')
//如果返回false,后面的更新操作将不在执行
return true
}
//更新组件之前获取快照
getSnapshotBeforeUpdate(){
console.log('count====getSnapshotBeforeUpdate 钩子函数执行')
return false
}
//组件更新完成
componentDidUpdate(preProps,preState,snapshotValue){
console.log('count====componentDidUpdate组件更新完成钩子函数执行',preProps,preState,snapshotValue)
}
render() {
console.log("Count===render组件执行")
const {count} = this.state
return (
<div>
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
</div>
);
}
}
ReactDOM.render(<Count/>, document.getElementById('test'))
</script>
? 初始化
? 更新数据页面
? 强制更新
? 卸载组件
注意:
1、17及以上版本componentWillMount、componentWillUpdate、componentWillReceiveProps三个钩子使用前要加UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。
2、新的生命周期和旧的生命周期相比,除了即将废弃三个钩子,还添加了两个新的钩子getDerivedStateFromProps和getSnapshotBeforeUpdate
3、static getDerivedStateFromProps:适用于罕见用例(几乎不用),返回null或state对象,state的值在任何时候都取决于props
4、getSnapshotBeforeUpdate(prevProps,prevState,):在更新之前获取快照,返回值传递给componentDidUpdate(prevProps,prevState,snapshotValue)
7. getSnapShotBeforeUpdate的使用场景
保留更新之前的原始数据
<script type="text/babel">
class NewsList extends React.Component{
//构造器
state = {
newArr:[]
}
//组件挂载完成
componentDidMount(){
//开启定时任务 每一秒钟增加一条新闻
setInterval(()=>{
const {newArr} = this.state
const news = "新闻"+newArr.length
this.setState({newArr:[news, ...newArr]})
},1000)
}
//更新组件之前获取快照
getSnapshotBeforeUpdate(){
//需求:定位到中间为止不动
//获取数据高度
console.log(this.refs.list.scrollHeight)
return this.refs.list.scrollHeight
}
//组件更新完成
componentDidUpdate(preProps,preState,snapshotValue){
//完成定位
this.refs.list.scrollTop += this.refs.list.scrollHeight - snapshotValue
}
render() {
const {newArr} = this.state
return (
<div>
<div className="list" ref="list">
{
newArr.map((item,index)=>{
return <div key={index} className="news">{item}</div>
})
}
</div>
</div>
);
}
}
ReactDOM.render(<NewsList/>, document.getElementById('test'))
</script>
<style>
.list{
width: 200px;
height: 200px;
background-color: skyblue;
overflow: auto;
}
.news{
height: 30px;
}
</style>
结语:
努力了这么久,但凡有点儿天赋,也该有些成功的迹象了
回复react笔记,可以获得全套笔记