首先,附上生命周期这部分的github代码地址
https://github.com/xinyeshuaiqi/ReactLearn/tree/master/7_lifecycle
再附上React组件生命周期完整的示意图
每一个组件都有关于生命周期的许多方法,我们可以重写这些方法
目录
组件生命周期的三个状态
Mounting
下面这些方法将在组件被创建和插入到DOM中时被调用:
Updating
props 或者 state的变化会导致更新,当一个组件被重新渲染时,下面这些方法将被调用:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
Unmounting
当一个组件被从DOM中移除时,下面这个方法将会被调用
怎么从DOM中移除一个组件?
ReactDOM.unmountComponentAtNode(document.getElementById('demo')) : 移除demo容器中的组件
上代码来直观感受下组件的生命周期及对应方法的调用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件生命周期</title>
</head>
<body>
<div id="demo"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
class LifeCycle extends React.Component{
constructor(props){
super(props);
this.state={
person:{
name:'wmx',
age:21
}
}
console.log('constructor被调用 ----> 创建组件实例')
}
//组件将要被渲染
componentWillMount(){
console.log('componentWillMount被调用 ----> 组件将被渲染')
}
//组件已经被渲染
componentDidMount(){
console.log('componentDidMount被调用 ----> 组件已经被渲染')
}
render(){
console.log('render被调用 ----> 渲染组件')
let {person} =this.state;
return (
<div>{person.name},{person.age}</div>
)
}
}
ReactDOM.render(<LifeCycle />,document.getElementById('demo'));
</script>
</body>
</html>
constructor、componentWillMount、componentDidMount只调用一次
render什么时候还会调用?
更新状态后 — > 组件更新 — >调用render( )
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件生命周期 - 更新</title>
</head>
<body>
<div id="demo"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
/*
* 为了便于观察理解,组件的渲染单独放在demo.html
* demo1.html有组件的更新
* */
class LifeCycle extends React.Component{
constructor(props){
super(props);
this.state={
person:{
name:'xinye',
age:21
}
}
console.log('constructor被调用 ----> 创建组件实例')
}
//组件将要被渲染
componentWillMount(){
console.log('componentWillMount被调用 ----> 组件将被渲染')
//这里可以发送ajax请求,开启定时器
/*
* 为什么ajax请求放在这里?
* 组件还没有渲染出来,就发送请求,数据来了,页面也刚好渲染出来了
*
* 但是如果componentWillMount干的活太重话,render()方法一直还没执行,用户一直等待页面的渲染、
*
* 可以根据需求选择在componentWillMount()还是componentDidMount()发送ajax请求
* */
//开启定时器 定时器的this是window,因此需要修改this
setTimeout(function () {
this.setState({
person:{
name:'wmx',
age:22
}
})
}.bind(this),5000) //推迟5秒钟,修改状态
}
//组件已经被渲染 用户已经看到界面
componentDidMount(){
console.log('componentDidMount被调用 ----> 组件已经被渲染')
}
//组件将要更新
componentWillUpdate(){
console.log('componentWillUpdate被调用 ----> 组件将要更新')
}
//组件已被更新
componentDidUpdate(){
console.log('componentDidUpdate被调用 ----> 组件已经更新')
}
//组件将被移除
componentWillUnMount(){
console.log('componentWillUnMount被调用 ----> 组件将被移除')
}
render(){
console.log('render被调用 ----> 渲染组件')
let {person} =this.state;
return (
<div>{person.name},{person.age}</div>
)
}
}
ReactDOM.render(<LifeCycle />,document.getElementById('demo'));
</script>
</body>
</html>
基于上面的代码,我们加一个组件的移除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件生命周期 - 移除</title>
</head>
<body>
<div id="demo"></div>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
class LifeCycle extends React.Component{
constructor(props){
super(props);
this.state={
person:{
name:'xinye',
age:21
}
}
console.log('constructor被调用 ----> 创建组件实例')
}
//组件将要被渲染
componentWillMount(){
console.log('componentWillMount被调用 ----> 组件将被渲染')
setTimeout(function () {
this.setState({
person:{
name:'wmx',
age:22
}
})
}.bind(this),3000) //推迟5秒钟,修改状态
}
//组件已经被渲染 用户已经看到界面
componentDidMount(){
console.log('componentDidMount被调用 ----> 组件已经被渲染')
setTimeout(function () {
//移除组件
ReactDOM.unmountComponentAtNode(document.getElementById('demo')); //参数是一个容器
}.bind(this),5000) //5秒钟后,移除组件
//返回一个intervalId 的定时器的标识符塞入实例中
this.intervalId = setInterval(function () {
console.log('循环定时器...')
}.bind(this),1000)
}
//组件将要更新
componentWillUpdate(){
console.log('componentWillUpdate被调用 ----> 组件将要更新')
}
//组件已被更新
componentDidUpdate(){
console.log('componentDidUpdate被调用 ----> 组件已经更新')
}
//组件将被移除
componentWillUnmount(){
console.log('componentWillUnmount被调用 ----> 组件将被移除')
//在这里做一些收尾工作:关掉一些东西
//关掉我们在componentDidMount()中的循环定时器
clearInterval(this.intervalId)
console.log('循环定时器已关闭...')
}
render(){
console.log('render被调用 ----> 渲染组件')
let {person} =this.state;
return (
<div>{person.name},{person.age}</div>
)
}
}
ReactDOM.render(<LifeCycle />,document.getElementById('demo'));
</script>
</body>
</html>
还有一个额外的功能就是循环定时器的开启和关闭
div里为空,也证明了组件的移除
关于组件生命周期的练习
我们要设置文字的透明度不停地变化
opacity 属性设置元素的不透明级别
从 0.0 (完全透明)到 1.0(完全不透明)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件生命周期练习</title>
</head>
<body>
<a id="demo" href="http://www.xinyeshuaiqi.cn"></a>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//将要展示的效果 : 页面字体的透明度改变
class ShowSomething extends React.Component{
constructor(props){
super(props);
this.state={
opacity:1 //不断修改这个opacity
}
}
componentDidMount(){
let opacity = this.state.opacity;
setInterval(()=>{
opacity-=0.05; //加减有一定的偏差
if(opacity < 0){
opacity=1;
}
this.setState({opacity});
},500)
}
render(){
let opacity=this.state.opacity;
//虚拟DOM内写大括号,需要写2对{ }
return (
<div style={{opacity:opacity}}>xinyeshuaiqi.cn</div>
)
}
}
ReactDOM.render(<ShowSomething/>,document.getElementById('demo'));
</script>
</body>
</html>
最终显示效果:渲染的组件的文字随时间变透明
最后再来看下React的diff算法:
先贴上代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>React diff算法( 最小化页面重绘 )</title>
</head>
<body>
<div id="demo"></div>
<br>
<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
class TimeRecord extends React.Component {
constructor(props) {
super(props);
this.state = {
date: new Date()
};
}
componentDidMount () {
setInterval(() => {
this.setState({
date: new Date()
})
}, 1000) //每一秒钟更新一次 页面重绘一次
}
render () {
console.log('render()调用...');
/*观察在输入框内输入的东西,会不会每秒清空一次
如果清空了,说明整个页面都随着state状态的改变而重绘
如果没有清空,则说明重绘只是针对小范围的,即最小化页面重绘 (局部)
*/
return (
<p>
<input type="text" placeholder="input something"/>!
当前时间 :{this.state.date.toTimeString()}
</p>
);
}
}
ReactDOM.render(
<TimeRecord/>, document.getElementById('demo')
);
</script>
</body>
</html>
文字随着时间推移,并没有刷新,说明这一部分并没有重新绘制,只是时间显示的这一部分变化,重新绘制,即最小页面重绘。
转载请注明:汪明鑫的个人博客 » React组件的生命周期
说点什么
您将是第一位评论人!