当前位置: 首页 > news >正文

React教程(React入门教程)(React组件、JSX、React Props、React State、React事件处理、Hooks、高阶组件HOC)

文章目录

  • 一、什么是React
  • 二、React的特点
    • 1. **组件化**:React采用组件化模式,将UI拆分为独立、可复用的组件,提高代码复用率。
    • 2. **声明式设计**:React采用声明范式,可以轻松描述应用状态与UI之间的关系。
    • 3. **虚拟DOM**:React不直接操作DOM,而是通过虚拟DOM和diff算法,以最小的步骤作用到真实的DOM上,提升性能。
    • 4. **单向数据流**:React实现了单向响应的数据流,从数据到视图的渲染,减少了重复代码,比传统数据绑定更简单。
    • 5. **高效**:通过对DOM的模拟,最大限度地减少与DOM的交互。
    • 6. **灵活**:React可以与已知的库或框架很好地配合。
  • 三、React与其他框架的比较
    • - React只专注于MVC框架中的V(视图层),而AngularJS是一个完整的MVC框架。
    • - React是单向数据流,非双向数据绑定。
    • - React不直接操作DOM,而是通过虚拟DOM进行编程。
  • 四、React应用现状
  • 五、环境搭建
  • 六、React核心概念
    • 1. 组件
      • **类组件示例**:
      • **函数组件示例**:
    • 2. JSX
    • 3. Props
    • 4. State
    • 5. 事件处理
      • React使用事件处理函数处理用户交互。
      • 疑问:`this.handleClick = this.handleClick.bind(this);`多余吗?
        • 为什么需要绑定?
        • 为什么这行代码是必要的?
        • 对比其他写法(为什么这行代码是正确方式)
          • ❌ 错误写法(不绑定):
          • ✅ 正确写法(构造函数中绑定):
          • ✅ 替代方案(类属性 + 箭头函数,ES7 语法):
        • 为什么说“不多余”?
        • 为什么有人觉得“多余”?
        • 结论
      • 疑问:为什么 this 会丢失?
        • 详细解释
          • 1. 为什么 `this` 会丢失?(看不懂,尴尬😭测也测不出来。。。)
          • 2. 为什么在构造函数中绑定是正确的方式?
          • 3. 一个简单示例说明
        • 为什么不是多余的?
    • 6. Hooks
  • 七、高阶组件
  • 八、实战:创建一个简单的组件
  • 九、学习资源推荐
    • 1. **官方文档**:React官网提供了最权威的文档和教程。
    • 2. **React视频教程**:《React极速入门指南》、《Vue、Angular、React 项目开发与深度对比》。
    • 3. **实践项目**:通过构建实际项目(如电商网站、社交应用)来巩固知识。
    • 4. **社区支持**:React社区活跃,Stack Overflow、GitHub等平台有大量问题解答。
  • 十、结语

一、什么是React

React是由Facebook的软件工程师Jordan Walke创建的JavaScript库,于2011年部署于Facebook的newsfeed,2012年部署于Instagram,2013年5月正式开源。React专注于构建用户界面(UI),是MVC框架中的"V"(视图层),而非完整的MVC框架。

React的核心理念是"从UI出发,抽象出不同的组件,继而将它们拼装起来",这顺应了Web开发组件化的趋势。

二、React的特点

1. 组件化:React采用组件化模式,将UI拆分为独立、可复用的组件,提高代码复用率。

2. 声明式设计:React采用声明范式,可以轻松描述应用状态与UI之间的关系。

3. 虚拟DOM:React不直接操作DOM,而是通过虚拟DOM和diff算法,以最小的步骤作用到真实的DOM上,提升性能。

4. 单向数据流:React实现了单向响应的数据流,从数据到视图的渲染,减少了重复代码,比传统数据绑定更简单。

5. 高效:通过对DOM的模拟,最大限度地减少与DOM的交互。

6. 灵活:React可以与已知的库或框架很好地配合。

三、React与其他框架的比较

React与AngularJS等框架的主要区别在于:

- React只专注于MVC框架中的V(视图层),而AngularJS是一个完整的MVC框架。

- React是单向数据流,非双向数据绑定。

参考文章:React单向数据流(unidirectional data flow)与非双向数据绑定的理解

- React不直接操作DOM,而是通过虚拟DOM进行编程。

四、React应用现状

React在国外应用广泛,Facebook、Yahoo、Reddit等知名公司都在使用。在国内,知乎、豆瓣、优酷等大厂也逐渐采用React技术栈。

值得注意的是,截至2022年第一季度,国内前端框架使用上大多偏向于Vue,这导致React前端工程师相对稀缺。在学习难度上,React比Vue稍高,这也是许多企业对React开发经验要求较高的原因。

