【React-1/Lesson67(2025-12-12)】React 从零到一:组件化思想与 JSX 实战详解🧱

11 阅读5分钟

🧱在现代前端开发中,React 凭借其纯粹的组件化思想声明式编程范式,成为构建用户界面的事实标准之一。本文将深入剖析 React 的核心理念、JSX 语法本质、状态管理机制、样式处理方式以及项目结构组织,并结合实际代码示例,全面还原一个典型 React 应用的构建过程。


🧠 组件化:React 的灵魂所在

React 最根本的哲学是“一切皆组件”。不同于传统前端将 HTML、CSS、JavaScript 分离开发的方式,React 将 UI 拆解为一个个可复用、可组合、职责单一的组件单元。

💡 组件 = 封装了 UI(JSX) + 逻辑(JavaScript) + 样式(CSS)的功能模块

App.jsx 文件中,我们可以清晰地看到这一思想的体现:

function JuejinHeader() {
  return (
    <header>
      <h1>JueJin首页</h1>
    </header>
  )
}

const Articles = () => { return <div>Articles</div> }
const Checkin = () => { return <div>Checkin</div> }
const TopArticles = () => { return <div>TopArticles</div> }

function App() {
  return (
    <div>
      <JuejinHeader />
      <main>
        <Articles />
        <aside>
          <Checkin />
          <TopArticles />
        </aside>
      </main>
    </div>
  )
}

这里,App 是根组件,它不再直接编写冗长的 HTML 结构,而是通过组合子组件(如 JuejinHeader, Articles 等)来构建页面。这种“搭积木”式的开发方式极大提升了代码的可维护性、可读性和复用性

📌 函数即组件:在 React 中,只要一个函数返回有效的 JSX,它就是一个组件。首字母大写是约定俗成的规范,用于区分原生 HTML 标签(如 div)和自定义组件(如 Articles)。


✨ JSX:JavaScript 中的 XML 扩展

JSX(JavaScript XML)是 React 的核心语法扩展,它允许我们在 JavaScript 代码中直接书写类似 HTML 的结构。

🔥 JSX 不是字符串,也不是 HTML,它是 React.createElement() 的语法糖!

App2.jsx 中,有这样一段对比代码:

const element = <h2>JSX 是 React 中用于描述用户界面的语法扩展</h2>;
const element2 = createElement(
  'h2',
  null,
  'JSX 是 React 中用于描述用户界面的语法扩展'
);

这两行代码在功能上是完全等价的。JSX 在编译阶段会被 Babel 等工具转换为 React.createElement() 调用,最终生成一个描述 UI 结构的虚拟 DOM 对象

JSX 的关键规则:

  • 必须有一个根元素:多个同级元素需要用 <></>(Fragment)包裹。
  • 属性使用 camelCase:如 className 代替 classonClick 代替 onclick
  • 表达式用 {} 包裹:可以在 JSX 中嵌入 JavaScript 表达式,如 {name}{isLoggedIn ? '已登录' : '未登录'}
  • 列表渲染需加 key:在 App2.jsx 的待办事项列表中,key={todo.id} 是必须的,它帮助 React 高效地识别哪些元素发生了变化、被添加或删除。

🧬 状态(State)驱动视图更新

React 的响应式能力源于其状态(State)管理机制。当状态发生变化时,React 会自动重新渲染相关组件,实现“数据驱动视图”。

useState 是 React 提供的最基础的 Hook,用于在函数组件中声明和更新状态。

App2.jsx 中,我们看到了三个典型的状态声明:

const [name, setName] = useState("vue");
const [todos, setTodos] = useState([
  { id: 1, title: "学习vue", done: false },
  // ...
]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
  • name 是一个字符串状态,3 秒后通过 setName("react") 更新。
  • todos 是一个对象数组状态,用于渲染待办事项列表。
  • isLoggedIn 是一个布尔值状态,控制登录状态的显示。

⚠️ 注意setTimeout 直接写在函数组件体内是不推荐的做法,因为它会在每次渲染时都创建一个新的定时器。正确的做法是将其放在 useEffect Hook 中。但此处仅为演示状态更新的效果。

状态更新是不可变的(immutable) 。例如,要修改 todos,不能直接操作数组,而应使用 setTodos([...newTodos]) 创建一个新数组。


🎨 样式与主题:从全局到局部

React 应用的样式可以通过多种方式管理,从全局 CSS 到 CSS-in-JS。

全局样式 (index.css)

index.css 定义了应用的基础样式和主题:

  • 使用 :root 设置了深色/浅色模式下的颜色变量。
  • body 设置了背景图片 url('./assets/image2.png') 并配置了 background-size: cover 等属性,确保背景完美适配。
  • 定义了按钮、链接等通用元素的样式,并包含了 @media (prefers-color-scheme: light) 媒体查询以支持系统主题自动切换。

局部样式 (App.css)

App.css 则更专注于特定组件的样式:

  • #root 限制了内容的最大宽度并设置了内边距。
  • .title 类将文字颜色设为红色,在 App2.jsx 中被用于高亮显示 name 变量。
  • 还包含了一些动画效果(如 logo 旋转)和响应式设计。

🌈 CSS Modules / Styled Components:对于大型项目,通常会采用更高级的 CSS 封装方案来避免样式冲突,但本例展示了最基础的全局+局部 CSS 组合。


🚀 应用入口与渲染流程

一个 React 应用的启动始于 main.jsx

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
  • createRoot 是 React 18 引入的新并发渲染 API 的入口。
  • StrictMode 是一个用于高亮潜在问题的工具(如不安全的生命周期、过时的 API 使用等),仅在开发模式下生效。
  • App 组件被挂载到 index.html 中 id 为 root 的 DOM 节点上。

🔧 注释掉的代码:文件中还保留了切换到 App2.jsx 的代码,这表明开发者可以在不同版本的根组件之间快速切换进行测试。


📖 总结:框架不重要,思想才重要

正如 readme.md 中所强调的:“框架不重要,思想才重要”。React 的真正价值在于它带来的工程化思维

  1. 组件化:将复杂 UI 拆解为独立、可复用的单元。
  2. 声明式:只需描述“UI 应该是什么样子”,而不必关心“如何一步步操作 DOM”。
  3. 单向数据流:数据从父组件流向子组件,状态集中管理,逻辑清晰。
  4. 虚拟 DOM:通过高效的 diff 算法,最小化真实 DOM 操作,提升性能。

通过以上对 main.jsxindex.cssApp.jsxApp2.jsxApp.cssreadme.md 的深度解析,我们不仅看到了一个 React 应用的骨架,更理解了其背后的设计哲学。掌握这些核心概念,是迈向高效、健壮前端开发的关键一步。🚀