React 基础
1. React 环境搭建
使用 Vite 创建项目
# 'my-react-app' 可以替换为你想要的任何项目名
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
项目结构
Vite 创建的项目结构如下:
public/
: 存放静态资源,如图片、图标等。此文件夹中的内容在构建时会被直接复制到输出目录。src/
: 存放应用的源代码。main.jsx
: 应用的入口文件。它负责将 React 应用挂载到 HTML 页面上。App.jsx
: 一个示例的根组件。index.css
: 全局 CSS 文件。
index.html
: 应用的 HTML 入口。与传统项目不同,Vite 将index.html
作为应用的中心,脚本通过<script type="module">
标签引入。package.json
: 项目的配置文件,包含依赖项和脚本命令。
入口文件解析 (main.jsx
)
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
import './index.css';
// 1. 使用 ReactDOM.createRoot 创建一个 React 根
// 它指定了 React 应用在哪个 DOM 元素内进行渲染
const root = ReactDOM.createRoot(document.getElementById('root'));
// 2. 使用 root.render() 方法渲染你的应用
// <App /> 就是我们要渲染的 React 组件
// <React.StrictMode> 是一个辅助组件,用于检查应用中潜在的问题
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
2. React 组件
基本概念
React 的核心思想就是组件化。它将复杂的 UI 拆分成独立的、可复用的部分,我们称之为“组件” (Components)。每个组件都可以有自己的逻辑和外观。
在现代 React 中,我们主要使用函数式组件。它就是一个返回 JSX 的 JavaScript 函数。
// src/components/Greeting.jsx
// 这是一个简单的函数式组件
function Greeting() {
// 它返回一个 JSX 元素
return <h1>Hello, World!</h1>;
}
// 导出组件,以便在其他地方使用
export default Greeting;
组件有如下的关键规则:
- 组件名称必须大写:
Greeting
而不是greeting
。React 通过首字母大小写来区分是 React 组件还是普通的 HTML 标签。 - 组件必须返回一个元素: 组件必须返回单个 JSX 元素。如果想返回多个元素,需要用一个父元素(如
<div>
)或 Fragment (<>...</>
) 包裹起来。
组合组件:import
和 export
组件的强大之处在于它们的可组合性。我们可以通过 import
和 export
机制来组织和复用组件。
导出 (Export)
- 默认导出 (
export default
): 每个文件只能有一个默认导出。这是最常见的导出组件的方式。// Greeting.jsx function Greeting() { /* ... */ } export default Greeting;
- 命名导出 (
export
): 每个文件可以有多个命名导出。导入时需要使用花括号{}
并且名称必须匹配。// Helpers.js export function helperOne() { /* ... */ } export const PI = 3.14;
导入 (Import)
- 导入默认导出:
// App.jsx import MyGreetingComponent from './components/Greeting.jsx';
- 导入命名导出:
// App.jsx import { helperOne, PI } from './Helpers.js';
现在,我们可以将我们创建的 Greeting
组件用到 App.jsx
中:
// src/App.jsx
import Greeting from './components/Greeting.jsx';
function App() {
return (
<div>
<h1>My Application</h1>
<Greeting /> {/*像 HTML 标签一样使用组件*/}
</div>
);
}
export default App;
3. JSX
JSX 基本概念
JSX 是 JavaScript 的语法扩展,它允许你在 JavaScript 代码中编写类似 HTML 的结构。虽然不是必须的,但它让编写 React 组件变得极其直观和简洁。
本质上,JSX 只是 React.createElement(component, props, ...children)
函数的语法糖。我们写的每一个 JSX 标签最终都会被 Babel 这样的编译器转换为一个普通的 JavaScript 对象。
// 这段 JSX...
const element = <h1 className="greeting">Hello, world!</h1>;
// ...会被 Babel 这样的编译器转换为:
const element = React.createElement('h1', {className: 'greeting'}, 'Hello, world!');
使用 JSX 的主要好处是它允许我们将渲染逻辑和 UI 结构自然地放在同一个地方——组件中,这使得代码更易于理解和维护。
JSX 的核心规则
直接将 HTML 复制到 JSX 中通常是行不通的,因为 JSX 有自己的一套规则。
- 必须返回单个根元素:一个组件返回的 JSX 必须被一个单独的父标签包裹。如果不想在 DOM 中添加额外的
<div>
,可以使用Fragment (<></>
)。
// 正确:使用 Fragment 包裹
function App() {
return (
<>
<h1>Example h1</h1>
<h2>Example h2</h2>
</>
);
}
// 错误:返回了两个顶级元素
/*
function App() {
return (
<h1>Example h1</h1>
<h2>Example h2</h2>
);
}
*/
- 必须闭合所有标签:在 HTML 中,像
<input>
或<li>
这样的标签可以不闭合。但在 JSX 中,所有标签都必须显式闭合。对于自闭合标签,在末尾加上/
即可。
// 正确
function Form() {
return (
<>
<input type="text" />
<ul>
<li>Item 1</li>
</ul>
</>
);
}
// 错误
/*
function Form() {
return (
<>
<input type="text">
<li>Item 1
</>
);
}
*/
- 使用驼峰命名法 (camelCase) 定义属性:因为 JSX 最终会转换为 JavaScript 对象,而对象的键不能包含破折号或 JavaScript 的保留字(如
class
)。因此,大多数 HTML 属性在 JSX 中需要使用驼峰命名法。
class
变为className
stroke-width
变为strokeWidth
onclick
变为onClick
// 正确
function MyComponent() {
return <div className="container" onClick={() => console.log('Clicked!')} />;
}
// 错误
/*
function MyComponent() {
return <div class="container" onclick="alert('hello')"></div>;
}
*/
在 JSX 中使用 JavaScript
JSX 的真正威力在于它能够与 JavaScript 无缝集成。我们可以使用花括号 {}
将 JavaScript 逻辑嵌入到你的标记中。
- 引用变量:我们可以将任何 JavaScript 变量(字符串、数字、数组等)直接渲染到 UI 中。
const userName = "Ada Lovelace";
function Profile() {
return <h1>Welcome, {userName}!</h1>;
}
- 在属性中使用:花括号也可以用于动态设置属性。
const avatarUrl = 'https://i.imgur.com/7vQD0fPs.jpg';
function Avatar() {
return <img src={avatarUrl} alt="User Avatar" />;
}
- 调用函数和使用表达式:我们可以在花括号内放置任何有效的 JavaScript 表达式,比如函数调用、三元运算符或数组方法。
function ShoppingList() {
const items = ['Apple', 'Banana', 'Cherry'];
return (
<ul>
{items.map(item => <li key={item}>{item}</li>)}
</ul>
);
}
- “双花括号” 与内联样式:在 JSX 中为元素添加内联样式时,有时会看到
style={{}}
这样的语法。这并不是什么特殊的语法,而是“在花括号内传入一个 JavaScript 对象”。
- 第一个花括号
{}
: 表示我们要嵌入一个 JavaScript 表达式。 - 第二个花括号
{}
: 表示我们传入的表达式本身是一个样式对象。
样式对象的属性也必须使用驼峰命名法。
function Panel() {
return (
<div style={{
backgroundColor: 'black',
color: 'pink',
fontSize: '16px'
}}>
This is a styled panel.
</div>
);
}