五、环境搭建

使用create-react-app脚手架快速搭建React项目:

# 创建新项目
npx create-react-app react-project# 进入项目目录
cd react-project# 启动项目
yarn start

如果提示没有yarn可看这里:yarn命令介绍(替代npm命令的JavaScript包管理工具)

在这里插入图片描述
在这里插入图片描述

六、React核心概念

1. 组件

React的核心是组件。组件是UI的构建块,可以是类组件或函数组件。

类组件示例

import React, { Component } from 'react'; // 从React库中导入React对象和Component类class Welcome extends Component { // 定义一个名为Welcome的类组件,继承自React.Componentrender() { // render方法是React组件的核心,用于返回要渲染的UIreturn <h1>Hello, {this.props.name}</h1>; // 返回一个h1元素,显示"Hello,"和传入的name属性}
}

函数组件示例

function Welcome(props) { // 定义一个名为Welcome的函数组件,接收props参数return <h1>Hello, {props.name}</h1>; // 返回一个h1元素,显示"Hello,"和传入的name属性
}

2. JSX

JSX是JavaScript语法的扩展,使HTML结构与JavaScript代码混合在一起,提高可读性。

const element = <h1>Hello, world!</h1>; // 创建一个h1元素,显示"Hello, world!"

3. Props

Props是组件的属性,用于从父组件向子组件传递数据。

function Welcome(props) { // 定义一个名为Welcome的函数组件,接收props参数return <h1>Hello, {props.name}</h1>; // 返回一个h1元素,显示"Hello,"和传入的name属性
}const element = <Welcome name="Sara" />; // 创建一个Welcome组件的实例,传入name属性为"Sara"

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. State

State是组件内部的状态,用于管理组件的动态数据。

class Counter extends Component { // 定义一个名为Counter的类组件,继承自React.Componentconstructor(props) { // 构造函数,初始化组件状态super(props); // 调用父类Component的构造函数this.state = { count: 0 }; // 初始化组件状态,count属性初始值为0}render() { // render方法,返回要渲染的UIreturn (<div><p>Count: {this.state.count}</p> // 显示count状态的值<button onClick={() => this.setState({ count: this.state.count + 1 })}>Increment // 按钮显示"Increment"</button></div>);}
}

5. 事件处理

React使用事件处理函数处理用户交互。

class Toggle extends Component { // 定义一个名为Toggle的类组件,继承自React.Componentconstructor(props) { // 构造函数,初始化组件状态super(props); // 调用父类Component的构造函数this.state = { isToggleOn: true }; // 初始化组件状态,isToggleOn属性初始值为true// 为确保this指向正确,绑定事件处理函数this.handleClick = this.handleClick.bind(this);}handleClick() { // 定义点击事件处理函数this.setState(prevState => ({ // 更新状态,使用prevState获取之前的状态isToggleOn: !prevState.isToggleOn // 将isToggleOn状态取反}));}render() { // render方法,返回要渲染的UIreturn (<button onClick={this.handleClick}> // 按钮的点击事件绑定到handleClick方法{this.state.isToggleOn ? 'ON' : 'OFF'} // 根据isToggleOn状态显示"ON"或"OFF"</button>);}
}

疑问:this.handleClick = this.handleClick.bind(this);多余吗?

在 React 类组件中,this.handleClick = this.handleClick.bind(this); 不是多余的,而是必要的。以下是详细解释:


为什么需要绑定?

在 JavaScript 中,类方法默认不会自动绑定 this。当我们将方法作为事件处理函数(如 onClick={this.handleClick})传递时:

  • 事件触发时,handleClick 会被调用,但 this 的指向会丢失(指向 undefinedwindow,取决于上下文)。
  • 例如:this.setState 会因 thisundefined 而报错。

为什么这行代码是必要的?
this.handleClick = this.handleClick.bind(this); // 绑定 this 指向组件实例
  • 作用:确保 handleClick 方法中的 this 指向组件实例(Toggle 的实例)。
  • 如果不绑定this.setState 会失败(thisundefined)。

