React----组件生命周期知识点整理
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React----组件生命周期知识点整理相关的知识,希望对你有一定的参考价值。
组件生命周期知识点整理
案例引入
需求:定义组件实现以下功能:
-
让指定的文本做显示 / 隐藏的渐变动画
-
从完全可见,到彻底消失,耗时2S
-
点击“不活了”按钮从界面中卸载组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="showInterval"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="./js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作dom -->
<script type="text/javascript" src="./js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转换为js -->
<script type="text/javascript" src="./js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="./js/prop-types.js"></script>
<script type="text/babel">
//创建组件
//生命周期函数,生命周期钩子函数
class Life extends React.Component
{
state={opacity:1}
//组件挂载完毕
componentDidMount()
{
//给类实例增加一个timer属性,保存当前定时器的唯一标识
this.timer=setInterval(()=>{
//获取原状态
let {opacity}=this.state
//减小0.1
opacity-=0.1
if(opacity<=0) opacity=1
//设置新的透明度
this.setState({opacity})
},200)
}
//组件即将卸载
componentWillUnmount()
{
//清除定义器
clearInterval(this.timer)
}
//卸载组件
death=()=>
{
ReactDOM.unmountComponentAtNode(document.getElementById('showInterval'));
}
render()
{
return(
<div>
<h2 style={{opacity:this.state.opacity}}>React学不会怎么办? </h2>
<button onClick={this.death}>拜拜了</button>
</div>
)
}
}
//渲染组件
ReactDOM.render(<Life/>,document.getElementById('showInterval'))
</script>
</body>
</html>
js使用字面量创建对象,当属性名和属性值同名时,可简写{name},等同于{name:name}
注意:
区分类组件中自定义方法,而React会在创建完类实例后,通过类实例调用的方法
如果是自定义方法,React不会自己去调用,因此一般使用变量+箭头函数的形式,将该自定义方法作为一个事件的触发函数
生命周期理解
1.组件从创建到死亡它会经历一些特定的阶段。
2.React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
3.我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
生命周期流程图(旧)
对于shouldComponentUpdate是否应该更新组件的方法来说,如果我们不重写父类该方法,那么该方法默认返回true,重写该方法,返回false,那么下面的流程就不会走了
父子组件
在A的类组件的render方法中调用B组件的标签,此时A是父组件,B是子组件
class A extends React.Component
{
//初始化状态
state={carName:'奔驰'}
changeCar=()=>
{
this.setState({carName:'劳斯莱斯'})
}
render(){
return(
<div>
<div>A组件</div>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName}/>
</div>
)
}
}
class B extends React.Component
{
render(){
return(
<div>
<div>B组件</div>
<div>接收到的车是:{this.props.carName}</div>
</div>
)
}
}
//渲染组件
ReactDOM.render(<A/>,document.getElementById('showInterval'))
componentWillReceiveProps方法—第一次挂载时不会调用,后面更新时才会调用
class A extends React.Component
{
//初始化状态
state={carName:'奔驰'}
changeCar=()=>
{
this.setState({carName:'劳斯莱斯'})
}
render(){
return(
<div>
<div>A组件</div>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName}/>
</div>
)
}
}
class B extends React.Component
{
//组件将要接收新的
componentWillReceiveProps(props)
{
console.log(props)
}
shouldComponentUpdate()
{
console.log('shouldComponentUpdate')
return true
}
componentWillUpdate()
{
console.log('componentWillUpdate')
}
componentDidUpdate()
{
console.log('conponentDidUpdate')
}
render(){
console.log('render')
return(
<div>
<div>B组件</div>
<div>接收到的车是:{this.props.carName}</div>
</div>
)
}
}
//渲染组件
ReactDOM.render(<A/>,document.getElementById('showInterval'))
旧版生命周期总结
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(),一般在这个钩子中做一些收尾的事情,例如:关闭定时器,取消订阅消息
React生命周期----新版本
新版本的React即将废弃三个钩子,如果还要使用前面加上UNSAFE_,尽量少用
新增钩子getDerivedStateFromProps ----让组件在 props 变化时更新 state
static getDerivedStateFromProps(props, state)
getDerivedStateFromProps
会在调用 render
方法之前调用,并且在初始挂载及后续更新时都会被调用
。它应返回一个对象来更新 state
,如果返回 null
则不更新任何内容。
如果返回的不是一个js对象,那么效果等同于null
此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props
getDerivedStateFromProps 的存在只有一个目的:让组件在 props 变化时更新 state。
class B extends React.Component
{
state={count:520}
static getDerivedStateFromProps(props,state)
{
console.log(props,state)
if(props.count===state.count)
return state
return props
}
render(){
console.log('render')
return(
<div>
<div>count的值为: {this.state.count}</div>
</div>
)
}
}
//渲染组件
ReactDOM.render(<B count={521}/>,document.getElementById('showInterval'))
一旦getDerivedStateFromProps返回一个js对象,那么后面state的值在任何时候都为该js对象的值,即使调用setState的方法,也没有效果
新增钩子getSnapshotBeforeUpdate----保留渲染前的一些信息
getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate()。
应返回 snapshot 的值(或 null)
class B extends React.Component
{
state={count:520}
//组件在 props 变化时更新 state
static getDerivedStateFromProps(props,state)
{
console.log('getDerivedStateFromProps')
return null
}
//应该更新吗
shouldComponentUpdate()
{
console.log('shouldComponentUpdate')
return true
}
//更新前获取快照
getSnapshotBeforeUpdate(prevProps, prevState)
{
console.log('getSnapshotBeforeUpdate')
return null
}
//更新完毕
componentDidUpdate(prevProps, prevState, snapshot)
{
console.log('componentDidUpdate: ',prevProps, prevState, snapshot)
}
add=()=>{this.setState({count:this.state.count+1})}
render(){
console.log('render')
return(
<div>
<div>count的值为: {this.state.count}</div>
<button onClick={this.add}>加一</button>
</div>
)
}
}
//渲染组件
ReactDOM.render(<B count={521}/>,document.getElementById('showInterval'))
getSnapshotBeforeUpdate的应用案例—滚动条
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</title>
<style>
.list
{
width:200px;
height:150px;
background-color:skyblue;
overflow: auto;
}
.news
{
height: 30px;
}
</style>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="show"></div>
<script type="text/javascript" src="./js/react.development.js"></script>
<script type="text/javascript" src="./js/react-dom.development.js"></script>
<script type="text/javascript" src="./js/babel.min.js"></script>
<script type="text/javascript" src="./js/prop-types.js"></script>
<script type="text/babel">
class NewsList extends React.Component{
state={newsArr:[]}
//每隔一秒中,加载一条新闻
componentDidMount()
{
setInterval(()=>{
//获取原状态
const {newsArr}=this.state
//模拟一条新闻
const news='新闻'+(newsArr.length+1)
//更新状态
this.setState({newsArr:[news,...newsArr]})
},1000);
}
//更新前的数据
getSnapshotBeforeUpdate(prevProps, prevState)
{
//返回更新前的滚动条高度
return this.refs.list.scrollHeight
}
//确保滑到某个位置,当前数据不会被挤下去
//更新后的数据
componentDidUpdate(prevProps, prevState, height)
{
//height获得的是getSnapshotBeforeUpdate的返回值
//this.refs.list.scrollHeight-height等于30,即一条新闻的高度
this.refs.list.scrollTop+=this.refs.list.scrollHeight-height;
}
render()
{
return (
<div className="list" ref='list'>
{
this.state.newsArr.map((n,index)=>{
return <div key={index} className='news'>{n}</div>
})
}
</div>
)
}
}
ReactDOM.render(<NewsList/>,document.getElementById('show'))
</script>
</body>
</html>
scrollTop和scrollHeight
scrollTop: 代表在有滚动条时,滚动条向下滚动的距离也就是元素顶部被遮住部分的高度。在没有滚动条时scrollTop==0恒成立。单位px,可读可设置。
scrollHeight: 因为子元素比父元素高,父元素不想被子元素撑的一样高就显示出了滚动条,在滚动的过程中本元素有部分被隐藏了,scrollHeight代表包括当前不可见部分的元素的高度。而可见部分的高度其实就是clientHeight,也就是scrollHeight>=clientHeight恒成立。在有滚动条时讨论scrollHeight才有意义,在没有滚动条时scrollHeight==clientHeight恒成立。单位px,只读元素。
搞清clientHeight、offsetHeight、scrollHeight、offsetTop、scrollTop
总结
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_前缀才能使用,以后可能会被彻底废弃,不建议使用。
以上是关于React----组件生命周期知识点整理的主要内容,如果未能解决你的问题,请参考以下文章