MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

React组件基础入门

2021-11-126.3k 阅读

React 组件基础入门

在前端开发领域,React 已经成为构建用户界面的重要工具之一。而理解和掌握 React 组件则是踏入 React 开发大门的关键一步。本文将深入探讨 React 组件的基础概念、创建方式、属性与状态等重要内容,并通过丰富的代码示例来帮助你更好地理解。

什么是 React 组件

React 组件是构成 React 应用程序的基本单元。简单来说,一个组件就是一个独立的、可复用的代码片段,它封装了特定的功能和用户界面。每个组件都有自己的状态(state)和属性(props),并且可以渲染出对应的 HTML 结构。

想象一下,你正在构建一个电商网站。商品列表、购物车、商品详情页等都可以看作是一个个不同的 React 组件。商品列表组件负责展示所有商品,购物车组件处理用户购物车相关的逻辑和界面,商品详情页组件则详细展示某一特定商品的信息。通过将整个应用拆分成多个组件,我们可以实现代码的模块化,提高代码的可维护性和复用性。

创建 React 组件

在 React 中,有两种主要的方式来创建组件:函数式组件和类组件。

  1. 函数式组件 函数式组件是一种简单的定义组件的方式,它本质上就是一个 JavaScript 函数。函数接收一个包含属性(props)的对象作为参数,并返回一个 React 元素。下面是一个简单的函数式组件示例:
import React from 'react';

const HelloWorld = (props) => {
    return <div>Hello, {props.name}!</div>;
};

export default HelloWorld;

在上述代码中,HelloWorld 是一个函数式组件。它接收 props 参数,props 中包含了我们传递进来的属性。这里我们假设传递了一个 name 属性,并在返回的 React 元素中使用它,从而在页面上显示出个性化的问候语。

  1. 类组件 类组件则是基于 ES6 类的方式来定义组件。它需要继承自 React.Component 类,并实现 render 方法。render 方法返回要渲染的 React 元素。以下是一个类组件的示例:
import React, { Component } from'react';

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

export default HelloWorldClass;

在这个类组件 HelloWorldClass 中,我们通过 this.props 来访问传递进来的属性。render 方法返回的内容和函数式组件返回的内容类似,都是用于在页面上显示的 React 元素。

从 React 16.8 版本引入 React Hooks 后,函数式组件得到了极大的增强,能够实现以前类组件才有的功能,如状态管理和生命周期方法等。不过,类组件在一些老项目中仍然广泛存在,所以对两种组件定义方式都需要掌握。

React 组件的属性(props)

属性(props)是 React 组件之间传递数据的主要方式。组件通过接收属性来定制其行为和外观。属性是只读的,一旦传递给组件,组件内部不能直接修改它。

  1. 传递属性 在父组件中,可以像这样向子组件传递属性:
import React from'react';
import HelloWorld from './HelloWorld';

const App = () => {
    return (
        <div>
            <HelloWorld name="John" />
        </div>
    );
};

export default App;

在上述代码中,App 组件是父组件,它将 name 属性设置为 John 并传递给了 HelloWorld 子组件。

  1. 默认属性值 为了防止属性未传递时出现错误,我们可以为组件的属性设置默认值。在函数式组件中,可以这样设置:
import React from'react';

const HelloWorld = (props) => {
    const { name = 'Guest' } = props;
    return <div>Hello, {name}!</div>;
};

export default HelloWorld;

在类组件中,则使用 defaultProps 来设置默认属性值:

import React, { Component } from'react';

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

HelloWorldClass.defaultProps = {
    name: 'Guest'
};

export default HelloWorldClass;

这样,当父组件没有传递 name 属性时,组件会使用默认值 Guest

React 组件的状态(state)

状态(state)是组件内部的数据,它可以随着时间而变化。与属性不同,状态是组件私有的,可以在组件内部进行修改。状态的改变会触发组件的重新渲染,从而更新用户界面。

  1. 在类组件中使用状态 在类组件中,需要在构造函数中初始化状态。以下是一个简单的计数器类组件示例:
import React, { Component } from'react';

class Counter extends Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0
        };
    }

    increment = () => {
        this.setState({
            count: this.state.count + 1
        });
    };

    render() {
        return (
            <div>
                <p>Count: {this.state.count}</p>
                <button onClick={this.increment}>Increment</button>
            </div>
        );
    }
}

export default Counter;

在上述代码中,Counter 组件在构造函数中初始化了 count 状态为 0。increment 方法通过 this.setState 来更新状态,setState 是 React 提供的用于更新状态的方法,它会触发组件的重新渲染。当用户点击按钮时,count 状态增加,页面上显示的计数也会随之更新。

  1. 在函数式组件中使用状态(React Hooks) React Hooks 提供了 useState 钩子函数,使得函数式组件也能使用状态。以下是用函数式组件实现同样计数器功能的代码:
import React, { useState } from'react';