对比其他写法(为什么这行代码是正确方式)
❌ 错误写法(不绑定):
render() {return <button onClick={this.handleClick}>...</button>; // this.handleClick 中的 this 为 undefined
}
✅ 正确写法(构造函数中绑定):
constructor(props) {super(props);this.state = { isToggleOn: true };this.handleClick = this.handleClick.bind(this); // 必须在这里绑定
}
✅ 替代方案(类属性 + 箭头函数,ES7 语法):
class Toggle extends Component {handleClick = () => { // 自动绑定 thisthis.setState(...);};// ...其他代码
}

注意:这是 ES7 语法(类属性),不是类方法。如果使用普通方法(非箭头函数),必须手动绑定


为什么说“不多余”?
  • 性能:在构造函数中绑定一次(this.handleClick = ...)比在 render 中每次渲染都绑定(onClick={this.handleClick.bind(this)}更高效
  • 正确性:确保 this 在组件生命周期中始终指向组件实例。

为什么有人觉得“多余”?
  1. 误解 ES6 类方法:误以为类方法会自动绑定 this实际不会)。
  2. 混淆箭头函数:如果写成 handleClick = () => { ... }(类属性),则无需绑定,但原始代码是普通方法handleClick() { ... }),所以必须绑定。

结论

this.handleClick = this.handleClick.bind(this); 是必要的,不是多余的。
它确保了事件处理函数中的 this 指向组件实例,是 React 类组件的标准实践。

推荐写法(构造函数绑定):

constructor(props) {super(props);this.state = { isToggleOn: true };this.handleClick = this.handleClick.bind(this); // 必须写
}

替代写法(ES7 类属性):

handleClick = () => { // 自动绑定,无需 bindthis.setState(...);
}

原始代码中的写法是正确且标准的,不是多余的

疑问:为什么 this 会丢失?

在 JavaScript 中,this 的指向取决于函数的调用方式,而不是定义方式。这是理解这个问题的关键。

详细解释
1. 为什么 this 会丢失?(看不懂,尴尬😭测也测不出来。。。)

当我们在 React 中这样写:

<button onClick={this.handleClick}>Toggle</button>

React 实际上是这样调用的:

// 伪代码
button.addEventListener('click', this.handleClick);

当按钮被点击时,React 会调用 this.handleClick,但调用方式是作为普通函数调用,而不是作为对象的方法调用。

在 JavaScript 中:

  • 如果函数是作为对象的方法调用(obj.method()),this 指向 obj
  • 如果函数是作为普通函数调用(method()),this 指向全局对象(浏览器中是 window)或 undefined(严格模式下)

所以当 handleClick 通过 onClick 被调用时:

  • 它不是通过 this.handleClick() 调用的
  • 而是通过 handleClick() 调用的
  • 因此 this 会丢失,指向 undefinedwindow
2. 为什么在构造函数中绑定是正确的方式?
constructor(props) {super(props);this.state = { isToggleOn: true };this.handleClick = this.handleClick.bind(this); // 绑定 this
}

这行代码的作用是:创建一个新的函数,将 this 指向组件实例。这样,无论 handleClick 如何被调用,this 都会指向组件实例。

3. 一个简单示例说明
class Example {constructor() {this.name = "Example";// 不绑定 thisthis.greet = this.greet.bind(this);}greet() {console.log("Hello, " + this.name);}run() {// 普通函数调用const fn = this.greet;fn(); // 输出: Hello, undefined (this 丢失)}
}const ex = new Example();
ex.run(); // 会输出 "Hello, undefined"

如果我们在构造函数中绑定了 this

constructor() {this.name = "Example";this.greet = this.greet.bind(this); // 绑定 this
}

那么 fn() 会正确输出 “Hello, Example”。

为什么不是多余的?

在 React 中,事件处理函数的 this 丢失是标准行为,不是 React 特有的问题。这是 JavaScript 语言本身的特性。

