React

一、React

React 是一个由 Facebook 开发的开源 JavaScript 库,用于构建用户界面,特别是单页面应用(SPA)。它通过组件化的方式构建 UI,组件可以是状态驱动的、可重用的,并且可以与其他组件进行组合。

二、组件

在 React 中,组件 是构建用户界面的基础,它代表了页面的一个部分,负责展示内容以及处理交互。你可以把它看作一个“自定义标签”,它可以用来封装页面的一部分内容,并且具有自己的逻辑和状态。

你可以把组件理解为:页面上的一块“模块”或“区域”。

它可以是一个按钮、一个输入框、一个列表,甚至一个复杂的界面结构。

1、组件和 HTML 的区别

在传统的 HTML 中,我们直接写 <div>、<h1>、<p> 等标签来定义页面结构,但在 React 中,我们通过组件来构建 UI(User Interface,即用户界面)

传统 HTML:

<div>
    <h1>Hello, World!</h1>
    <p>This is a paragraph.</p>
</div>

React 组件:

function MyComponent() {
    return (
        <div>
            <h1>Hello, World!</h1>
            <p>This is a paragraph.</p>
        </div>
    );
}

在 React 中,我们通过一个 MyComponent 组件来封装这段 UI。MyComponent 返回的是一段 JSX 代码(类似 HTML),React 会根据它生成实际的 HTML

其中 JSX(JavaScript XML)是 JavaScript 的一种语法扩展,它让你可以在 JavaScript 代码中直接写类似 HTML 的标签。React 使用 JSX 来定义组件的结构,提供了一种简洁的方式来描述 UI。

也就是说,JSX 看起来像是 HTML,但它实际上是 JavaScript 对象。它允许你在 JavaScript 代码中直接书写结构化的界面,而 React 会将这些结构化的内容转化为真正的 DOM 元素。

2、组件的类型

React 主要有两种类型的组件:函数组件 和 类组件。

2.1、函数组件

最简单的组件形式,它就是一个 JavaScript 函数,返回 UI 代码。

function Greeting(props) {
    return <h1>Hello, {props.name}!</h1>;
}

Greeting 是一个函数组件,它接受一个 props 对象,并返回一个 <h1> 元素,显示传入的名字。

props 是从父组件传递给子组件的数据。

2.2、类组件

类组件是通过 JavaScript 类定义的组件,通常包含一些方法和生命周期逻辑,适用于需要管理状态或副作用的场景。

class Greeting extends React.Component {
    render() {
        return <h1>Hello, {this.props.name}!</h1>;
    }
}

类组件会继承 React.Component 类,包含一个 render() 方法,返回要渲染的内容。

在这个例子中,props.name 是从父组件传递的数据。

3、组件的“状态”

React 组件的一个重要概念是 状态(State)。状态 是指组件内部的数据,通常会影响组件的显示内容。

这里澄清一下 props 和 state 的区别:

props(属性):

定义:props 是组件的 输入,是父组件传递给子组件的数据。它们是不可修改的,子组件只能读取 props 中的值。

方向:props 是 单向流动 的,从父组件流向子组件。

用途:用于传递数据和事件处理函数,让子组件可以使用或处理父组件传递的数据。

不可修改:子组件不能直接修改它接收到的 props,它只能基于这些 props 渲染视图。

state(状态):

定义:state 是组件的 内部状态,用于存储组件内部需要跟踪和控制的数据。它是可变的,可以在组件内部更新。

方向:state 是 局部的,它只存在于组件内部,可以通过 setState 更新。

用途:用于保存和管理组件内部的可变数据(如用户输入、计数器的值等)。

可修改:子组件可以通过调用 setState 来修改自己的 state,并且 React 会根据新的 state 更新组件的 UI。

我将以下面这段代码作为示例来展示一下用法

