react-组件生命周期

1.react的生命周期

  • 生命周期图
    在这里插入图片描述

1.1react的生命周期-类式组件

1.1.1生命周期基本使用

import React, {
    
     Component } from 'react';
import ReactDOM from 'react-dom';

export default class Optimize extends Component {
    
    
  constructor(props) {
    
    
    super(props);
    console.log('constructor');
    this.state = {
    
    
      msg: '这里是生命周期组件'
    }
  }
  changeMsg = () => {
    
    
    this.setState({
    
    
      msg: '修改msg的数据'
    })
  }
  strongUpdate = () => {
    
    
    this.forceUpdate()
  }
  unmountCom = () => {
    
    
    ReactDOM.unmountComponentAtNode(document.querySelector('#root'))
  }
  /**
   * 此方法运用于一个罕见的用例:state在任何情况下都取决于props,无论是初始化还是修改,都不起作用
   * 
   * 返回值:状态对象/null
   * 默认返回:null
   * 
   * 注意点:派生状态会导致代码冗余,并使组件难以维护,了解即可
   */
  static getDerivedStateFromProps(props, state) {
    
    
    console.log('getDerivedStateFromProps-获取派生状态从props中', props, state);
    // return props; //props对象中的key存在和state中的key相等的情况下,就会替换掉state中相等key所对应的value,那么任何修改这个value的方法都将失效
    return null;
  }
  /**
   * 组件是否应该被更新:控制组件是否更新的阀门
   * 
   * 返回值:true/false
   * 默认返回:true
   * 如果返回false,终止更新,停止之后的所有生命周期包括render
   */
  shouldComponentUpdate(props, state) {
    
    
    console.log('shouldComponentUpdate-是否应该更新组件', props, state);
    return true;
  }
  render() {
    
    
    console.log('组件初始化/更新完毕', 'render');
    return (
      <div>
        <h2>组件生命周期</h2>
        <p>{
    
    this.state.msg}</p>
        <button onClick={
    
    this.changeMsg}>更新msg</button>
        <button onClick={
    
    this.strongUpdate}>强制更新</button>
        <button onClick={
    
    this.unmountCom}>卸载组件</button>
      </div>
    )
  }
  /**
   * 在组件更新之前获取快照
   * getSnapshotBeforeUpdate在最近一次渲染输出(提交到DOM)节点之前调用,他使得组件能在发生之前从DOM中捕获一些信息(例如滚动位置)。此生命周期的任何返回值将作为参数传递给componentDidUpdate
   * 
   * 返回值:快照值(字符串/布尔/数字/数组/对象...任何值都可以作为快照值)或者null
   * 默认返回:null
   */
  getSnapshotBeforeUpdate(prevProps, prevState) {
    
    
    console.log('getSnapshotBeforeUpdate-获取快照在更新之前', prevProps, prevState);
    return {
    
    
      name: '李四',
      age: 16
    }
  }
  componentDidMount() {
    
    //这里面没有能接受的参数
    console.log('组件挂载完毕', 'componentDidMount');
  }
  componentDidUpdate(prevProps, prevState, snapshotValue) {
    
    
    console.log('componentDidUpdate-组件更新完毕', prevProps, prevState, snapshotValue);
  }
  componentWillUnmount() {
    
    //这里面没有能接受的参数
    console.log('componentWillUnmount------组件将要被卸载');
  }
}

1.1.2生命周期-初始化

import React, {
    
     Component } from 'react';

export default class Optimize extends Component {
    
    
  constructor(props) {
    
    
    super(props);
    console.log('constructor');
    this.state = {
    
    
      msg: '这里是生命周期组件'
    }
  }
  /**
   * 此方法运用于一个罕见的用例:state在任何情况下都取决于props,无论是初始化还是修改,都不起作用
   * 
   * 返回值:状态对象/null
   * 默认返回:null
   * 
   * 注意点:派生状态会导致代码冗余,并使组件难以维护,了解即可
   */
  static getDerivedStateFromProps(props, state) {
    
    
    console.log('getDerivedStateFromProps-获取派生状态从props中', props, state);
    // return props; //props对象中的key存在和state中的key相等的情况下,就会替换掉state中相等key所对应的value,那么任何修改这个value的方法都将失效
    return null;
  }
  render() {
    
    
    console.log('组件初始化/更新完毕', 'render');
    return (
      <div>
        <h2>组件生命周期</h2>
        <p>{
    
    this.state.msg}</p>
      </div>
    )
  }
  componentDidMount() {
    
    //这里面没有能接受的参数
    console.log('组件挂载完毕', 'componentDidMount');
  }
}

1.1.3生命周期-更新

1.1.3.1生命周期-更新-正常更新
import React, {
    
     Component } from 'react';

