(先赞后看,已成习惯(bushi))这段时间,也是学习了一点React相关的知识,想着来写一篇文章总结一下对这段时间的学习以及学习成果,各位大佬看看有什么不足之处,欢迎指导~~~
前言(不用看):前端技术的不断发展,现代 Web 应用已经告别了传统的手动操作 DOM 和底层 API,转向了更加高效和灵活的数据驱动界面开发。React,作为最受欢迎的前端框架之一,利用组件化和响应式数据流,使得开发者能够专注于业务逻辑,而不是繁琐的 DOM 操作。
此文章将以 React 中的 Todo List 组件为例,深入剖析如何通过组件化思想、数据驱动的方式来构建一个响应式的 Web 应用。
项目的初始化与工程化:vite + React
在开始编写 React 项目之前,我们需要先进行项目初始化。现代前端开发离不开良好的构建工具,vite
是目前非常流行的前端构建工具之一,它提供了快速的开发环境和优化的打包性能。
** 创建一个React项目**
既然是React项目,那我们该如何创建呢? 下面跟着我一起来敲一敲这段神秘的代码吧!
- npm init vite 按vite模版初始化一个React项目
- 为我们的项目取一个名字TodoListComponent
- 选择React项目,语言为JS
- npm i 安装依赖
- npm run dev 启动项目,打开端口
React 初体验:组件化开发与状态管理
React 的核心思想是组件化。每个组件都是完成开发任务的最小单元,它将 HTML、CSS 和 JavaScript 结合在一起,封装成一个功能单元。让我们从创建一个简单的 Todo List 组件开始,一起来快速体验一下 React 的组件化开发吧!!
1. 组件是最小的开发单元
在 React 中,组件(Component)就是一个函数function(),每个组件就像一个个小功能块,并且这个功能块是独立的、被封装的。举个栗子,相信大家都拼过乐高积木吧,React 一个个组件就像一块块乐高积木。在开发React业务时,一个个大大小小的组件也就构成了我们的项目。 下面是个组件的例子
js
// 函数组件示例
function MyComponent() {
return <h1>Hello, React!</h1>;
}
在JS中,组件通常为函数式组件,由html,css,js共同构成,并且组件可以被复用和嵌套,在一个团队型业务开发中,你写的组件可以供全队的成员使用,同时你也可以使用其他团队成员的组件,是不是非常方便?
下面我们就开始构建jsx项目吧(jsx实则为js)
javascript
jsx
import { useState } from 'react';
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: '吃饭', completed: false },
]);
const handleAdd = (text) => {
setTodos([
...todos,
{ id: todos.length + 1, text, completed: false },
]);
};
return (
<div>
<h1>Todo List</h1>
{/* 表单组件 */}
<TodoForm onAdd={handleAdd} />
{/* 列表组件 */}
<Todos todos={todos} />
</div>
);
}
这是什么东西???我的脑袋好像不管用了。 下面我就来逐步分析一下吧
import { useState } from 'react'; 此代码意思是从react中导入一个为useState的hook, 那么有什么用?let's go!
其实useState是一个函数,此函数接受一个初始状态作为参数值,返回的是一个数组,数组的第一元素是当前的状态值,第二个元素是一个函数,可以用来更新当前状态
举个例子 const [todos, setTodos] = useState('todo') todos里面放的是todo setTodo可以和后续的定时器一起用来修改当前的状态值
下面我们来解释一下return里面的内容吧!期待一下(*❦ω❦)
-
<Todos />
是另一个自定义子组件,负责展示待办事项列表。todos
是父组件TodoList
中的状态变量,存储了所有待办事项的数据(包括每个待办事项的id
、text
、completed
等)。 -
todos={todos}
:这是将todos
作为 prop 传递给Todos
组件。Todos
会接收到这个todos
数据,并在其内部渲染所有待办事项。 -
<TodoForm />
是一个自定义的子组件,它负责展示一个表单界面,允许用户输入新的待办事项。 -
onAdd={handleAdd}
:这里是通过 props 将父组件(TodoList
)中的handleAdd
方法传递给TodoForm
组件。handleAdd
是父组件中的一个方法,它负责处理新任务的添加逻辑。
具体来说,TodoForm
会展示一个输入框和一个提交按钮,用户输入任务后点击提交按钮时,handleAdd
被调用,TodoForm
通过 onAdd
这个 prop 将数据(比如新任务的内容)传递回 TodoList
,然后 TodoList
更新其 todos
状态,重新渲染界面。
在这个例子中,TodoList
是一个 React 组件,它包含了一个 useState
钩子来存储和更新 todos
数据。你可以看到,组件通过 return
语句返回了一段 HTML,同时return里面又包含两个自定义的子组件,并通过 {todos.map(...)}
显示了所有待办项。
2. 数据驱动界面
在 React 中,数据状态 state
是自动驱动 UI 更新的关键。当 state
发生变化时,React 会重新渲染组件并更新视图,确保页面始终保持最新的状态。
php
jsx
复制编辑
const [todos, setTodos] = useState([
{ id: 1, text: '吃饭', completed: false },
]);
// 添加新任务
const handleAdd = (text) => {
setTodos([
...todos,
{ id: todos.length + 1, text, completed: false },
]);
};
通过 useState
我们可以轻松地管理组件中的数据状态,并通过 setTodos
方法来更新它。一旦数据发生变化,React 会自动更新页面中与之相关的部分,省去了手动操作 DOM 的麻烦。
3. 数据和 UI 绑定
React 中的模板语法非常直观,通过 {}
来绑定数据。这使得数据和视图的同步变得非常简单。我们不需要手动去操作 DOM,React 会根据数据的变化自动更新视图。
javascript
jsx
复制编辑
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
在这个例子中,todos.map()
遍历了 todos
数组,并动态渲染每个待办事项。如果我们添加一个新的待办项,React 会自动更新视图,展示新的列表项。
模块化开发:拆分组件与职责划分
随着项目的复杂度增加,组件化开发的优势会逐渐显现。在大型项目中,我们往往需要将组件进行拆分,每个组件只负责一个功能或者一个页面部分。
1. 拆分组件
在 Todo List 应用中,我们可以将不同的功能拆分成多个组件,例如:
TodoForm
:负责添加新任务的表单组件TodoItem
:负责渲染单个待办项TodoList
:负责显示任务列表的组件
2. 组件传值与通信
React 中的组件之间通过 props
传递数据,父组件向子组件传递数据,而子组件则通过触发回调函数来与父组件进行通信。
ini
jsx
function TodoForm({ onAdd }) {
const [text, setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
onAdd(text);
setText('');
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button type="submit">Add</button>
</form>
);
}
在 TodoForm
组件中,我们通过 props.onAdd
将任务添加的功能传递给父组件 TodoList
。这种方式非常适合拆分复杂的 UI,提升代码的可复用性和可维护性。
这段代码是一个 React 组件 TodoForm
,它负责渲染一个输入框和一个按钮,让用户输入待办事项,并通过点击按钮提交该事项。下面我将详细解释每一部分的内容,帮助你理解它的工作原理。
完整代码
ini
import { useState } from 'react';
function TodoForm(props) {
const onAdd = props.onAdd; // 从父组件接收到的 props
const [text, setText] = useState('打豆豆'); // useState 用来管理表单输入的状态
const handleSubmit = (e) => {
e.preventDefault(); // 阻止表单的默认提交行为
onAdd(text); // 调用父组件传递的 onAdd 函数并传递文本
}
const handleChange = (e) => {
setText(e.target.value); // 更新输入框的状态
}
return (
<form action="http://www.baidu.com" onSubmit={handleSubmit}>
<input
type="text"
placeholder="请输入待办事项"
value={text} // 双向绑定:输入框的值和状态 text 绑定
onChange={handleChange} // 输入框内容改变时更新状态
/>
<button type="submit">添加</button>
</form>
)
}
export default TodoForm;
逐行解释
1. useState
和初始化状态
arduino
const [text, setText] = useState('打豆豆');
- 这行代码通过
useState
创建了一个名为text
的状态变量,并使用setText
来更新它。useState('打豆豆')
为text
提供了一个初始值'打豆豆'
,这意味着当表单第一次渲染时,输入框的值是'打豆豆'
。 text
状态用于存储输入框中的内容。
2. 从 props
获取 onAdd
ini
const onAdd = props.onAdd;
- 这行代码从父组件传递来的
props
中获取onAdd
函数。onAdd
是一个回调函数,它会在表单提交时被调用,并将待办事项的文本(text
)传递给父组件。父组件通常会用这个文本来更新其todos
状态。
3. handleSubmit
函数:处理表单提交
scss
const handleSubmit = (e) => {
e.preventDefault(); // 阻止表单的默认提交行为
onAdd(text); // 调用父组件的 onAdd 函数,将文本传递给父组件
}
e.preventDefault()
:阻止表单的默认行为,防止页面刷新。通常,提交表单时浏览器会刷新页面,而e.preventDefault()
可以阻止这个行为,让我们自己控制表单提交的动作。onAdd(text)
:表单提交时,调用onAdd
回调函数,并将text
作为参数传递给它。onAdd
是父组件传递过来的一个函数,用来处理新待办事项的添加操作。
4. handleChange
函数:处理输入框变化
scss
const handleChange = (e) => {
setText(e.target.value); // 更新输入框的状态
}
- 这个函数在用户输入内容时被触发。每当用户在输入框中修改内容,
handleChange
函数会被调用,它会更新text
状态,使得text
始终保持输入框的最新值。 e.target.value
是输入框的当前值,将它传递给setText
函数来更新状态。由于 React 是响应式的,更新状态后,组件会自动重新渲染,确保输入框显示的是最新的值。
5. 表单的 JSX 结构
ini
<form action="http://www.baidu.com" onSubmit={handleSubmit}>
<input
type="text"
placeholder="请输入待办事项"
value={text} // 双向绑定
onChange={handleChange}
/>
<button type="submit">添加</button>
</form>
-
<form action="http://www.baidu.com" onSubmit={handleSubmit}>
: 这是一个表单元素,action="http://www.baidu.com"
是默认的提交行为,但我们通过e.preventDefault()
阻止了这个行为,改为自定义的提交逻辑。 -
<input type="text" placeholder="请输入待办事项" value={text} onChange={handleChange} />
:type="text"
:这表示这是一个文本输入框。placeholder="请输入待办事项"
:输入框内的占位符提示用户输入待办事项。value={text}
:这实现了 React 中的"受控组件"模式。输入框的值与text
状态绑定,即text
的值决定了输入框中显示的内容。onChange={handleChange}
:当用户修改输入框内容时,handleChange
会被调用,更新text
状态。
-
<button type="submit">添加</button>
:这是一个提交按钮,点击时会触发表单的onSubmit
事件,从而调用handleSubmit
函数。
双向绑定
在 React 中,表单控件通常被称为"受控组件"。这里的 双向绑定 是通过 value={text}
和 onChange={handleChange}
实现的:
value={text}
:输入框的值由text
状态来控制,因此输入框的内容总是与text
状态同步。onChange={handleChange}
:当用户修改输入框的内容时,handleChange
会更新text
状态,这样text
状态总是与输入框中的内容保持同步。
小结
useState
管理表单状态 :通过useState
创建了一个状态text
来保存输入框的内容。handleSubmit
阻止表单提交 :通过e.preventDefault()
阻止表单的默认提交行为,改为通过onAdd
调用父组件的回调函数,传递用户输入的待办事项。handleChange
更新状态 :每当输入框的内容发生变化时,handleChange
会更新text
状态,确保text
始终包含输入框中的最新内容。- 受控组件 :通过将输入框的值绑定到
text
状态,确保输入框的内容与状态同步,实现了双向绑定。
通过这种方式,TodoForm
组件有效地管理了用户输入,并将数据通过回调函数传递给父组件,完成了从用户交互到状态更新的整个流程。
总结
通过本文的讲解,我们深入了解了 React 的基本概念、组件化思想、状态管理和响应式界面开发。通过创建一个简单的 Todo List 组件,我们掌握了如何利用 React 构建一个数据驱动的 Web 应用。
React 的强大之处在于其组件化的架构和响应式的 UI 更新机制,使得开发者能够专注于业务逻辑而非 DOM 操作。随着项目的复杂度增加,拆分组件、模块化开发将成为必不可少的技能。掌握这些技能后,我们将能够高效地开发现代 Web 应用,构建出更加灵活、易维护的前端系统。
好啦,朋友们,今天我们的分享就到这里啦!!细节和干货还是拉满了的,有什么需要补充的地方也欢迎各位大佬在评论区指点一下!!