React 核心概念:JSX、组件与数据驱动

一、前言:React 解决了什么根本问题?

回顾一下传统前端(jQuery 时代)的代码:

javascript 复制代码
// 一个计数器------你需要手动描述每一步 DOM 操作
$('#btn').on('click', function() {
  let count = parseInt($('#result').text()) || 0
  count++                                    // 数据变了
  $('#result').text(count)                   // 手动更新 DOM
  if (count > 10) {
    $('#result').css('color', 'red')         // 手动改样式
  }
})

这段代码有一个根本问题:数据存在 DOM 里。整个应用的真实状态分散在数十个 DOM 节点中,没有任何一个地方能完整地回答"当前页面处于什么状态?"。

React 提出了一种完全不同的思考方式:

tsx 复制代码
function Counter() {
  const [count, setCount] = useState(0)     // 数据是"一等公民"
  
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>点击</button>
      <div className={count > 10 ? 'text-red-500' : ''}>
        {count}                              // 数据变了,界面自动变
      </div>
    </div>
  )
}

React 的核心承诺:你只需要描述每个状态下界面长什么样,当数据变化时,React 负责让界面跟上。你不需要知道 DOM 是怎么更新的。

二、JSX:在 JavaScript 里写 HTML

JSX 是什么?

tsx 复制代码
// 你写的 JSX
const element = <h1 className="title">Hello, {name}!</h1>

// 编译后等价于 ------
const element = React.createElement(
  'h1',
  { className: 'title' },
  'Hello, ',
  name,
  '!'
)

JSX = React.createElement() 的语法糖

JSX 不是 HTML,不是模板字符串,不是一门新语言。它就是 JavaScript------用 HTML 的书写方式来描述 UI 结构,然后在编译时被转换成纯函数调用。

三条核心规则

tsx 复制代码
// 规则1:{} 内可以写任意 JS 表达式
<div>{isLoggedIn ? `欢迎, ${user.name}` : '请登录'}</div>
<div>{items.map(item => <li key={item.id}>{item.text}</li>)}</div>

// 规则2:className 不是 class
// 因为 class 是 JavaScript 的保留关键字
<div className="flex items-center">

// 规则3:每个 JSX 标签 = 一个 Virtual DOM 节点
// 多个节点组合 = 一棵 Virtual DOM 树

TSX:带类型的 JSX

如果你的项目使用 TypeScript,文件后缀就是 .tsx

tsx 复制代码
// .tsx 文件:TypeScript + JSX
// 你可以享受完整的类型检查 + JSX 语法

interface ButtonProps {
  label: string;
  onClick: () => void;
  variant?: 'primary' | 'secondary';
}

function Button({ label, onClick, variant = 'primary' }: ButtonProps) {
  // ...
}

三、组件:UI 的基本单元

一个函数就是一个组件

React 组件的独特之处在于------一个函数就是一个组件

tsx 复制代码
function App() {
  // ─── ① 逻辑区:return 之前 ───
  // 数据定义、状态管理、事件处理、副作用注册
  const [status, setStatus] = useState(null)
  const [error, setError] = useState(null)

  // ─── ② UI 区:return 之后 ───
  // JSX 描述界面长什么样,用 {} 引用逻辑区的变量
  return (
    <div className="flex flex-col h-screen mx-auto items-center justify-center">
      {error ? (
        <div className="text-red-500">{error}</div>
      ) : (
        <h1 className="text-4xl font-bold">一切正常</h1>
      )}
    </div>
  )
}

// ─── ③ 样式 ───
// Tailwind class 直接写在 className 上,或者 import CSS 文件

组件的核心公式

ini 复制代码
UI = f(state + props)

  组件函数  = f()
  state    = 内部数据(useState)
  props    = 外部输入(父组件传入)
  UI       = return 返回的 JSX

这个公式的含义

  • 相同的 state + props 一定产生相同的 UI(可预测)
  • 状态变了,UI 自动跟上(数据驱动)
  • 你可以像测试纯函数一样测试组件

组件首字母必须大写

tsx 复制代码
// ✅ 这是组件(首字母大写)
function App() { return <div>...</div> }
<App />

// ❌ 这是普通 HTML 标签
function app() { return <div>...</div> }
<app />  // React 会将 <app /> 当作原生 HTML 标签处理

四、数据驱动:声明式 vs 命令式

这是 React 相对于传统前端开发最本质的区别:

erlang 复制代码
传统方式(jQuery/原生JS)           React 方式
─────────────────────────          ─────────────────────────
命令式 (How)                       声明式 (What)

描述"怎么做":                      描述"是什么":
"找到 #result 元素,                  "当 count = 5 时,
 把内容改成 5,                      这个 div 的文本就是 5,
 再修改颜色为红色"                    颜色自动变红"

一个操作 = 一串步骤                   一个状态 = 一个界面

