react第三天组件生命周期

本文详细介绍了React组件的生命周期,包括初始化、运行时和销毁时的各个阶段,以及在这些阶段中可以执行的操作。重点讨论了componentWillMount、render、componentDidMount、componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate和componentDidUpdate等关键钩子函数的用途和执行顺序。通过一个实例展示了如何利用生命周期函数进行性能优化。
摘要由CSDN通过智能技术生成

生命周期

生命周期钩子函数

<script src="./base/react.min.js"></script>
<script src="./base/react-dom.min.js"></script>
<script src="./base/browser.min.js"></script>
//和昨天一样的js文件

初始化生命周期钩子函数

1.getDefaultProps
初始化默认值
2.getInititalState
初始化状态
3.componentWillMount
可以做一些初始化的设置 获取一些数据,但是不建议在这里使用下面细说
4.render
渲染真实dom
5.componentDidMount
渲染真实dom之后

<body>
    <div id="app"></div>
    <div id="app1"></div>
    <script type="text/babel">
        var props_num = 0;
        var state_num = 0;
        var Hello = React.createClass({
            getDefaultProps(){   //初始化值,实例化时,第一个执行,但是实例化多次,只执行一遍
                console.log("getDefaultProps...")
                return {
                    num:++props_num
                }
            },
            //作用:设置组件的初始化状态
            //特点:为每一个组件设置新的状态  简言之,实例化几次,就执行几次
            getInitialState(){
                console.log("getInitialState...")
                return {
                    num:++state_num
                }
            },
            //作用:在这里获取组件的属性与状态,并且可以更改状态
            //在这里更改状态不会影响运行时钩子函数的执行
            //功能?可以做一些初始化的设置  获取一些数据(ajax)
            //但是不在这里进行数据请求。
            //1. 首先未来的17的版本废弃    2.16版,fiber算法 这个钩子函数可能会执行多次,
            //这就意味着,ajax请求也会有多次,这显然不符合我们的预期所以在componentDidMount中请求数据
            //类似于vue中created+beforeMount的结合体
            componentWillMount(){
                console.log("componentWillMount...")
            },
            render(){ //渲染真实dom
                console.log("render...")
                return (
                    <div>hello! {this.props.num} {this.state.num}</div>
                )
            },
            //建议将数据请求的代码放在此钩子函数里面   
            //可以操作真实dom  并且可以实例化一些插件 (类似于vue中mounted)
            componentDidMount(){
                console.log("componentDidmount...")
            }
        })
        ReactDOM.render(<Hello/>,app)
        ReactDOM.render(<Hello/>,app1)
        //实例化两次,运行结果看截图
    </script>
</body>

运行截图
显而易见:实例化两次,
getDefaultProps运行一遍

getInitialState
componentWillMount
render
componentDidmount
这四个函数运行两遍,且按顺序执行

运行中钩子函数

1.componentWillReceiveProps
即将接收数据
2.shouldComponentUpdate
属性或者状态改变的时候,此钩子函数就会执行
3.componentWillUpdate
shouldComponentUpdate一旦返回true,这个函数立马触发
4.componentDidUpdate
render渲染完毕后触发

一个简单的实例,爸爸打儿子,打五次儿子会疼

<body>
    <div id="app"></div>
    <script type="text/babel">
        var Father = React.createClass({
            getInitialState(){   //初始化状态
                return {
                    hit:0
                }
            },
            hitSon(){
                //更改自身状态
                this.setState({
                    hit:++this.state.hit
                })
            },
            render(){
                return (
                    <div>
                        <p>我是father..</p> 
                        <p><button onClick={this.hitSon}>开打了!</button></p>
                        <Son hitnum={this.state.hit}/>  //将次数传递给儿子
                    </div>
                )
            }
        });

        var Son = React.createClass({
            getInitialState(){   //初始化状态,不疼
                return {
                    pain:false
                }
            },
            //此钩子函数默认不会执行,只有属性发生改变的时候,才会执行此钩子函数
            //会发现this.props.hitnum获取到的还是之前的属性
            //作用?可以根据更改后的属性做一些操作,例如可以更改状态
            //并且在这里更改状态不会触发生命周期钩子函数的重复执行
            componentWillReceiveProps(nextProps,nextState){
            	//两个参数,第一个是更新后的参数,第二个是更新后的状态
                console.log("componentWillReceiveProps....",nextProps.hitnum)
                if(nextProps.hitnum >=5 && !this.state.pain){
                    this.setState({pain:true})
                }
            },
            //触发条件:属性或者状态改变的时候,此钩子函数就会执行
            //默认返回true  向下执行组件更新操作  返回false就不会执行更新操作了
            //作用? 可以阻止组件的更新,提升性能,很重要
            shouldComponentUpdate(nextProps,nextState){
                console.log("shouldComponentUpdate...")
                if(nextProps.hitnum>=5){ //如果打了5次,才会进行后续的更新组件  虚拟dom对比
                    return true;
                }
                return false //后续更新操作不再执行了!
            },
            //触发条件: shouldComponentUpdate一旦返回true立马触发
            componentWillUpdate(){
                console.log("componentWillUpdate...")
            },
            render(){ 
                console.log("render...")
                let {pain} = this.state;
                return (
                    <div>
                        <p>我是son </p>
                        <p>被打了{this.props.hitnum}</p>
                        <p>{pain || "不"}</p>
                    </div>
                )
            },
            componentDidUpdate(){
                console.log("componentDidUpdate...")
            },
        })
        ReactDOM.render(<Father/>,app)
    </script>
