React是个啥?
React 是一个用于构建用户界面的 JavaScript 库 ,由 Facebook于2011年开发并开源。它的核心目标是高效、灵活地构建动态网页应用。
简单来说,React 让你用 组件(Component) 的方式搭建界面,就像用乐高积木拼装玩具一样:
- 每个组件负责一块功能(如按钮、导航栏、数据列表)。
- 组件可以组合、复用,不同拼凑好的积木重新组合成新东西。
- 数据变化时,React 自动更新界面,无需手动操作 DOM。
为什么选择React?
React和传统的DOM(Document Object Model)编程相比,让我们不再需要把精力聚焦在细节上,比如同一段需求实现,DOM编程和React相比:
js
// 手动找到DOM元素并修改
const element = document.getElementById('armor-status');
element.innerHTML = '能量剩余: 75%';
element.style.color = 'orange';
js
// 直接描述"UI应该是什么样子"
function ArmorStatus() {
return (
<div style = {{ color: 'orange' }} >
能量剩余: {75}%
</div>
);
}
其次,我们将某一些功能封装 成了一个组件,这个组件又可以在其他地方使用,大大提升了复用性,就拿B站的来举例吧:
这是B站主页的部分组件,最常用的应该就是导航栏组件了,这个组件的复用性极高,如果我们利用传统的JS,那只能对这个组件的代码CV了,但是如果利用React,我们就可以将其封装成一个组件(Component),在需要的时候直接将组件嵌入即可。
下面是b站其他网页应用导航栏的例子:


如何创建React?
既然大家对于React有了一个基础的认知了,那么下面我们就一起来创建一个React项目吧。
首先创建一个文件夹,在里面存放react项目,文件名自定义,之后在终端中输入以下命令:
cmd
npm init vite
之后取个文件名
按小键盘上下来选择框架类型,选择React,再选择JavaScript
接下来根据提示逐一执行命令:
所有命令执行完毕后,打开其提供的链接:
这样你的第一个React项目就创建完毕了。

如何理解组件化/数据驱动?
接下来让我们以一个例子来走进React的这两个特性,我们来做一个TodoList:
做一个输入框,一个button,将要做的事情输入并展现在输入框下面。

