现在有一个需求:在页面中显示一个标题,初始化时该组件的透明度就在0-1之间进行变化,直到点击按钮卸载组件为止。
<!-- 准备好员工“容器” --> <div id="app"></div> <!-- 引入ReactJS核心库 --> <script type="text/javascript" src="../JS/react.development.js"></script> <!-- 引入React-DOM核心库,用于操作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> <!-- 此处类型为babel --> <script type="text/babel"> class Life extends React.Component { // 初始化状态 state = { opacity: 1 } // 卸载组件 death = () => { ReactDOM.unmountComponentAtNode(document.getElementById('app')) } // 组件挂载完毕 componentDidMount () { this.timer = setInterval(() => { let { opacity } = this.state opacity -= 0.1 if (opacity <= 0) opacity = 1 this.setState({ opacity }) }, 200); } // 组件将要被卸载 componentWillUnmount () { clearInterval(this.timer) } render () { return ( <div> <h1 style={{ opacity: this.state.opacity }} >React学不会怎么办?</h1> <button onClick={this.death}>不活了</button> </div> ) } } // 2、将虚拟DOM渲染到页面,标签必须闭合 ReactDOM.render(<Life />, document.getElementById('app')) </script>
以上代码中有一些新的面孔,就是react
中的生命周期。接下来我们来捋顺一下该组件的逻辑。
1、初始化状态,设置了一个opacity的属性状态,该状态用于记录透明度。
2、在h1标签中设置一个style样式属性,并设置其透明度
3、在按钮中添加onClick事件,用于卸载组件,需要使用ReactDOM.unmountComponentAtNode方法
4、在组件挂载完毕后,我们需要开启透明度的变化,所以需要在componentDidMount生命周期钩子函数,编写逻辑。
5、在组件将要被卸载时需要清除定时器,所以需要引出componentWillUnmount生命周期钩子函数。
理解生命周期(旧)
React组件的生命周期是指组件从实例化到销毁的整个过程,其中包括组件的挂载、更新和卸载三个阶段。在这个过程中,React提供了一些特定的函数,称为生命周期函数,可以让我们在组件的不同阶段执行一些操作。
React组件的生命周期可以分为三个阶段:
- 挂载阶段:组件实例被创建并插入到DOM中。
- 更新阶段:组件的状态或属性发生变化,导致组件重新渲染。
- 卸载阶段:组件从DOM中移除。
在这三个阶段中,React提供了一些特定的生命周期函数,可以让我们在组件的不同阶段执行一些操作。
- constructor:组件被创建时调用,用于初始化组件的状态和绑定事件处理函数等操作。
- componentWillMount:组件被插入到DOM中前调用,用于执行一些初始化操作。
- render:组件被创建或更新时调用,用于生成组件的虚拟DOM。
- componentDidMount:组件被插入到DOM中时调用,用于执行一些需要DOM的操作,如获取元素的宽高等。
- componentWillReceiveProps:组件接收到**新的props**时调用,用于更新组件的状态。
- shouldComponentUpdate:组件被更新时调用,用于判断是否需要重新渲染组件。
- componentWillUpdate:组件被更新前调用,用于执行一些更新前的操作。
- componentDidUpdate:组件被更新后调用,用于执行一些更新后的操作,如更新后的DOM状态等。
- componentWillUnmount:组件被销毁前调用,用于执行一些清理操作,如清除定时器等。
我们通过代码显示一下这些生命周期的流程:
class Count extends React.Component { constructor(props){ console.log('Count--constructor') super(props) // 初始化状态 this.state = { count: 0 } } // 卸载组件 death = () => { ReactDOM.unmountComponentAtNode(document.getElementById('app')) } // 求和加1 add = () => { let { count } = this.state count += 1 this.setState({count}) } // 强制更新 force = () => { this.forceUpdate() } // 组件将要挂载完成 componentWillMount(){ console.log("Count--componentWillMount") } // 组件挂载完毕 componentDidMount() { console.log("Count--componentDidMount") } // 判断组件是否需要更新,返回一个false或者true shouldComponentUpdate(){ console.log("Count--shouldComponentUpdate") return true } // 组件将要更新 componentWillUpdate(){ console.log("Count--componentWillUpdate") } // 组件更新完毕 componentDidUpdate(){ console.log("Count--componentDidUpdate") } // 组件将要被卸载 componentWillUnmount(){ console.log("Count--componentWillUnmount") } // 渲染DOM结构 render () { console.log("Count--render") const {count} = this.state return ( <div> <h1>当前求和为:{count}</h1> <button onClick={this.add}>点我+1</button> <button onClick={this.force}>强制更新</button> <button onClick={this.death}>卸载组件</button> </div> ) } } // 2、将虚拟DOM渲染到页面,标签必须闭合 ReactDOM.render(<Count />, document.getElementById('app'))
以上组件功能:
- 当我点击【点我+1】的按钮时,使得状态里面的
count
自增1。 - 当我点击【强制更新】的按钮时,使得组件调用
this.forceUpdate()
方法。 - 当我点击【卸载组件】的按钮时,调用
ReactDOM.unmountComponentAtNode
方法卸载组件。
步骤1:初始化组件===>查看执行了哪些生命周期
Count--constructor Count--componentWillMount Count--render Count--componentDidMount
步骤2:点击自增按钮时===>查看执行了哪些生命周期
Count--shouldComponentUpdate Count--componentWillUpdate Count--render Count--componentDidUpdate
注意:shouldComponentUpdate
如果返回的是false
或者undefined
,则会终止组件的更新流程。
步骤3:点击卸载按钮时===>查看执行了哪些生命周期
Count--componentWillUnmount
以上组件我们发现有一个生命周期没有复现,那就是componentWillReceiveProps
, 在此我们需要写一个新的案例:
class A extends React.Component { // 初始化状态 state = {carName:'特斯拉'} changeCar = () => { this.setState({carName:'奔驰'}) } // 渲染DOM结构 render () { return ( <div> <h1>我是父组件A</h1> <button onClick={this.changeCar}>换车</button> <B carName={this.state.carName}/> </div> ) } } class B extends React.Component { // 组件接收到新的`props`时调用 componentWillReceiveProps(){ console.log('B--componentWillReceiveProps') } render() { console.log("B--render") return ( <div>我是子组件B,我收到的新车是:{this.props.carName}</div> ) } } // 2、将虚拟DOM渲染到页面,标签必须闭合 ReactDOM.render(<A />, document.getElementById('app'))
以上代码,组件A是父组件,组件B是子组件,父组件给子组件传了一个props
===>carName
,子组件接收该标签属性,并展示它。当我点击父组件的【换车】按钮时,看看子组件执行了哪些生命周期:
B--componentWillReceiveProps B--shouldComponentUpdate B--componentWillUpdate B--render B--componentDidUpdate
注意:初始化组件时,生命周期钩子componentWillReceiveProps
并不会执行,只有接收新的props时该生命周期钩子才会执行。
小总结
1、初始化阶段:由ReactDOM.render()
触发—初次渲染
- 1===>
constructor()
- 2===>
componentWillMount()
- 3===>
render()
- 4===>
componentDidMount()
2、更新阶段:由组件内部this.setState()
或者父组件render
触发
- 1===>
shouldComponentUpdate()
- 2===>
componentWillUpdate()
- 3===>
render()
- 4===>
componentDidUpdate()
3、 卸载组件:由ReactDOM.unmountComponentAtNode()
触发
- 1===>
componentWillUnmount()
常用的两个生命周期钩子函数是: componentDidMount()和componentWillUnmount()。一个做一些初始化的事情,如:开启定时器,发送网络请求,订阅消息等,一个做一些收尾工作,如:关闭定时器,取消订阅消息等。