系列文章目录
👏欢迎来到我的React系列文章
🍭本系列文章从React入门开始,涵盖了React的一切基础,属于是从零开始的一个系列
🍭文章会以图文结合-动图-代码实现-解释代码的形式带领大家走进React的世界
🍭本系列会从React v16.8 开始 => 直到React v 18.0 新版旧版一起抓
🍭持续更新中~希望大家能够喜欢,系列文章👉点这里
🌈博客主页👉点这里
👋回见~
- 🔥React入门与概览(JSX语法)
- 🔥面向组件编程——组件实例的三大核心属性state、props和refs超详解
- 🔥受控组件与非受控组件(vue和react的双向绑定分别是怎么实现的?)
- 🔥React函数的柯里化(什么?这玩意儿不仅能装x,还能优化代码?)
- 🔥四行代码让我的cpu跑上90度——走进组件生命周期
文章目录
有这么一个示例效果:
示例效果
需求:定义组件实现以下功能:
1.让指定的文本做显示/隐藏的渐变动画
2.从完全可见,到彻底消失,耗时2S
3.点击“不活了”按钮从界面中卸载组件
代码实现?
我一看到这个小示例,我立马就从天桥底下爬起来,冲向了最近的一个网吧,因为我知道,这玩意儿我会啊!
花了我两块大洋开了台机后,我飞快的敲出下面的代码:
<script type="text/babel">classLifeextendsReact.Component{// 将不透明度存放到state中
state ={opacity:1}render(){
console.log('render')// 每隔200ms,将不透明度减少0.1setInterval(()=>{// 获取原状态let{ opacity }=this.state
// 减小0.1
opacity -=0.1if(opacity <=0) opacity =1// 设置新的不透明度// this.setState({ opacity: opacity });这是标准写法,可以简写成:this.setState({ opacity });},200)return(<div><h2 style={{opacity:this.state.opacity }}>React学不会怎么办?</h2><button onClick={this.death}>不活了</button></div>);}// 挂载 mount,卸载 unmountdeath=()=>{// 在这里卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'))}}// 挂载 mount
ReactDOM.render(<Life />, document.getElementById('test'))</script>
反手直接运行!这还不是敢敢单单?
结果一看界面我傻眼了:
React在疯狂的调用render,不停的重新渲染组件,短短1分钟,很快啊~网吧的主机就有一个鲁大师在里边抽烟了…
在网吧老板的死亡注视下,我立马关闭了演示的网页…
回过头瞅瞅代码,嗯,发现问题了:
render(){
console.log('render')// 每隔200ms,将不透明度减少0.1setInterval(()=>{// 获取原状态let{ opacity }=this.state
// 减小0.1
opacity -=0.1if(opacity <=0) opacity =1// 设置新的不透明度// this.setState({ opacity: opacity });这是标准写法,可以简写成:this.setState({ opacity });},200)return(<div><h2 style={{opacity:this.state.opacity }}>React学不会怎么办?</h2><button onClick={this.death}>不活了</button></div>);}
setInterval计时器放在render中,该计时器内部又封装了
this.setState
方法,第一次函数挂载到页面中,调用了setInterval函数,函数每过200ms就会对state中的数据进行更改,每次更改后又会调用render对组件更新重新渲染,重新渲染时又触发了serInterval函数。
也就是说,setInterval函数一直在被调用,而之前的计时器又没有被关闭,页面在不断的生成计时器,触发了递归暖手成就,属于是子子孙孙无穷尽也~
let{ opacity }=this.state
opacity -=0.1if(opacity <=0) opacity =1this.setState({ opacity });
没想到短短四行代码,让我的cpu一直在跑,一路向北直到90度…
没想到这个看上去简单的小示例还真不简单(什么废话文学)
怎么解决呢?
究其原因,setInterval计时器显然是不能放在render中了,了解vue的道友立马就想到了,用生命周期就好了!
这才是真正的代码实现——组件的生命周期
<script type="text/babel">classLifeextendsReact.Component{// 将不透明度存放到state中
state ={opacity:1}// 状态更新就调render,每次计时器更新状态就会调用render,然后又会重新开启一个定时器,// 5s内render调用上万次// 无限递归暖手,所以计时器不能放在render中render(){// render调用的时机:初始化渲染、状态更新之后
console.log('render')// 每隔200ms,将不透明度减少0.1/*
setInterval(() => {
// 获取原状态
let { opacity } = this.state
// 减小0.1
opacity -= 0.1
if (opacity <= 0) opacity = 1
// 设置新的不透明度
// this.setState({ opacity: opacity });这是标准写法,可以简写成:
this.setState({ opacity });
}, 200)
*/return(<div><h2 style={{opacity:this.state.opacity }}>React学不会怎么办?</h2><button onClick={this.death}>不活了</button></div>);}// 组件完成挂载时调用componentDidMount(){this.timer =setInterval(()=>{// 获取原状态let{ opacity }=this.state
// 减小0.1
opacity -=0.1if(opacity <=0) opacity =1// 设置新的不透明度// this.setState({ opacity: opacity });这是标准写法,可以简写成:this.setState({ opacity });},200)}// 组件将要被卸载之前时调用componentWillUnmount(){// 清空定时器clearInterval(this.timer)}// 挂载 mount,卸载 unmountdeath=()=>{// 在这里卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('test'))}}// 挂载 mount
ReactDOM.render(<Life />, document.getElementById('test'))</script>
理解
- 组件从创建到死亡它会经历一些特定的阶段。
- React组件中包含一系列钩子函数(生命周期回调函数), 会在特定的时刻调用。
- 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
解释
React提供了非常丰富的生命周期函数,以供开发者使用。这里就涉及到了其中两个重要的生命周期函数:
componentDidMount:组件完成挂载时调用,将setInterval计时器放在这里,组件完成挂载时调用计时器,就算计时器内部调用了
this.setState
方法对组件的state进行修改,组件重新渲染,也不会重复打开新的计时器,避免了电脑
Boom
沙卡拉卡的悲剧。
unmountComponentAtNode:卸载组件。
componentWillUnmount:组件将要被卸载之前时调用,点击
不活了
按钮触发事件中的回调函数death,在组件将要被卸载前调用
clearInterval
清空计时器。
这样就达到示例的最终效果咯~
当然啦,下一篇文章我将会从组件出生到组件临终,为各位道友详细介绍组件的生命周期钩子函数,尽情期待哟~

结账、下机、回天桥底下——深藏功与名~
回见~
版权归原作者 codeMak1r. 所有, 如有侵权,请联系我们删除。