  • 如果不绑定,this.setState 会失败(因为 thisundefined
  • 在构造函数中绑定一次,比每次渲染都绑定(如 onClick={this.handleClick.bind(this)}更高效

所以,this.handleClick = this.handleClick.bind(this); 不是多余的,而是 React 类组件中必须的步骤,确保事件处理函数中的 this 指向组件实例。

6. Hooks

React Hooks是React 16.8引入的新特性,允许在函数组件中使用状态和其他React特性。

useState

import React, { useState } from 'react'; // 从React库中导入useState Hookfunction Example() { // 定义一个函数组件Example// 声明一个名为"count"的state变量,初始值为0const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p> // 显示点击次数<button onClick={() => setCount(count + 1)}> // 点击按钮时,将count加1Click me</button></div>);
}

useEffect

import React, { useState, useEffect } from 'react'; // 从React库中导入useState和useEffect Hookfunction Example() { // 定义一个函数组件Exampleconst [count, setCount] = useState(0); // 声明count状态变量// 类似于 componentDidMount 和 componentDidUpdate:useEffect(() => { // useEffect Hook,用于在组件渲染后执行副作用// 更新文档标题document.title = `You clicked ${count} times`; // 设置文档标题为"你点击了count次"}, [count]); // 仅在count变化时执行return (<div><p>You clicked {count} times</p> // 显示点击次数<button onClick={() => setCount(count + 1)}> // 点击按钮时,将count加1Click me</button></div>);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

七、高阶组件

高阶组件(HOC)是React中一个重要的概念,它本质上是一个函数,接收一个组件并返回一个新的增强版组件。

代理方式高阶组件

function withLogger(WrappedComponent) { // 定义一个高阶组件withLogger,接收一个组件作为参数return class extends React.Component { // 返回一个新的组件componentDidMount() { // 组件挂载完成后执行console.log(`Component ${WrappedComponent.name} mounted`); // 在控制台打印组件名称}render() { // 返回渲染的组件return <WrappedComponent {...this.props} />; // 将传入的props传递给被包装的组件}};
}

使用方式

const EnhancedComponent = withLogger(Welcome); // 使用withLogger高阶组件包装Welcome组件

八、实战:创建一个简单的组件

import React from 'react'; // 从React库中导入React对象
import ReactDOM from 'react-dom'; // 从react-dom库中导入ReactDOM对象class App extends React.Component { // 定义一个名为App的类组件,继承自React.Componentconstructor(props) { // 构造函数,初始化组件状态super(props); // 调用父类Component的构造函数this.state = { // 初始化组件状态message: 'Hello, React!' // message状态初始值为"Hello, React!"};}handleClick = () => { // 定义点击事件处理函数this.setState({ // 更新状态message: 'Button clicked!' // 将message状态更新为"Button clicked!"});}render() { // render方法,返回要渲染的UIreturn (<div> // 返回一个div容器<h1>{this.state.message}</h1> // 显示message状态的值<button onClick={this.handleClick}>Click Me</button> // 按钮的点击事件绑定到handleClick方法</div>);}
}ReactDOM.render(<App />, document.getElementById('root')); // 将App组件渲染到id为"root"的DOM元素中

九、学习资源推荐

1. 官方文档:React官网提供了最权威的文档和教程。

2. React视频教程:《React极速入门指南》、《Vue、Angular、React 项目开发与深度对比》。

3. 实践项目:通过构建实际项目(如电商网站、社交应用)来巩固知识。

4. 社区支持:React社区活跃,Stack Overflow、GitHub等平台有大量问题解答。

十、结语

React作为当今最流行的前端框架之一,以其组件化、声明式和高性能的特点,成为构建现代Web应用的首选。虽然学习曲线比Vue稍高,但掌握React将为你的前端开发技能带来巨大提升。

随着React生态系统的不断发展(如Redux、React Router、Hooks等),React的应用场景越来越广泛。无论你是前端新手还是有经验的开发者,学习React都将为你的职业发展带来重要价值。

开始你的React之旅,用组件化思维构建更高效、更可维护的Web应用吧!

http://www.dtcms.com/a/394968.html

相关文章:

  • 2025年CSP-S初赛真题及答案解析(完善程序第1题)
  • 六、页面优化
  • CVAT部署到虚拟机小记
  • scss基础学习
  • 基于衍射神经网络的光学高速粒子分类系统A1(未做完)
  • ffprobe安装与简单使用
  • close函数就像“关门“操作,用于关闭文件描述符释放系统资源
  • PyTorch 神经网络工具箱学习笔记
  • Qt常用控件之QWidget(三)
  • apache poi excel 单元格换行
  • 全能视频下载器-下载自媒体平台视频 v1.5.5 专业版
  • 状态模式指南:对象状态变化的优雅管理
  • 自动化多段视频删除:FFmpeg.AutoGen 与 C# 的完整实现​
  • C、C++、Java 和 Python:四大编程语言的对比分析
  • ESP iic驱动
  • Ai-Agent学习历程——大模型的概念
  • 5G NR-NTN协议学习系列:NR-NTN介绍(3)
  • 一场 MCP 生态的变革——详解 OpenTiny NEXT 逆向思维的技术创新
  • 【案例教程】从CNN到 Transformer:基于PyTorch的遥感影像、无人机影像的地物分类、目标检测、语义分割和点云分类
  • 私有证书不被edge浏览器认可的问题的解决-Debian13环境下
  • 团体程序设计天梯赛 L2-052 吉利矩阵 (DFS+剪枝)(Java实现)
  • 【LeetCode 每日一题】966. 元音拼写检查器
  • windows 服务器如何开启系统自带的ftp服务
  • 2025年面试经历
  • Linux 基础:目录结构
  • OpenLayers地图交互 -- 章节七:指针交互详解
  • Kafka实战案例一:阿里云Kafka智能设备数据实时处理系统
  • 回调函数与错误处理
  • 深入大模型-2-大模型微调之Windows10安装大语言模型Unsloth微调环境
  • openssl x509 -noout -text -in server.cert.pem输出字段详解