React基础笔记(一)

299 阅读6分钟

箭头函数

下面很多时候都会出现 => 这样子的东西 这个不是大于等于 而是es6的一个语法糖箭头函数 它的用处很多 最大的用处就是关于this的绑定 这个慢慢体会就好 在此不做详细解释 下面可能会出现的几个箭头函数用法作说明:

//不带参数的箭头函数
const handleClick = () => {
  console.log(123);
}
<Button onClick={this.handleClick}>dianwo</Button>

// 带参数的箭头函数
const handleClick = (value) => () => {
  console.log(value)
}
<Button onClick={this.handleClick('hai')}>dianwo</Button>
上面的写法等效于

const handleClick = (value) => {
  console.log(value)
}
<Button onClick={() => this.handleClick('hai')}>dianwo</Button>

React类组件

类组件的模版

class DemoComponent extends React.Component {
  state = {
        
  }
  render() {
    return (
      <div>
        HelloWorld!!
      </div
    )
  }
}

state

state是类组件自己维护的状态属性 定义后不可通过访问对象的方式去更改 要通过setState函数更改 setState后页面的刷新不是同步的

例如

class DemoComponent extends React.Component {
  state = {
    name: '123',
  }
  render() {
    return (
      <div>
        {this.state.name}
      </div
    )
  }
}

这个例子会显示123这个名字 但如果我们想点击按钮更改state的name就需要 PS: 这里用到了es6的箭头函数

class DemoComponent extends React.Component {
  state = {
    name: '123',
  }
  handleNameChange = () => {
    this.setState({
      name: 'heiheihei',
    })
  }
  render() {
    return (
      <div>
        {this.state.name}
        <button onClick={this.handleNameChange}>changeName</button
      </div>
    )
  }
}

当点击按钮后123就会变成heiheihei

上面只是一个简单的例子去介绍类组件的state的用法 state的作用一般用于:

  1. 某个组件或者页面他需要独立去维护某种状态或者数据的时候
  2. 接受props的数据但需要在该组件内去更改这个props的值(仅仅是在该组件内,对父组件无影响)

props

当编写好一个类组件后 通常需要配合其他组件的使用组合成一个页面 比如我写了一个简单的计算器组件CalComponent PS: React.PureComponenet和React.Compoenent区别

// CalComponent.jsx
import React from 'react';
import { Input, Button } from 'antd';
import PropTypes from 'prop-types';

class CalComponent extends React.PureComponent {
  static propTypes = {
    type: PropTypes.string.isRequired
    title: PropTypes.string,
  }
  static defaultProps = {
    title: '默认',
  }
  state = {
    value1: '',
    value2: '',
    result: null,
  }
  
  handleInputChange = (keyName) => ({ target }) => {
    this.setState({
      [keyName]: target.value,
    })
  }
  
  handleCalcClick = () => {
    let result;
    const { type } = this.props;
    if(type === 'add') {
      result = this.state.value1 + this.state.value2;
    } else if ( type === 'multipy') {
      result = this.state.value1 * this.state.value2;
    } else if ( type === 'divide') {
      result = this.state.value1 / this.state.value2;
    } else if ( type === 'minus') {
      result = this.state.value1 - this.state.value2;
    }
    this.setState({
      value1: '',
      value2: '',
      result,
    })
  }
  
  render() {
    return (
      <div>
        {this.props.title}
        <Input 
          value={this.state.value1} 
          onChange={this.handleInputChange('value1')}
        />
        <Input 
          value={this.state.value2} 
          onChange={this.handleInputChange('value2')}
        />
        <Button onClick={this.handleCalcClick}>计算</Button>
        {this.result && <div>
          结果:{this.state.result}
        </div>}
      </div>
    )
  }
}

export default CalComponent;
// IndexView.jsx
import React from 'react';
import CalComponent from './CalComponent.jsx';

class IndexView extends React.PureComponenet {
  state = {
    type: null,
  }
  handleTypeChange = (value) => {
    this.setState({
      type: value,
    })
  }
  render() {
    return (
      <div>
        <Button 
          onClick={() => this.handleTypeChange()} 
        >加法</Button>
        <Button 
          onClick={() => this.handleTypeChange()} 
        >减法</Button>
        <Button 
         onClick={() => this.handleTypeChange()} 
        >乘法</Button>
        <Button 
         onClick={() => this.handleTypeChange()} 
        >除法</Button>
        {this.state.type && <CalComponent type={this.state.type} />}
      </div>
    )
  }
}