首先我们先删除App.jsx到这样:
之后在src文件下创建 components
文件夹,在里面创建 TodoList.jsx
文件
组件化
我们的功能模块都是封装成一个个组件的,而App.jsx
就是我们的根组件
,也就是说其他的组件要挂载到这上面,在App.jsx
的基础上进行展示,那么我们就可以将TodoList.jsx
挂载到App
中:
jsx
import TodoList from './components/TodoList' // 引入TodoList
import './App.css'
function App() {
return (
<>
<TodoList/> <!--作为组件之一,挂载到模板上-->
</>
)
}
export default App
接下来我们可以编写Todolist
的内容了:
jsx
function TodoList(){
const title = "Todo List";
const hi = "Hello World";
return (
<div className="container" style={{color:"red"}}>
<h1>{title}</h1>
<h2>{hi}</h2>
</div>
)
}
export default TodoList; // 记得将函数导出,只有货物出口了,所需的国家(App.jsx)才能进口
什么是组件
就上面的例子来看,组件就是html+css+js
的一个结合,是一个开发单元,一个功能的实现就可以放到一个组件中,它的本质就是返回了一个函数,函数里面的返回值返回了相应的元素,同时实现了某些功能。
比较来讲,之前的DOM编程,html和css以及JS都是分开来写的,现在有了react
,我们把它们组合来写,不再分开去写,而是将要实现功能的html、css、JS全部组合到一起,实现了组件化开发。
如何划分组件?
以 TodoList
为例,函数就是一个组件,return
之前可以写JavaScript的各种数据和逻辑,return直接返回html
,以类字符串模板的形式,将数据嵌入到html标签内,可以更加方便的实现数据传递动态更新的功能。
组件化思想:现代前端开发的基石
在前端开发领域,组件化思想 已经成为所有现代框架(React、Vue、Svelte等)的核心设计理念。它彻底改变了我们构建用户界面的方式,将开发模式从传统的DOM树编程 升级为更高效的组件树编程。
1. 从"沙子"到"砖块"的进化
如果把构建网页比作建造一面墙:
- 传统HTML就像是散落的沙子------虽然能完成基础结构,但缺乏工程化的组织方式
- 组件则是预制的砖块------每个组件都封装了相关的HTML结构、CSS样式和JavaScript逻辑,成为一个完整的功能单元
例如,一个<TodoItem>
组件就包含了任务展示、完成状态切换和删除等完整功能,开发者无需关心内部DOM操作细节。
2. 组件的核心优势
- 功能封装 :将相关的UI和逻辑组合成独立单元(如
<SearchBar>
、<ProductCard>
) - 极致复用 :像乐高积木一样重复使用(一个
<Button>
组件可在全项目通用) - 协作开发:不同开发者可以并行开发不同组件
3. 组件化开发范式
现代前端项目本质上就是组件树的组合:
通过这种层级结构,复杂页面被分解为可维护的独立单元。开发者只需关注:
- 如何合理拆分组件(原子设计原则)
- 组件间的数据流动(props/state管理)
- 业务逻辑的实现(而非DOM操作)
这种模式让前端开发真正聚焦于业务价值而非底层实现,这也是React等框架迅速崛起的关键原因。
表单输入
接下来让我们编写另一个组件TodoForm.jsx
用来添加输入框和提交按钮,首先在components
文件夹下创建TodoForm.jsx
:
jsx
import { useState } from "react";
function TodoForm(props) {
return (
<form className="form" >
<input type="text" className="input" placeholder="Add a todo..." />
<button type='submit' className="button">Add</button>
</form>
)
}
export default TodoForm;
再利用import TodoForm from'./TodoForm'
将其添加至Todolist.jsx
即可
jsx
import TodoForm from'./TodoForm'
import Todos from'./Todos'
function TodoList(){
const title = "Todo List";
const hi = "Hello World";
return (
<div className="container">
<h1>{title}</h1>
<h2>{hi}</h2>
<TodoForm/>
<Todos/> <!--将下面展示列表的功能模块暂时命名为Todos;-->
</div>
)
}
export default TodoList;
这样第二个模块就写好了,接下来就是要处理数据传输的逻辑了:
当我们利用表单提交数据,我们希望其不要刷新页面,并将表单数据提交到当前页面,所以就对其修改如下:
jsx
import Todos from "./Todos";
import { useState } from "react";
function TodoForm() {
const [text, setText] = useState('打豆豆') // 状态的初始值
const handleChange = (e) => { // 事件处理函数 事件对象e event object
setText(e.target.value)
}
const handleSubmit = (e) => {
console.log(e);
e.preventDefault(); // event api
}
return (
<form className="form" onSubmit={handleSubmit} action="localhost:5173">
<input type="text" className="input" placeholder="Add a todo..." value={text} onChange={handleChange}/>
<button type='submit' className="button">Add</button>
</form>
)
}
export default TodoForm;
value
给表单内容设置了个初始值为text
,为什么要用onchange呢?因为当你设置这个初始值后,这个初始值是常量,不可改变,所以就需要利用onchange
时刻检测text的变化,并利用setText展示出来并修改原Text的值。
数据驱动
有的同学会疑问,const[text,setText] = useState('打豆豆')
是个什么鬼?
这就是React的精髓了,useState顾名思义就是使用状态,React将纯数据转换成了数据状态 ,这一个语句是一个解构赋值,当你用输出展示useState中都有什么东西时,你会发现useState[0]是它的初始值,我们在这里将其设置为了打豆豆
,useState[1]是一个函数,用于改变Text的值。
什么叫数据驱动?简而言之,就是数据在更新时,页面内容才会发生更改,自动更新,在这里就是数据状态的改变,数据状态的改变驱动着页面的变化,比如写一个时钟,随着时间不断更改,React每检测到数据变化就会将相应的变化利用虚拟DOM驱动真实DOM发生更改呈现在页面上。
为什么是虚拟DOM?它有什么用?
在框架设计的时候,由于React是数据驱动的,一个组件中可能有100个数据,某一个数据发生了变化,我就要去更新它,但它由于很多问题,导致它检测不出来哪个发生了变化,所以它就有个render函数,我用render将数据全部重新加载,全量生成页面,那么利用真实DOM开销就很昂贵了,所以就开发了虚拟DOM,其利用数据改变后创建的虚拟DOM与之前的真实DOM利用diff比较,找到不一样的再操作真实DOM发生改变,其在某种程度上是增进了一定的效率。
OK,继续,我们由于需要进行数据的接收和更新,所以我们需要对TodoList.jsx
进行改进:
jsx
const [todos, setTodos] = useState([
{
id: 1,
title: 'todo 1',
completed: false,
} // 初始化一个todo列表
])
// useState是一个hook函数,
// 返回一个数组,
// 第一个元素是状态,
const handleAdd = (text) =>{
setTodos([
...todos, //展开原来数组
{
id:todos.length+1,
title:text,
completed:false,
}
])
}
return (
<TodoForm onAdd={handleAdd}/> //对这俩元素进行改变,将函数和数据分别传递给子组件
<Todos todos={todos}/>
// 将 handleAdd函数传过去,传过去的函数名叫onAdd
// 将 todos 数组传递过去,传过去的数组名叫todos
)
之后子组件更新逻辑,调用父组件的函数来实现todos的更新(TodoForm.jsx完整版):
jsx
import Todos from "./Todos";
import { useState } from "react";
function TodoForm(props) {
const onAdd = props.onAdd;
const [text, setText] = useState('打豆豆') // 状态的初始值
const handleChange = (e) => { // 事件处理函数 事件对象e event object
setText(e.target.value)
}
const handleSubmit = (e) => {
console.log(e);
e.preventDefault(); // event api
// 如何修改todos? 由于是父组件的,改不了,所以只能打报告
onAdd(text)
}
return (
<form className="form" onSubmit={handleSubmit} action="localhost:5173">
<input type="text" className="input" placeholder="Add a todo..." value={text} onChange={handleChange}/>
<button type='submit' className="button">Add</button>
</form>
)
}
export default TodoForm;
jsx
// 列表的渲染
import TodoForm from "./TodoForm";
function Todos(props) {
// 利用参数拿到父组件传来的数据状态
const todos = props.todos;
console.log(props + '/////');
return(
<ul>
{ //数据绑定 data binding
// 数据驱动
// 发生改变后 自动地改变界面
todos.map(todo=>(
<li key={todo.id}>{todo.title}</li>
)) // 利用map循环更新
}
</ul>
)
}
export default Todos;
TodoList:
jsx
import { useState } from 'react' // 内置的hook函数
import '../Todo.css'
import TodoForm from './TodoForm'
import Todos from './Todos'
function TodoList() {
const[hi,setHi] = useState('haha');
const [title,setTitle] = useState('Todo_list')
// 数据 -》 变化 -》 数据状态 -> 自动刷新页面 -》数据驱动(drive)页面
// 数据 ↓
const [todos, setTodos] = useState([
{
id: 1,
title: 'todo 1',
completed: false,
}
])
const handleAdd = (text) =>{
setTodos([
...todos,
{
id:todos.length+1,
title:text,
completed:false,
}
])
}
return (
<div className="container">
<h1>{title}</h1>
<h2>{hi}</h2>
<TodoForm onAdd={handleAdd}/>
<Todos todos={todos}/>
</div>
)
}
export default TodoList
总结
通过这个例子,我们要学会组件化思想,看到需求先想想能划分成几个组件,将各自的逻辑封装在里面,最后集中挂载到一个根组件去展示,要理解 data-binding 数据绑定和数据驱动的意义,在这个例子中, 由于form表单每次更新都会触发onAdd函数,每一次都会对todos进行更新,最后使得页面进行更新,这就是数据驱动。