export default class Optimize extends Component {
    
    
  state={
    
    
  	 msg: '这里是生命周期组件'
  }
  changeMsg = () => {
    
    
    this.setState({
    
    
      msg: '修改msg的数据'
    })
  }
  /**
   * 此方法运用于一个罕见的用例:state在任何情况下都取决于props,无论是初始化还是修改,都不起作用
   * 
   * 返回值:状态对象/null
   * 默认返回:null
   * 
   * 注意点:派生状态会导致代码冗余,并使组件难以维护,了解即可
   */
  static getDerivedStateFromProps(props, state) {
    
    
    console.log('getDerivedStateFromProps-获取派生状态从props中', props, state);
    // return props; //props对象中的key存在和state中的key相等的情况下,就会替换掉state中相等key所对应的value,那么任何修改这个value的方法都将失效
    return null;
  }
  /**
   * 组件是否应该被更新:控制组件是否更新的阀门
   * 
   * 返回值:true/false
   * 默认返回:true
   * 如果返回false,终止更新,停止之后的所有生命周期包括render
   */
  shouldComponentUpdate(props, state) {
    
    
    console.log('shouldComponentUpdate-是否应该更新组件', props, state);
    return true;
  }
  render() {
    
    
    console.log('组件初始化/更新完毕', 'render');
    return (
      <div>
        <h2>组件生命周期</h2>
        <p>{
    
    this.state.msg}</p>
        <button onClick={
    
    this.changeMsg}>更新msg</button>
      </div>
    )
  }
  /**
   * 在组件更新之前获取快照
   * getSnapshotBeforeUpdate在最近一次渲染输出(提交到DOM)节点之前调用,他使得组件能在发生之前从DOM中捕获一些信息(例如滚动位置)。此生命周期的任何返回值将作为参数传递给componentDidUpdate
   * 
   * 返回值:快照值(字符串/布尔/数字/数组/对象...任何值都可以作为快照值)或者null
   * 默认返回:null
   */
  getSnapshotBeforeUpdate(prevProps, prevState) {
    
    
    console.log('getSnapshotBeforeUpdate-获取快照在更新之前', prevProps, prevState);
    return {
    
    
      name: '李四',
      age: 16
    }
  }
  componentDidUpdate(prevProps, prevState, snapshotValue) {
    
    
    console.log('componentDidUpdate-组件更新完毕', prevProps, prevState, snapshotValue);
  }
}
1.1.3.1生命周期-更新-强制更新
import React, {
    
     Component } from 'react';

export default class Optimize extends Component {
    
    
  strongUpdate = () => {
    
    
    this.forceUpdate()
  }
  /**
   * 此方法运用于一个罕见的用例:state在任何情况下都取决于props,无论是初始化还是修改,都不起作用
   * 
   * 返回值:状态对象/null
   * 默认返回:null
   * 
   * 注意点:派生状态会导致代码冗余,并使组件难以维护,了解即可
   */
  static getDerivedStateFromProps(props, state) {
    
    
    console.log('getDerivedStateFromProps-获取派生状态从props中', props, state);
    // return props; //props对象中的key存在和state中的key相等的情况下,就会替换掉state中相等key所对应的value,那么任何修改这个value的方法都将失效
    return null;
  }
  render() {
    
    
    console.log('组件初始化/更新完毕', 'render');
    return (
      <div>
        <h2>组件生命周期</h2>
        <button onClick={
    
    this.strongUpdate}>强制更新</button>
      </div>
    )
  }
  /**
   * 在组件更新之前获取快照
   * getSnapshotBeforeUpdate在最近一次渲染输出(提交到DOM)节点之前调用,他使得组件能在发生之前从DOM中捕获一些信息(例如滚动位置)。此生命周期的任何返回值将作为参数传递给componentDidUpdate
   * 
   * 返回值:快照值(字符串/布尔/数字/数组/对象...任何值都可以作为快照值)或者null
   * 默认返回:null
   */
  getSnapshotBeforeUpdate(prevProps, prevState) {
    
    
    console.log('getSnapshotBeforeUpdate-获取快照在更新之前', prevProps, prevState);
    return {
    
    
      name: '李四',
      age: 16
    }
  }
  componentDidUpdate(prevProps, prevState, snapshotValue) {
    
    
    console.log('componentDidUpdate-组件更新完毕', prevProps, prevState, snapshotValue);
  }
}

1.1.4生命周期-卸载

import React, {
    
     Component } from 'react';
import ReactDOM from 'react-dom';