生命周期 (参考自官网)

创建组件的时候会经历一系列的生命周期,生命周期就是一个组件从有到无再到无的过程。
周期顺序一般为 挂载——更新——卸载

挂载

当组件实例被创建并插入DOM时,生命周期会如以下顺序调用:

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()

更新

当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

卸载

当组件从DOM中移除时会调用如下方法:

  • componentWillUnmount()

错误处理

当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:

  • static getDerivedStateFromError()
  • componentDidCatch()

具体说明

constructor()

避免将 props 的值复制给 state!

constructor(props) {
    super(props);
    this.state = {
        counter: 0
    };
    this.handleClick = this.handleClick.bind(this);
}

componentDidMount()

componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用
依赖于 DOM 节点的初始化应该放在这里。
如需通过网络请求获取数据,此处是实例化请求的好地方。 这里面也可以添加订阅,但要在 componentWillUnmount() 里取消订阅 这里面也可以调用 setState() 方法,会进行额外的渲染,发生在浏览器更新屏幕前。
在里面过多使用 setState 会造成性能问题

componentDidUpdate()

componentDidUpdate() 会在更新后会被立即调用 首次渲染不会执行此方法
当组件更新后,可以在此处对 DOM 进行操作。如果你对更新前后的 props 进行了比较,也可以选择在此处进行网络请求。(例如,当 props 未发生变化时,则不会执行网络请求)。

componentDidUpdate(prevProps) {
  // 典型用法(不要忘记比较 props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

componentWillUnmount()

componentWillUnmount() 会在组件卸载及销毁之前直接调用
在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。 组件实例卸载后,将永远不会再挂载它。

static getDerivedFromStateToProps(state, props)

getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用
它应返回一个对象来更新 state,如果返回 null 则不更新任何内容每次渲染前触发此方法</b

函数组件

函数组件就是用Function的方式去构建所有的组件,万物皆Func 注意:!!函数组件又称为无状态组件,与之对应的是有状态组件(类组件) 顾名思义,无状态就是说他没有state去独立的管理这个组件的内部状态,只有靠外部的props去传递参数改变他的状态。 例子:

const AddComponent = (props) => {
  const { a, b } = props;
  return <div>{ a + b }<div>
}

*通过HOOKS实现有状态的函数式写法

import { useState, useEffect } from 'react';
import { Button } form 'antd';
const CalcComponent = (props) => {
  useEffect(() => { // 用来代替生命周期
    // componentDidMount,componentDidUpdate 和 componentWillUnmount的组合
  }, []) // 第二个参数为触发条件
  const [type, setType] = useState(null);
 
  const handleTypeChange = (mode) => {
    setType(mode);
  }
  return <div>
    {type}
    <Button onClick={() => handleTypeChange('状态1')}>改变状态1</Button>
    <Button onClick={() => handleTypeChange('状态2')}>改变状态1</Button>
    <Button onClick={() => handleTypeChange('状态3')}>改变状态1</Button>
  </div>
}

父子组件通讯

众所周知 在React里数据流是单向的,从上至下传递,子组件获取到父组件的值后,并不能通过对象或者属性方法直接修改父组件的值,也就是说,子组件干了什么父组件是不知道的,那子组件如何告知父组件自己干了什么,这时候就需要父组件去定义一个函数然后当作props传递给子组件 子组件通过这个函数去修改父组件的属性 例子:

// 父组件
Class FatherComponent extends React.PureComponent {
  state = {
    status: false,
  }
  handleStatusChange = () => {
    this.setState({
      status: !this.state.status,
    })
  }
  render() {
   return(
     <SonComponent 
       onStatusChange={this.handleStatusChange}
       status={this.state.status}
     />
   )   
  }
}

//子组件
Class SonComponent extends React.PureComponent {
  static propTypes = {
    status: PropTypes.boolean.isRequired,
    onStatusChange: PropTypes.func.isRequired,
  }

  render() {
   return(
     <div>
       {this.props.status ? '真' : '假'}
      <Button onClick={this.props.onStatusChange}>我要改变父组件!!!</Button>
     </div>
    
   )   
  }
}