const CounterFunction = () => {
    const [count, setCount] = useState(0);

    const increment = () => {
        setCount(count + 1);
    };

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

export default CounterFunction;

在这个函数式组件中,useState 接受一个初始值 0,并返回一个数组,数组的第一个元素 count 是当前状态值,第二个元素 setCount 是用于更新状态的函数。当点击按钮调用 setCount 时,组件会重新渲染并显示更新后的计数。

React 组件的生命周期

组件的生命周期描述了组件从创建到销毁的整个过程。在不同的阶段,组件会执行特定的方法,我们可以利用这些方法来处理一些逻辑,比如数据的加载、清理等。

  1. 类组件的生命周期
    • 挂载阶段
      • constructor:组件的构造函数,在组件创建时被调用。通常用于初始化状态和绑定方法。
      • componentDidMount:组件挂载到 DOM 后调用。在这里可以进行一些需要 DOM 元素的操作,如发起网络请求获取数据等。
    • 更新阶段
      • shouldComponentUpdate:在组件接收到新的属性或状态时调用,用于判断组件是否需要更新。返回 true 表示需要更新,false 则表示不需要更新。这可以用于性能优化,避免不必要的重新渲染。
      • componentDidUpdate:在组件更新后调用。可以在这里进行一些依赖于更新后 DOM 状态的操作。
    • 卸载阶段
      • componentWillUnmount:在组件从 DOM 中移除之前调用。常用于清理定时器、取消网络请求等操作。

以下是一个展示类组件生命周期方法调用的示例:

import React, { Component } from'react';

class LifecycleExample extends Component {
    constructor(props) {
        super(props);
        console.log('Constructor');
    }

    componentDidMount() {
        console.log('Component Did Mount');
    }

    shouldComponentUpdate(nextProps, nextState) {
        console.log('Should Component Update');
        return true;
    }

    componentDidUpdate() {
        console.log('Component Did Update');
    }

    componentWillUnmount() {
        console.log('Component Will Unmount');
    }

    render() {
        console.log('Render');
        return <div>Lifecycle Example</div>;
    }
}

export default LifecycleExample;

在浏览器控制台中,你可以看到随着组件的创建、更新和销毁,相应的生命周期方法被依次调用并打印出日志。

  1. 函数式组件的生命周期(React Hooks 模拟) 虽然函数式组件没有传统的生命周期方法,但可以通过 useEffect 钩子函数来模拟一些生命周期行为。
    • 模拟 componentDidMount
import React, { useEffect } from'react';

const MountExample = () => {
    useEffect(() => {
        console.log('Component Did Mount');
        return () => {
            console.log('Component Will Unmount');
        };
    }, []);

    return <div>Mount Example</div>;
};

export default MountExample;

在上述代码中,useEffect 的第一个参数是一个回调函数,当组件挂载时,这个回调函数会被执行,模拟了 componentDidMount 的行为。同时,这个回调函数返回了另一个函数,当组件卸载时,这个返回的函数会被执行,模拟了 componentWillUnmount 的行为。useEffect 的第二个参数是一个空数组 [],表示这个 useEffect 只在组件挂载和卸载时执行,不会因为其他状态或属性的变化而执行。 - 模拟 componentDidUpdate

import React, { useState, useEffect } from'react';

const UpdateExample = () => {
    const [count, setCount] = useState(0);

    useEffect(() => {
        console.log('Component Did Update');
    }, [count]);

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

export default UpdateExample;

这里 useEffect 的第二个参数是 [count],表示只有当 count 状态发生变化时,useEffect 中的回调函数才会被执行,从而模拟了 componentDidUpdate 对特定状态变化的响应。

React 组件的组合与嵌套

在实际应用中,一个 React 应用通常由多个组件相互组合和嵌套而成。通过组件的组合,可以构建出复杂的用户界面。

  1. 组件组合 假设我们有一个 Button 组件和一个 Container 组件,我们可以在 Container 组件中使用 Button 组件,实现组件的组合。
import React from'react';

const Button = (props) => {
    return <button>{props.label}</button>;
};

const Container = () => {
    return (
        <div>
            <Button label="Click Me" />
        </div>
    );
};

export default Container;

在上述代码中,Container 组件内部使用了 Button 组件,并为 Button 组件传递了 label 属性。

  1. 组件嵌套 组件嵌套则是指在一个组件的返回内容中包含其他组件,并且这些组件之间有层次关系。比如一个 Menu 组件包含多个 MenuItem 组件。
import React from'react';

const MenuItem = (props) => {
    return <li>{props.text}</li>;
};

const Menu = () => {
    return (
        <ul>
            <MenuItem text="Home" />
            <MenuItem text="About" />
            <MenuItem text="Contact" />
        </ul>
    );
};

export default Menu;

这里 Menu 组件内部嵌套了多个 MenuItem 组件,形成了一个简单的菜单结构。

总结 React 组件基础要点

通过以上对 React 组件基础的学习,我们了解到:

  • React 组件是构建 React 应用的基本单元,有函数式组件和类组件两种定义方式。
  • 属性(props)用于组件间传递数据,是只读的;状态(state)是组件私有的数据,可通过 setState(类组件)或 useState(函数式组件)来更新,状态变化会触发组件重新渲染。
  • 类组件有完整的生命周期方法,函数式组件可通过 useEffect 等钩子函数模拟一些生命周期行为。
  • 组件之间可以通过组合和嵌套的方式构建复杂的用户界面。

掌握这些 React 组件的基础知识,是进一步深入学习 React 开发的重要基石。在后续的学习和实践中,你将不断运用这些知识,构建出功能丰富、交互流畅的前端应用程序。

希望通过本文的讲解和代码示例,你对 React 组件基础有了更深入的理解和掌握。在实际开发中,多实践、多思考,不断积累经验,才能更好地运用 React 组件开发出优秀的前端项目。