export default class Optimize extends Component {
    
    
  unmountCom = () => {
    
    
    ReactDOM.unmountComponentAtNode(document.querySelector('#root'))
  }
  render() {
    
    //卸载的时候不调用
    console.log('组件初始化/更新完毕', 'render');
    return (
      <div>
        <h2>组件生命周期</h2>
        <button onClick={
    
    this.unmountCom}>卸载组件</button>
      </div>
    )
  }
  componentWillUnmount() {
    
    //这里面没有能接受的参数
    console.log('componentWillUnmount------组件将要被卸载');
  }
}

1.1.4getSnapshotBeforeUpdate/componentDidUpdate使用实例

import React, {
    
     Component } from 'react';
import ReactDOM from 'react-dom';

export default class Optimize extends Component {
    
    
  constructor(props) {
    
    
    super(props);
    console.log('constructor');
    this.state = {
    
    
      msg: '这里是生命周期组件',
      arr: []
    }
  }
  addArrDate = () => {
    
    
    let {
    
     arr } = this.state;
    arr.push({
    
    
      id: arr.length + 1,
      name: 'name' + (arr.length + 1)
    });
    this.setState({
    
    
      arr
    })
  }
  unmountCom = () => {
    
    
    ReactDOM.unmountComponentAtNode(document.querySelector('#root'))
  }
  render() {
    
    
    console.log('组件初始化/更新完毕', 'render');
    return (
      <div>
        <h2>组件生命周期</h2>
        <div ref={
    
    (currentNode) => {
    
    
          this.fatherWrapDOM = currentNode;
        }} className="father-wrap">
          {
    
    
            this.state.arr.map(item => {
    
    
              return (
                <div key={
    
    item.id} className="son-inner">
                  {
    
    item.name}
                </div>
              )
            })
          }
        </div>
        <button onClick={
    
    this.unmountCom}>卸载组件</button>
      </div>
    )
  }
  /**
   * 在组件更新之前获取快照
   * getSnapshotBeforeUpdate在最近一次渲染输出(提交到DOM)节点之前调用,他使得组件能在发生之前从DOM中捕获一些信息(例如滚动位置)。此生命周期的任何返回值将作为参数传递给componentDidUpdate
   * 
   * 返回值:快照值(字符串/布尔/数字/数组/对象...任何值都可以作为快照值)或者null
   * 默认返回:null
   */
  getSnapshotBeforeUpdate(prevProps, prevState) {
    
    
    console.log('getSnapshotBeforeUpdate-获取快照在更新之前', prevProps, prevState);
    // 获取DOM更新之前fatherWrapDOM的实际高度
    let beforeUpdateWrapHeight = this.fatherWrapDOM.scrollHeight;
    return {
    
    
      beforeUpdateWrapHeight: beforeUpdateWrapHeight
    }
  }
  componentDidMount() {
    
    //这里面没有能接受的参数
    console.log('组件挂载完毕', 'componentDidMount');
    this.timer = setInterval(() => {
    
    
      this.addArrDate()
    }, 1000);
  }
  componentDidUpdate(prevProps, prevState, snapshotValue) {
    
    
    console.log('componentDidUpdate-组件更新完毕', prevProps, prevState, snapshotValue);
    let {
    
     beforeUpdateWrapHeight } = snapshotValue;
    // 获取DOM更新之后fatherWrapDOM的实际高度
    let nowWrapHeight = this.fatherWrapDOM.scrollHeight;
    this.fatherWrapDOM.scrollTop += nowWrapHeight - beforeUpdateWrapHeight;
  }
  componentWillUnmount() {
    
    //这里面没有能接受的参数
    console.log('componentWillUnmount------组件将要被卸载');
    //清除定时器
    clearInterval(this.timer)
  }
}

1.2react的生命周期-函数式组件

  • effect Hook可以让你在函数中执行副作用操作(用于模拟组件中的生命周期钩子)
  • React中的副作用操作
    • 发送Ajax请求
    • 设置订阅/启动定时器
    • 手动更改真实DOM
  • 语法和说明
    React.useEffect(()=>{
          
          
    	//在此可以执行任何副作用的操作==》生命周期钩子
    	return ()=>{
          
          //在函数组件卸载前执行
    		//在此做一些首尾性的操作==》清除定时器/取消订阅等
    	}
    },[stateValue])//如果指定的是空数组,那么只会在第一次render之后执行
    
  • 可以把React.useEffect看成以下三个函数的组合
    • componentDidMount==》stateValue[]
    • componentDidUpdate==》数组为[‘需要监听的变量名称’]或者不写
    • componentWillUnmount==》return()=>{}

1.2.1React.useEffect(()=>{})

  • 如果不传React.useEffect的第二个参数,就代表着要监听所有的React.useState的状态,也就相当于类式组件中的componentDidUpdate
  • 注意点:这样写是十分危险的,如果在回调函数中不断更新数据,数据一更新,就要重新调用这个回到函数和更新界面,就会导致界面卡死的情况