一个对比案例

假设做一个搜索功能:

传统方式(你需要手动管理每一步):

javascript 复制代码
// 监听输入
$('#search').on('input', function(e) {
  const keyword = e.target.value
  
  // 发起请求
  $.get('/api/search', { keyword }, function(results) {
    // 手动更新 UI
    $('#results').empty()
    if (results.length === 0) {
      $('#results').append('<li>无结果</li>')
    } else {
      results.forEach(r => $('#results').append(`<li>${r.title}</li>`))
    }
    // 手动处理 loading 状态
    $('#loading').hide()
  })
  
  // 手动显示 loading
  $('#loading').show()
})

React 方式(你只描述每个状态):

tsx 复制代码
function Search() {
  const [keyword, setKeyword] = useState('')
  const [results, setResults] = useState([])
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    if (!keyword) return
    setLoading(true)
    fetch(`/api/search?keyword=${keyword}`)
      .then(r => r.json())
      .then(data => {
        setResults(data)
        setLoading(false)
      })
  }, [keyword])

  return (
    <div>
      <input value={keyword} onChange={e => setKeyword(e.target.value)} />
      {loading && <div>搜索中...</div>}
      {!loading && results.length === 0 && <div>无结果</div>}
      <ul>
        {results.map(r => <li key={r.id}>{r.title}</li>)}
      </ul>
    </div>
  )
}

关键区别:React 版本中,你不需要关心 DOM 在什么时机更新、怎么更新------你只需要定义"每个状态下界面是什么样"。

五、Virtual DOM:界面更新的"调度器"

为什么不直接操作真实 DOM?

真实 DOM 操作很昂贵。每改一个节点的内容,浏览器要做大量工作:重新计算布局、重绘、合成图层。

React 的做法:

scss 复制代码
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  1. 你的代码  │ →  │  2. Virtual  │ →  │  3. Diff    │
│  setCount(5) │    │  DOM 重新生成 │    │  新旧对比    │
└─────────────┘     └─────────────┘     └─────────────┘
                                               │
                                               ▼
                                        ┌─────────────┐
                                        │  4. 最小更新  │
                                        │  只改变化部分  │
                                        └─────────────┘

Virtual DOM 不是让 React 更快,而是让 React 在大多数情况下"够快",同时让你不必手动优化 DOM 操作。

六、TypeScript + React:类型安全的最佳实践

你的项目使用 TypeScript,它和 React 的配合非常自然:

tsx 复制代码
// 定义 Props 类型
interface AppState {
  status: 'loading' | 'ready' | 'error' | null
  error: string | null
  loadingMessage: string
}

function App() {
  // TypeScript 自动推断类型
  const [status, setStatus] = useState<AppState['status']>(null)
  const [error, setError] = useState<AppState['error']>(null)

  // 如果你尝试 setStatus(123),TypeScript 会直接报错
  // Type 'number' is not assignable to type...
}

TypeScript + React 的价值

  • 组件的 props 有明确类型,传错了 IDE 立刻标红
  • 重构组件时,TypeScript 告诉你所有需要同步修改的地方
  • 团队协作时,代码就是文档(看接口定义就知道怎么用)

七、总结

概念 一句话
JSX 在 JS 里写 HTML,编译为 React.createElement()
TSX JSX + TypeScript 类型检查
组件 一个返回 JSX 的函数 = HTML + CSS + JS 的封装
数据驱动 UI = f(state),描述状态而非操作步骤
Virtual DOM JS 层面的 UI 树,Diff 后最小化更新真实 DOM
声明式 "当 count=5 时界面长这样",而非"先改文字再改颜色"

React 的根本价值不在于性能或语法,而在于它把 UI 开发从过程式思维 (找到元素 → 改属性 → 改内容)转变为声明式思维(这个状态下的界面长这样)。这是心智模型的彻底转变。

相关推荐
触底反弹2 小时前
🔥 React 零基础入门(中):500 行屎山代码到组件化的蜕变
前端·javascript·react.js
不好听6132 小时前
React vs Vue:两大前端框架技术选型深度对比
前端·vue.js·react.js
GuWenyue2 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
GuWenyue2 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
小林ixn3 小时前
从 onclick 到 React 合成事件,再到完整应用逻辑:一次前端架构的深度剖析
前端·react.js·前端框架
Csvn4 小时前
🧩「找不到模块」排查全记录——Monorepo 下 TypeScript 路径别名的 5 种「不通」与根治方案
前端
腻害兔4 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
CodexDave4 小时前
MySQL事务隔离级别与MVCC机制解析
前端·数据库·mysql·nginx·性能优化·负载均衡
Ai_easygo5 小时前
AI Agent开发入门——从ReAct到Tool Calling,拆解Agent的底层运行逻辑
前端·人工智能·react.js