重生之我又来学React了Day01-- State,Props和LifeCycle

127 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

前言

我本人的技术栈是Vue,工作上也一直大部分使用的都是Vue,期间断断续续有学过React,但是也止步于学了很久不用就忘了的阶段,作为一个有强烈求知欲望的前端(啊呸...还不是因为生活所迫!)要如何能摆脱掉这种困境呢?在网上看到很多大佬的学习方法之后,痛定思痛,决定采用主要以思维导图的方式来记录,由浅入深得再次去学习React,这一系列文章就围绕着这份思维导图来讲解。

image.png

React 基础

React组件分为函数组件和类组件,在v16.8之前,函数组件也被称为无状态组件,类组件被称为状态组件,直到v16.8发布,React Hooks的出现,算是打破了这一局面,函数组件也可以拥有自己的state了(利用useState)

JSX

在React中,使用JSX语法来实现用户界面,JSX就是一种语法糖,在经过Babel转译之后,其实就是JavaScript的一些API的调用。可以在花括号里写 JavaScript表达式;

let name = 'Rose'
function getName() {
    return name;
}
const element = {name} // 获取变量
const element2 = {getName()} //获取函数返回值

image.png

State

通过state属性给组件设置自己的状态值,利用setState来进行合并修改,注意必须要通过setState来修改,不然视图不会更新。

export default class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 123
    };
  }

  render() {
    return (
      <>
        <h1>value:{this.state.value}</h1>
        <h1>value1:{this.state.value1}</h1>
        // 点击按钮之后value1为X,而value没有修改
        <button onClick={() => this.setState({ value1: "X" })}>button</button>
      </>
    );
  }
}

props

组件之间可以通过props传递数据,父组件向子组件传值,子组件通过props对象获取外部传递进来的数据

export default class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 123,
      pname: "Jack"
    };
  }

  render() {
    return (
      <>
        <h1>value:{this.state.value}</h1>
        <h1>value1:{this.state.value1}</h1>
        {/* 点击按钮之后value1为X,而value没有修改 */}
        <button onClick={() => this.setState({ value1: "X" })}>button</button>
        <Child pname={this.state.pname}>
            <span className="parent">我是父组件的DOM</span>
        </Child>
      </>
    );
  }
}

class Child extends React.Component {
    render() {
        return (
            <div>
             <div>我的父亲是:{this.props.pname}</div>
             <div>接受到的父组件DOM:{this.props.children}</div>
            </div>
        )
    }
}

image.png

生命周期

constructor

初始化state,对类组件的事件做一些处理,比如绑定this。

class Child2 extends React.Component {
    constructor() {
        super();
        this.state = {
          value: "hello",
          this.handleClick = this.handleClick.bind(this);
        };
    }
    handleClick() {
        this.setState({
            value: "goodbye"
        })
    }
    render() {
        return (
            <div>
                 <button onClick={this.handleClick}>按钮</button>
            </div>
        )
    }
}

getDerivedStateFromProps(nextProps,prevState)

getDerivedStateFromProps(nextProps,prevState)这个生命周期是一个静态方法,因此获取不到this。nextProps是父组件新传递的props,prevState为待合并的state。

只要组件更新就会执行,不管是props改变还是执行setState。这个方法虽然把props映射到了state上面,但是这个state在组件里面使用setState是无法修改的。

一般用于对props进行一些逻辑处理。

class Child extends React.Component {
  constructor() {
    super();
    this.state = {
      books: "",
      age: "20"
    };
  }
  static getDerivedStateFromProps(newProps) {
    console.log("getDerivedStateFromProps");
    const { pname } = newProps;
    switch (pname) {
      case "Jack":
        return { books: "数学" };
    }
  }

  ChangeProps = () => {
    console.log("ChangeProps");
    this.setState({
      books: "语文"
    });
  };

  ChangeAge = () => {
    this.setState({
      age: "18"
    });
  };

  render() {
    return (
      <div>
        <div>Jack给的书:{this.state.books}</div>
        <button onClick={this.ChangeProps}>修改books</button>
        <div>子组件age:{this.state.age}</div>
        <button onClick={this.ChangeAge}>修改age</button>
        <div>我的父亲是:{this.props.pname}</div>
        <div>接受到的父组件DOM:{this.props.children}</div>
      </div>
    );
  }
}

componentWillMount改为UNSAFE_componentWillMount

在v16.3中componentWillMount这个生命周期前面加上了UNSAFE_标识,根据源码得知,是由于render方法可以通过sholdUpdate来约束是否可以更新,但在render之前的生命周期却依然会被不必要的执行,所以官网不推荐再用这样的生命周期了。

componentWillReceiveProps改为UNSAFE_componentWillReceiveProps

只要父组件render函数执行,props被重新创建,子组件的componentWillReceiveProps方法就会被执行。

componentWillUpdate改为UNSAFE_componentWillUpdate

在这个生命周期中可以获取到组件在更新之前的状态,比如DOM。

render

获取到JSX创建的视图,一次 render 的过程,就是创建 React.element 元素的过程。 React.element就是React.creatElement()生成的对象。

getSnapshotBeforeUpdate,componentDidUpdate

该生命周期是为了获取更新前的快照,处于数据更新了但DOM还未更新的那个阶段。该生命周期主要与componentDidUpdate结合使用(如果使用getSnapshotBeforeUpdate,但不使用componentDidUpdate控制台会给出警告),该生命周期返回一个snapshot(快照),在componentDidUpdate中可通过第三个参数获取到该快照。

getSnapshotBeforeUpdate(prevProps,preState) {
    return {
        x:1
    }
}
componentDidUpdate(prevProps, prevState, snapshot) {
    console.log(snapshot) // {x:1}
}

⚠注意: 如果在componentDidUpdate中使用setState,可能会误操作导致无限更新,所以在该生命周期中更新state要小心操作。写好条件限制。

componentDidMount

componentDidUpdate 在组件更新的时候执行,而componentDidMount则在组件DOM挂载的时候执行,可以在该生命周期中向后台发起请求,以及做一些DOM事件绑定之类的操作。

更新相关生命周期:

shouldComponentUpdate

shouldComponentUpdate(newProps,newState){
    if (newProps.pname !== this.props.pname ) { 
    /* 渲染组件 */ 
          return true 
      } else if(newState.page !== this.props.page ){ 
      /* 渲染组件 */ 
          return true 
        } else { /* 否则组件不渲染 */ 
         return false 
       }
}

该生命周期在getDerivedStateFromProps之后在render之前执行,在getDerivedStateFromProps中props映射到的state将会合并到newState中,供shouldComponentUpdate使用。

组件销毁生命周期:

componentWillUnmount

看名字就可以得知该生命周期在组件销毁之前执行,可以在该生命周期中移除定时器,DOM的事件绑定等操作。

同样在函数组件中,现在也可以通过React Hooks实现函数组件的“生命周期”,在React Hooks的学习中再深究。

下一篇再继续学习React基础知识之Ref,context,css