</body>

①运行完截图,页面会进行一次渲染
运行完
②开打第一次截图,接收到数据了,执行shouldComponentUpdate,但是不符合我们的条件,所以返回false不执行页面渲染等三个钩子函数。可见我们的值已经被修改了,但是页面上没有显示
开打
③开打第二次
开打第二次
④开打第五次,依旧接收了数据,数据改变执行shouldComponentUpdate,这次返回true,开始执行componentWillUpdate,然后渲染页面render,渲染完毕componentDidUpdate。我们在shouldComponentUpdate中进行判断,只有符合条件了才会进行dom操作,所以可以在这里进行优化处理
打了五次
完美的符合我们的生命周期图示

销毁时触发的钩子函数

componentWillUnmount

<style>
    body { height: 2000px; }
    #app { position: fixed; }
    .world { width: 100px; height: 100px; border: 1px solid red; }
</style>
<body>
    <div id="app"></div>
</body>//这个实例,每次点击的时候,让元素显示与隐藏
<script type = "text/babel">
    var Hello = React.createClass({
        getInitialState(){     //初始化我们的状态
            return {
                isShow:true
            }
        },
        toggle(){     //这是个开关,每次点击我们改变isShow的状态
            this.setState((prevState,prevProps)=>{
                return {
                    isShow:!prevState.isShow
                }
            })
        },
        render(){
            return (
                <div>
                    <button onClick={this.toggle}>toggle</button>
                    {!this.state.isShow || <World/>}
                </div>
            )
        }
    })
    var World = React.createClass({
        //当组件销毁的时候,执行componentWillUnmount
        //销毁的钩子函数? 可以做一些善后的操作   清除定时器  清除事件绑定
        componentWillUnmount(){
            console.log("world-componentWillUnmount")
            clearInterval(this.timer);
        },
        componentWillMount(){
            //开启定时器
            this.timer = setInterval(() => {
                console.log(11111111111111)
                this.changeColor()
            }, 1000);
        },
        changeColor(){   //状态只能自身去改变
            this.setState({
                color: this.getRandomColor()
            })
        },
        getInitialState(){   //初始化我们的颜色状态
            return {
                color:"blue"
            }
        },
        render(){
            return (
                <div style={{background:this.state.color}} className="world"></div>
            )
        },
        getRandomColor () { //这是个生成随机颜色的方法
            return '#'+'0123456789abcdef'.split('').map(function(v,i,a){
                return i>5 ? null : a[Math.floor(Math.random()*16)] }).join('');
        }
    })
    ReactDOM.render(<Hello/>,document.getElementById('app'))
</script>

①这里运行之后,下面的div框的背景颜色会一秒一变,我们在定时器中,改变状态,改变状态之后,会触发shouldComponentUpdate钩子函数,默认返回值为true,然后执行componentWillUpdate,紧接着render渲染页面,再然后执行componentDidUpdate,所以页面上的元素在,在状态改变时,也会实时更新。(根据最上面的图示也可以看到)
运行截图
②然后我们点击toggle按钮,让isShow变为非isShow,可见触发了我们的componentWillUnmount钩子函数。
运行截图
这里加点别的,vue框架在销毁组件的时候,只是解除数据的双向绑定、监听等,且dom结构还存在,而react是将dom也消除掉。

这里总结一下,不管是属性还是状态改变,render函数会重新执行,页面都会重新渲染
这里shouldComponentUpdate 默认返回true
属性改变 componentWillReceiveProps—> shouldComponentUpdate—> componentWillUpdate—> render—> componentDidUpdate

状态改变 shouldComponentUpdate—> componentWillUpdate—> render—> componentDidUpdate

React 的 Class 组件生命周期可以分为以下几个阶段: 1. Mounting(挂载阶段): - constructor:初始化组件的状态和绑定事件。 - static getDerivedStateFromProps(props, state):根据传入的 props 更新 state。 - render:渲染组件的内容。 - componentDidMount:组件第一次渲染之后调用,通常用于发送网络请求或订阅事件。 2. Updating(更新阶段): - static getDerivedStateFromProps(props, state):根据传入的 props 更新 state。 - shouldComponentUpdate(nextProps, nextState):决定是否重新渲染组件。默认情况下,每次 state 或 props 更新都会触发重新渲染。 - render:渲染组件的内容。 - componentDidUpdate(prevProps, prevState):组件更新之后调用,通常用于更新 DOM 或执行其他副作用操作。 3. Unmounting(卸载阶段): - componentWillUnmount:组件卸载之前调用,通常用于清理定时器、取消订阅等操作。 4. Error Handling(错误处理阶段): - static getDerivedStateFromError(error):在子组件抛出错误时调用,返回一个新的 state 以渲染错误信息。 - componentDidCatch(error, info):在子组件抛出错误后调用,通常用于记录错误信息。 这些生命周期方法提供了在组件不同阶段执行代码的机会,方便开发者进行管理和控制。不过需要注意的是,在 React 16.3 之后,官方已经推荐使用函数组件React Hooks 来替代 Class 组件生命周期方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值