function Counter() {
    const [count, setCount] = React.useState(0); // 组件的状态:计数器

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

Counter 是一个 React 函数组件。

const [count, setCount] = React.useState(0);

这行代码定义了一个名为 count 的状态变量,初始值为 0,并且定义了一个函数 setCount 来更新这个状态。

这里涉及到了 const 的一个语法形式:数组解构

React.useState(0) 是 React 的 useState Hook,它返回一个包含两个元素的数组:

count:当前的状态值(这里是计数器的值,初始值为 0)。

setCount:一个函数,用来更新 count 的值。每当调用 setCount 时,React 会重新渲染组件并更新界面上
的 count。

组件的返回部分是一个 JSX 结构:<p>Count: {count}</p>:显示当前 count 的值。当 count 更新时,组件会重新渲染,显示最新的计数值。

<button onClick={() => setCount(count + 1)}>Increment</button>:

这是一个按钮,当点击时会调用一个箭头函数 () => setCount(count + 1),该函数会将 count 的值增加 1,并通过 setCount 更新状态。setCount(count + 1) 触发组件重新渲染,更新显示的计数值。

这里是关于 Hook 的补充

一、什么是 Hook

Hook 是 React 提供的工具函数,名字都以 use 开头

它们解决了函数组件中无法使用状态(state)和生命周期的局限性

核心 Hook 包括:

useState:用来管理组件的状态

useEffect:用来管理副作用(如数据请求、订阅等)

useContext:用来使用上下文(context)

React 还提供了许多其他的 Hook,比如 useRef、useReducer 等

二、为什么叫 Hook

React 团队将它称为 “Hook”(钩子),因为它可以“钩住”函数组件,让它们拥有状态和生命周期的能力

想象一下,传统的函数组件就像是一个简单的工具函数,而 Hook 就是额外为它装上的“模块”,赋予它更多功能

三、以 useState 为例:用 Hook 管理状态

a. 什么是状态?

状态(state)是组件的数据,数据会随着用户的交互(比如点击按钮)而改变。状态变化后,React 会自动重新渲染组件。

b. useState 是什么?

useState 是 React 提供的一个 Hook,用来为函数组件添加状态。

它返回一个数组,包含两个元素:当前状态的值和改变状态的函数。

c. useState 的用法:
import React, { useState } from 'react';

function Counter() {
    const [count, setCount] = useState(0); // 初始化状态为 0

    return (
        <div>
            <p>当前计数:{count}</p>
            <button onClick={() => setCount(count + 1)}>增加计数</button>
        </div>
    );
}

调用 useState(0) 时,定义了一个状态变量 count,并赋初始值为 0。

setCount 是一个函数,用于更新状态。当你调用 setCount(count + 1) 时,React 会更新 count 的值,并重新渲染组件。

每次状态更新,组件的 return 部分会重新执行,更新页面显示。

四、以 useEffect 为例:用 Hook 管理副作用

a. 什么是副作用?

副作用是指那些不直接产生 UI 的操作,比如:

数据获取(AJAX 请求)。

订阅事件(如 WebSocket)。

操作浏览器的 DOM。

设置定时器等。

b. useEffect 是什么?

useEffect 是一个 Hook,帮助你管理副作用。

它相当于类组件中的生命周期方法(如 componentDidMount、componentDidUpdate 和 componentWillUnmount 的结合)。

c. useEffect 的用法:
import React, { useState, useEffect } from 'react';

function Timer() {
    const [count, setCount] = useState(0);

    useEffect(() => {
        const interval = setInterval(() => {
            setCount((prevCount) => prevCount + 1);
        }, 1000);

        // 清理副作用
        return () => clearInterval(interval);
    }, []); // 空数组表示只在组件挂载和卸载时执行

    return <p>计时器:{count} 秒</p>;
}

useEffect 接收一个函数作为参数,函数会在组件挂载(初始化)时调用。

如果返回一个清理函数,它会在组件卸载时执行,清理副作用(比如取消定时器)。

第二个参数 [] 表示依赖项,空数组意味着这个 useEffect 只在组件挂载和卸载时执行。

五、Hook 使用规则

使用 Hook 时,需要遵守以下规则:

1、只能在函数组件或自定义 Hook 中使用,不能在普通函数或类组件中使用。

2、只能在函数的顶层调用,不能在条件语句或循环中调用。

4、组件的生命周期

一、生命周期的三个主要阶段

挂载阶段(Mounting):组件被创建并插入到 DOM 中。

更新阶段(Updating):组件的状态或属性发生变化时,组件会重新渲染。

卸载阶段(Unmounting):组件从 DOM 中移除,生命周期结束。

二、类组件的生命周期

函数组件的生命周期由 useEffect 赋予,下面主要说类组件的生命周期

a、挂载阶段(Mounting)

当一个组件实例被创建并插入 DOM 时,它会经历以下几个生命周期方法:

constructor()

组件的构造函数,在组件实例化时调用。

用于初始化组件的状态,绑定事件处理方法。

不建议在 constructor 中进行副作用操作,如发起请求。

constructor(props) {
    super(props);
    //在JavaScript中,如果一个类继承了另一个类,那么子类必须在构造函数中调用父类的构造函数
    this.state = {
        count: 0
    };
    //类组件中,所有的状态数据都存储在 this.state 中,组件的状态需要通过 this.state 来访问和修改 
    //类组件中如果要修改状态通过this.setState,如this.setState({ count: this.state.count + 1 })
}
static getDerivedStateFromProps()

在每次组件更新时调用,渲染前调用。

它的作用是根据父组件传递的 props 来更新组件的状态。

这个方法是静态的,不能访问 this,并且返回一个新的状态对象或 null。

static getDerivedStateFromProps(nextProps, nextState) {
    if (nextProps.value !== nextState.value) {
        return {
            value: nextProps.value
        };
    }
    return null; // 不需要更新 state
}
render()

必须实现的函数,用来返回 JSX,表示组件的 UI。

只根据 props 和 state 生成 UI,不能修改状态或做副作用。

render() {
    return <div>{this.state.count}</div>;
}
componentDidMount()

组件挂载完成后调用。

适合用来做一些副作用操作,例如发送网络请求、添加事件监听器等。

只会在组件挂载后执行一次。

componentDidMount() {
    console.log("Component has mounted!");
}

b、更新阶段(Updating)

组件的更新阶段是当 state 或 props 改变时发生的。此时,React 会重新渲染组件并更新 DOM

getDerivedStateFromProps()

在更新阶段,getDerivedStateFromProps() 会在 父组件的 props 或组件的 state 更新时被调用。你可以在这个阶段根据新的 props 更新组件的 state,例如父组件传递的数据变化了,子组件需要根据新数据更新自己的状态。

每次组件重新渲染时,getDerivedStateFromProps() 都会被调用,所以需要非常小心性能问题,确保它不进行不必要的更新。

shouldComponentUpdate()

当组件的 props 或 state 更新时,调用此方法。

用来判断组件是否需要重新渲染。返回 true 表示继续渲染,返回 false 表示跳过渲染。

这是性能优化的一种方式,可以避免不必要的渲染。

shouldComponentUpdate(nextProps, nextState) {
    return nextState.count !== this.state.count;
}
render()

组件在更新阶段的 render() 方法会根据更新后的 state 和 props 重新渲染 UI。

getSnapshotBeforeUpdate()

在 render() 方法之后、DOM 更新之前调用。

它允许你在组件更新之前读取一些 DOM 信息(例如获取滚动位置),并将其传递给 componentDidUpdate()。

getSnapshotBeforeUpdate(prevProps, prevState) {
    return null; // 返回一个值会传递给 componentDidUpdate
}
componentDidUpdate()

组件更新后调用。

用于执行副作用操作,通常用来处理一些基于更新的操作,比如数据请求或动画效果。

可以通过 prevProps 和 prevState 获取更新前的 props 和 state。

componentDidUpdate(prevProps, prevState, snapshot) {
    console.log("Component did update!");
}

c、卸载阶段(Unmounting)

当组件从 DOM 中移除时,React 会调用 componentWillUnmount(),这是最后的生命周期方法。

componentWillUnmount()

组件即将卸载时调用。

用来清理副作用,比如清除定时器、移除事件监听器等。

componentWillUnmount() {
    console.log("Component is being removed from the DOM.");
}

5、组件之间的信息传递

之前说过了,组件之间通过 props 来通信,父组件通过 props 给子组件传递信息,下面是一个用法的示例

function Parent() {
    return <Child message="Hello from Parent!" />;
}

function Child(props) {
    return <h1>{props.message}</h1>;
}
//Parent 组件将一个 message 属性传递给 Child 组件,Child 组件通过 props.message 来获取并显示它。
posted @   KJGKMTZB  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示