import React, {
    
     Component } from 'react';

export default function Optimize() {
    
    
  const [count, changeCount] = React.useState(1)
  function handleAddCount() {
    
    
    changeCount((count) => {
    
    
      return count + 1
    })
  }
  //如果不传入第二个参数,就默认监听所有的React.useState(),当在回调函数中开启定时器的时候,数据就会更新,数据更新又会导致新一轮的调用 React.useEffect,周而复始,很快界面就卡死掉了
  React.useEffect(() => {
    
    
    console.log('React.useReducer调用了');
    // 注意点在定时器中调用修改状态值的方法的时候,最好使用回调函数的方式设置值
    setInterval(() => {
    
    
      // changeCount(count+1)//这种非回调的函数写法就有问题,count加不上去
      handleAddCount();
    }, 1000);
  })
  return (
    <div>
      <h2>函数式组件生命周期</h2>
      <p>{
    
    count}</p>
    </div>
  )
}

1.2.2React.useEffect(()=>{},[])

  • 空对象就是什么React.useState的状态都不监听,这个也就相当于类式组件中的componentDidMount
import React, {
    
     Component } from 'react';

export default function Optimize() {
    
    
  const [count, changeCount] = React.useState(1)
  function handleAddCount() {
    
    
    changeCount((count) => {
    
    
      return count + 1
    })
  }
  React.useEffect(() => {
    
    
    console.log('React.useReducer调用了');
    // 注意点在定时器中调用修改状态值的方法的时候,最好使用回调函数的方式设置值
    setInterval(() => {
    
    
      // changeCount(count+1)//这种非回调的函数写法就有问题,count加不上去
      handleAddCount();
    }, 1000);
  }, [])
  return (
    <div>
      <h2>函数式组件生命周期</h2>
      <p>{
    
    count}</p>
    </div>
  )
}

1.2.3React.useEffect(()=>{},['React.useState()的值','React.useState()的值',...])

  • 只会监听数组中的React.useState()的值,这个也就相当于类式组件中的componentDidUpdate
import React, {
    
     Component } from 'react';

export default function Optimize() {
    
    
  const [msg, changeMsg] = React.useState('初始msg')
  const [count, changeCount] = React.useState(1)
  function handleChangeMsg() {
    
    
    changeMsg('修改msg')
  }
  function handleAddCount() {
    
    
    changeCount((count) => {
    
    
      return count + 1
    })
  }
  React.useEffect(() => {
    
    
    console.log('React.useReducer调用了');
    // 注意点在定时器中调用修改状态值的方法的时候,最好使用回调函数的方式设置值
    setInterval(() => {
    
    
      // changeCount(count+1)//这种非回调的函数写法就有问题,count加不上去
      handleAddCount();
    }, 1000);
  }, [msg])
  return (
    <div>
      <h2>函数式组件生命周期</h2>
      <p>{
    
    msg}</p>
      <p>{
    
    count}</p>
      <button onClick={
    
    handleChangeMsg}>改变msg</button>
    </div>
  )
}

1.2.4React.useEffect(()=>{return ()=>{}})

  • 如果在React.useEffect的回调函数中返回了一个回调函数,那么这个回调函数中的内容就会在组件将要卸载的时候触发也就相当于类式组件中的componentWillUnmount
import React, {
    
     Component } from 'react';
import ReactDOM from 'react-dom';

export default function Optimize() {
    
    

  const [msg, changeMsg] = React.useState('初始msg')
  const [count, changeCount] = React.useState(1)
  function handleChangeMsg() {
    
    
    changeMsg('修改msg')
  }
  function handleAddCount() {
    
    
    changeCount((count) => {
    
    
      return count + 1
    })
  }
  function unmount() {
    
    
    ReactDOM.unmountComponentAtNode(document.querySelector('#root'));
  }
  React.useEffect(() => {
    
    
    console.log('React.useReducer调用了');
    // 注意点在定时器中调用修改状态值的方法的时候,最好使用回调函数的方式设置值
    let timer = setInterval(() => {
    
    
      // changeCount(count+1)//这种非回调的函数写法就有问题,count加不上去
      handleAddCount();
    }, 1000);
    return ()=>{
    
    
      console.log('组件将要卸载');
      clearInterval(timer);
    }
  }, [msg])
  return (
    <div>
      <h2>函数式组件生命周期</h2>
      <p>{
    
    msg}</p>
      <p>{
    
    count}</p>
      <button onClick={
    
    handleChangeMsg}>改变msg</button>
      <button onClick={
    
    unmount}>卸载组件</button>
    </div>
  )
}

猜你喜欢

转载自blog.csdn.net/big_sun_962464/article/details/113385545