React生命周期162版本之前老的

导读:本篇文章讲解 React生命周期162版本之前老的,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

老生命周期存在的一些问题
1.componentWillMount:在ssr中 这个方法将会被多次调用,所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致
内存泄漏 ,变得不够安全高效,逐步废弃。

2.componentWillReceiveProps:外部组件多次频繁更新传入多次不同的 props,会导致不必要的异步请求。

3.componetWillupdate:更新前记录 DOM 状态, 可能会做一些处理,与componentDidUpdate相隔时间如果过长,会导致状态不可信。

1.初始化阶段

(1)componentWillMount:将要挂载
	客户端一辈子只执行一次,服务端渲染会执行多次,render之前最后一次修改状态的机会,(类似于:vue 中的 beforeMount)。如果
	在这里要发Ajax、setInterval会有隐患,在服务端渲染的时候,这个生命周期会重复执行,会导致Ajax发送多次请求、定时器会关闭不了。

(2)render:正在渲染
	只能访问this.props 和 this.state,不允许修改状态和DOM输出。
	
(3)componentDidMount: 已经挂载完了
	一辈子只执行一次,在render成功渲染完真实的DOM后触发,可以修改DOM(类似于:vue 中的 Mounted)
import React, { Component } from 'react'

export default class App extends Component {
    state = {
        list:[]
    }

	/*
		不建议用这个生命周期,不安全,如果非要用的话,
		加上一个UNSAFE_  --> UNSAFE_componentWillMount(){},
		17版本要加UNSAFE_
	*/ 
    componentWillMount(){
       /*
       		Ajax和setInterval一般不写在这里,一般写在componentDidMount里,因为有个隐患,
       		将来在服务端渲染的时候,这个生命周期会重复执行,Ajax和setInterval多次执行,
       		会导致Ajax发送多次请求、定时器会关闭不了
       */
    }

    componentDidMount() {
        // Ajax、常规工作、绑定事件、启动定时器
        // React没有新的Ajax请求方式 --> fetch、axios
        // 如果要做假数据,把json文件放在public静态资源文件夹下
        fetch("/test.json").then(res=>res.json()).then(res=>{
            console.log(res)
            this.setState({
                list:res.coming
            })
        })
    }
    
    render() { // 每次重新渲染页面的时候,都会走一遍render
        return (
            <div>
                {
                    this.state.list.map(item=>
                        <li key={item.id}>
                            <img src={item.img.replace('w.h','128.180')}/>
                            {item.nm}
                        </li>
                    )
                }
            </div>
        )
    }
}

2.运行中阶段

1.componentWillReceiveProps(nextProps,nextState){}:
	父组件修改属性时触发(要建立在父子关系下才会用到这个生命周期,写在子组件身上)父子通信的时候,因为componentDidMount
只执行一遍,componentWillReceiveProps会走多次,所以获取不到新的Ajax数据,要在componentWillReceiveProps中获取Ajax

2.shouldComponentUpdate:
组件是否更新了,返回false会阻止render调用

3.componentWillUpdate:
不能修改属性和状态

4.render:
只能访问 this.props 和 this.state,不允许修改状态和DOM输出

5.componentDidUpdate:
可以修改DOM

没有父子关系的情况:

import React, { Component } from 'react'

export default class App extends Component {
    state = {
        myname:"kerwin"
    }
    
    componentWillUpdate(){ // 3.将要更新
    }

    componentDidUpdate(){ // 5.已经更新完了 
    }

    componentWillReceiveProps(){ 
    // 要在父子通信的情况下才使用,写在子组件身上,因为App是根组件,所以App没有父组件,
    }

	// 7.优化性能:判断myname这个状态是否改变了,改变了就走更新,没改变就不走更新
	// shouldComponentUpdate -- 性能调优函数
    shouldComponentUpdate(nextProps, nextState) { // (代码提示:scu)
        // 8.状态myname改变了
        // (对比:nextProps是老的,在父子通信下才会用   nextState是新的 )
        // (对比:this.state.myname是老的   nextState.myname是新的 )
        if(this.state.myname !== nextState.myname){
            return true // true就更新
        }
        return false //  状态没改变,false就不更新
    }
    
	// 4.正在更新
    render() {
        // 1.先渲染一遍页面
        return (
            <div>
                {this.state.myname}
         {/* 
         	2.调用setState方法的时候,会开启更新
         */}
                <button onClick= {()=>{
                    this.setState({
                        myname:"xiaoming"
                    })
                }}>click</button>
{/* 6.setState之后 --> 会进行更新 --> 虚拟DOM创建 --> Diif算法比较,
	把对比的补丁更新到页面中,这个过程是异步的很慢,每次调用setState都会重新走一遍这个过程,
	这样会导致浏览器会很累,组件性能不好 
*/}
            </div>
        )
    }
}

有父子关系的情况:

import React, { Component } from 'react'

class Child extends Component{
    componentDidMount() { // 只会走一次
        {/* this.props.myname是老的属性 */}
        console.log('Ajax请求数据', this.props.myname)
    }
    
    {/* nextProps -- 根据新的数据获取新的属性 */}
    componentWillReceiveProps(nextProps) { // 会走多次
        {/* this.props.myname是老的属性 */}
        {/* nextProps.myname是新的属性 */}
        console.log('Ajax请求数据', nextProps.myname)
    }
	{/*
		componentWillReceiveProps这个生命周期也有问题,加上UNSAFE_
		--> UNSAFE_componentWillReceiveProps
	*/}
    
    render(){
        return <div>
            {/* 这样子组件就只需要做页面渲染 */}
            child组件-{this.props.myname}
        </div>
    }
}

export default class App extends Component {
    state= {
        myname:"4567"
    }
    render() {
        return (
            <div>
                {this.state.myname}
                
                <button onClick={()=>{
                    this.setState({
                        myname:"4321"
                    })
                }}>click</button>
                
                <Child myname={this.state.myname}></Child>
            </div>
        )
    }
}

3.销毁阶段

componentWillUnmount:
在删除组件之前进行清理操作,比如:计时器和事件监听器
import React, { Component } from 'react'

class Navbar extends Component{
    render(){
        return <div style={{background:"red"}}>
            navbar-<button onClick={this.handleClick}>click</button>
        </div>
    }

    handleClick = ()=>{
        console.log(this.props.onKerwinEvent)
        this.props.onKerwinEvent()
    }
}

class Sidebar extends Component{
    render(){
        return <div style={{background:"yellow"}}>
            Sidebar
            <ul>
                <li>11111</li>
                <li>222222</li>
                <li>33333</li>
            </ul>
        </div>
    }

    componentWillUnmount(){
        // 卸载生命周期 --> 清除定时器、scroll为空
    }
}

export default class App extends Component {
    state = {
        isShow:true
    }
    render() {
        return (
            <div>
                App
                <Navbar onKerwinEvent={()=>{
                    console.log("App 组件的回调函数")
                    this.setState({
                        isShow:!this.state.isShow
                    })
                }}/>
                {/* <button onClick={()=>{
                    this.setState({
                        isShow:!this.state.isShow
                    })
                }}>click</button> */}
                {
                    this.state.isShow?
                    <Sidebar/>
                    :null
                }
            </div>
        )
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/4571.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!