react 学习

180 阅读4分钟

JSX 语法

<div></div>

使用规则

  • 只能返回一个根元素
<>
    内容
</>
<React.Fragment>
    内容
</React.Fragment>
  • 标签必须闭合
  • 使用驼峰式命名法给

组件分类

类组件

import React from 'react'

class Comp1 extends React.Component {
  render() {
    return <div>类组件  Comp1</div>
  }
}


export default Comp1

生命周期

含义: 一个组件从被创建到销毁的整个过程叫做生命周期,生命周期其实就是在特定的时候执行的钩子函数。

import React from 'react'

class Comp1 extends React.Component {
  // 方法
  addCount() {
    console.log('addCound');
    // console.log(this)
    // 类组件修改 state 唯一方式
    this.setState({
      count: this.state.count + 1
    })
  }
  // 内部状态
  state = {
    message: '你好, 生命周期',
    count: 1
  }
  // 挂载
  constructor(props) {
    // 必须先调用supper
    super(props)
    // 1. 初始化数据(不建议, 太麻烦)
    // 2. 绑定this指向
    console.log('1. constructor 生命周期执行')
    console.log(document.querySelector('.oo'))
  } 
  render() {
    console.log('2. render 生命周期执行')
    console.log(document.querySelector('.oo'))
    return <div className='oo'>
      <div>类组件  Comp1----{this.state.message}</div>
      <h2>{this.state.count}</h2>
      <button onClick={() => this.addCount()}>+1</button>
    </div>
  }
  componentDidMount() {
    // 页面第一次渲染完毕执行, 真实dom已经渲染完毕, 可以操作dom
    // 发起请求
    console.log('3. componentDidMount 生命周期执行')
    console.log(document.querySelector('.oo'));
    console.log(this)
  }
  // 更新
  shouldComponentUpdate() {
    console.log('1. shouldComponentUpdate')
    // 一般用来做优化
    return false
  }

  componentDidUpdate() {
    // 数据更新完毕
    console.log('3. componentDidUpdate ')
  }

  // 销毁
  componentWillUnmount() {
    // 1. 取消副作用
  }
}


export default Comp1
销毁 componentWillUnmount

一般来说, 在这个生命周期取消副作用, 比如 取消定时器


import React from 'react'


// 定义类组件

class Comp1 extends React.Component {
  state = {
    timer: null
  }
  // 三个阶段

  // 挂载
  constructor(props) {
    // 必须调用父类的constructor
    super(props);

    // 初始化, 函数绑定this
  }
  render() {
    // 就负责渲染
    return <div>comp1</div>
  }
  componentDidMount() {
    // 第一次渲染完成执行
    // 可以进行副作用操作
    this.timer = setInterval(() => {
      console.log(new Date())
    }, 1000)
  }

  // 更新
  shouldComponentUpdate() {
    // state 内部状态
    // props 外部状态
    return true
  }
  // render
  componentDidUpdate() {
    // 更新完毕
  }
  // 销毁
  componentWillUnmount() {
    // 取消副作用
    clearInterval(this.timer)
  }

}

export default Comp1

函数组件

在react@16.8版本之前,函数只可以用来进行UI渲染, 无法进行逻辑交互等复杂业务。 但是在react@16.8之后, 出现了hooks, 可以通过hooks 实现等同于类组件相同的操作。

import React from 'react'


const Comp2 = () => {
  return (
    <div>
      函数组件 Comp2
    </div>  
  )
}

export default Comp2

hooks

useState 声明数据

const [state, setState] = useState(初始值);

setState(新值)
setState((上一次的值) => 新值)

useEffect 副作用函数

  • 首页渲染完毕, 执行一次
  • 第二个参数不存在, 任何数据发生改变都会执行一次。 存在依赖项, 当依赖参数发生改变,会执行一次
  • 返回卸载函数, 当组件被卸载的时候, 该函数执行
  useEffect(() => {
    // 首次渲染执行
    // 更新的时候也会执行, 但是必须依赖的参数发生改变
    return () => {
      // 组件卸载执行
    }
  }, [依赖参数])

useNavigate 编程式导航

const navigate = useNavigate();

navigate('/home') // 导航到 /home 路由
navigate(-1)      // 返回上一页

// 可选的第二个参数
navigate(路径, {
        replace?: boolean;  
        state?: any;  
        preventScrollReset?: boolean;  
        relative?: RelativeRoutingType;  
        unstable_viewTransition?: boolean;
})

类组件和函数的联系与区别??

  • 类组件有生命周期,函数组件没有
  • 类组件需要继承 Class,函数组件不需要
  • 类组件可以获取实例化的 this,并且基于 this 做各种操作,函数组件不行
  • 类组件内部可以定义并维护 state, 函数组件为无状态组件(可以通过hooks实现)

组件通信

父子通讯: 副组件在调用子组件的时候,传递自定义属性, 传递了三个自定义属性 title, image, desc

  <ListItem
      title={v.title}
      image={v.image}
      desc={v.desc}
  ></ListItem>

子组件通过 this.props 接收到传递过来的自定义属性, 结构赋值

  const { title, desc, image } = this.props

子父通信: 副组件传递自定义方法, 由子组件props接收调用即可

    // 父组件
  <Comp1 count={count}  addCount={this.addCount}></Comp1>
    // 子组件
  <button onClick={this.props.addCount}>+1</button>

context 通信

  • 创建context
const MyContext = React.createContext(初始值)
  • 提供 Provider
<MyContext.Provider value={共享的值}>
    <其他组件></其他组件>
</MyContext.Provider>
  • 消费 consumer
    // 1. 方式一 类组件
        class Index extends React.Components {
            static contentType = MyContext
            
            render() {
                this.context  // 共享的值
                
                return (<DIV></DIV>)
            }
        }
    // 2. 方式一 类组件
        class Index extends React.Components {
             render() {
                this.context  // 共享的值
                
                return (<DIV></DIV>)
            }
        }
        Index.contentType = MyContext
        
        
    // 3. 方式三  类组件|函数组件
     class Index extends React.Components {
           render() {
               return <MyContext.Consumer>
                   {
                       (共享的值) => {
                           
                       }
                   }
               </MyContext.Consumer>
           }
     }
        

事件

事件传播

  • react 从捕获到目标到冒泡

事件分类

  • 合成事件:与原生事件直接在元素上注册的方式不同的是,React的合成事件不会直接绑定到目标DOM节点上,用事件委托机制,以队列的方式,从触发事件的组件向父组件回溯,直到Root节点。因此,React组件上声明的事件最终绑定到了Root对象(React17之前是Document)上。在Root节点,用一个统一的监听器去监听,这个监听器上保存着目标节点与事件对象的映射。当组件挂载或卸载时,只需在这个统一的事件监听器上插入或删除对应对象;当事件发生时(即Root上的事件处理函数被执行),在映射里按照冒泡或捕获的路径去组件中收集真正的事件处理函数,然后,由这个统一的事件监听器对所收集的事件逐一执行。

合成事件与原生事件区别

  • 事件名称必须小驼峰
  • 事件驱动函数要写成引用形式 { 函数 } 或者 { () => 函数() }
  • 阻止行为不同