阅读视图

发现新文章,点击刷新页面。

🎉 React 的 JSX 语法与组件思想:开启你的前端‘搭积木’之旅(深度对比 Vue 哲学)

嘿,未来的前端大神们!👋 欢迎来到 React 的世界!如果你正在寻找一个现代、高效、充满乐趣的前端框架,那么恭喜你,你找对地方了!

在 React 中,有两个核心概念你必须掌握:JSX 语法组件化思想。它们不仅是 React 的“招牌”,也是你实现炫酷用户界面的“魔法棒”。

别担心,React 并没有传说中那么“高冷”,只要理解了它的核心哲学,特别是通过与 Vue 等框架的对比,你就会发现这是一个充满乐趣的“搭积木”游戏!

本文将结合一个仿掘金首页的示例,带你一起深入理解 JSX 和组件的魅力,并穿插讲解 React 这种**“All in JavaScript”的纯粹思想与 Vue 的“关注点分离”**哲学有何不同。


🚀 一、现代前端框架的魅力与 React 的“激进”哲学

在深入 JSX 之前,我们先来聊聊 Vue、React 等现代前端框架的共同特点和它们之间的根本区别:

1. 现代框架的共同点

  • 响应式(Reactive):数据(State/状态)发生变化时,UI 界面会自动、高效地同步更新。
  • 数据绑定(Data Binding): 建立数据和 DOM 之间的连接。
  • 组件化(Component-Based):组件为基本开发单位,像搭积木一样来组合页面。

2. React 与 Vue 的哲学差异:关注点如何分离?

尽管都推崇组件化,但在如何组织一个组件内部的职责上,React 和 Vue 采取了截然不同的路径:

特性 React 哲学 (激进) Vue 哲学 (渐进)
关注点分离 技术融合: 关注一个功能/组件的完整性。将模板(UI)、逻辑、样式都写在 JavaScript 文件内。 技术分离: 关注 HTML/CSS/JS 三种技术的传统分工。在一个 .vue 文件中用 <template><script><style> 分块。
模板语法 JSX (XML in JS): 在 JavaScript 中写类似 HTML 的结构。 HTML 扩展:<template> 块中使用标准的 HTML,通过 v-bindv-on 等指令扩展其能力。
入门门槛 相对较高,需要先适应在 JS 中写 UI 的 JSX 语法。 相对较低,接近传统前端开发习惯(HTML 模板)。

🌟 React 的“激进”之处:

React 认为,一个组件的 UI 描述(JSX)、逻辑(JS 代码)和样式(可选的 CSS 模块化)应该紧密地封装在一起,形成一个功能完整的单元。它更推崇**“关注点分离”而非“技术分离”**。实现这一点的核心,就是 JSX


✨ 二、JSX 语法:XML in JavaScript 的魔法

1. 什么是 JSX?(React 的模板语法)

在 React 的世界里,你不再需要一个单独的模板文件来描述 UI。你直接在 JavaScript 代码里写类似 HTML 的结构!这种在 JavaScript 中书写 XML/HTML 结构的语法扩展,就是 JSX (JavaScript XML)

核心定义: JSX 是 React 中用于描述用户界面语法拓展。它本质上是 XML 的一个特定应用,将 UI 描述(原本的 HTML 职责)和逻辑控制(原本的 JS 职责)完美地融合在一起。

在我们的示例代码中,以下两行代码完美地诠释了 JSX 作为语法糖(Syntactic Sugar)的作用:

JavaScript

// 语法糖:用类似 HTML 的 JSX 结构来描述 UI,可读性极高
const element = <h2>JSX 是 React 中用于描述用户界面的语法拓展</h2>;

// 原始写法:使用 React.createElement API,繁琐且可读性差
import { createElement } from 'react'; // 引入 createElement
const element2 = createElement("h2", null, "JSX 是 React 中用于描述用户界面的语法拓展");

结论: JSX 是为了简化模板开发提升代码可读性而生的。在底层,它会被像 Babel 这样的工具编译成 React.createElement() 函数调用,最终创建出 React 元素(Elements)。

2. JSX 与 Vue 模板的对比

特性 React (JSX) Vue (Template)
数据展示 使用 {变量/表达式} 使用 {{ 变量/表达式 }} (双花括号)
类名属性 必须使用 className 使用标准的 class 属性
条件渲染 使用 JavaScript 表达式{condition ? <A/> : <B/>}{condition && <A/>} 使用 特殊指令<p v-if="condition">A</p><p v-else>B</p>
列表渲染 使用 JavaScript 数组方法{list.map((item) => <li key={item.id}>{item.title}</li>)} 使用 特殊指令<li v-for="item in list" :key="item.id">{{ item.title }}</li>

对比总结: Vue 倾向于在 HTML 模板中引入 新的语法和指令(如 v-if, v-for)来实现逻辑控制;而 React (JSX) 则直接利用原生 JavaScript 的强大表现力(如三元运算符、.map() 方法)来实现模板逻辑。这要求开发者对 JavaScript 更加熟悉。

示例:在 JSX 中嵌入 JavaScript 表达式

你可以在 JSX 中使用单花括号 {} 来嵌入任何有效的 JavaScript 表达式

JavaScript

// 在 <span> 标签内嵌入 getname 变量的值
<h1>Hello <span className="title">{getname}!</span></h1>

// 列表渲染:利用 JS 的 .map() 方法和三元表达式进行条件渲染
{
    // 如果 gettodos.length > 0 为真,则渲染 ul 列表,否则渲染 <p>
    gettodos.length > 0 ? (<ul>
        {/* 原生JS react 能不用新语法,就不用。我们直接使用原生 map */}
        {gettodos.map((item) => {
            return (
                // 迭代生成的元素必须要有 key 属性,帮助 React 识别哪些项发生了变化
                <li key={item.id}>
                    {item.title}
                </li>
            )
        })}
    </ul>) : (
        <p>暂无待办事项</p>
    )
}

🏗️ 三、组件化:从“砖头沙子”到“根组件”

1. 以组件为基本单位(组件是函数)

在 React 中,你工作的基本单位不再是孤立的 HTML 元素,而是组件(Component)

简单回答: 返回 JSX 的函数就是组件。

例如,我们的掘金首页示例:

JavaScript

// 函数名(约定以大写字母开头)就是组件名
function JuejinHeader() {
  return (
    // jsx 最外层只能有一个元素
    <div>
      <header>
        <h1>JueJin首页</h1>
      </header>
    </div>
  )
}

// ... 其他子组件
  • App根组件,它渲染了整个页面。
  • 组件树: 这种结构清晰地展示了组件树如何取代传统的 DOM 树,成为我们审查和组织网页结构的主要方式。

2. 根组件的挂载:一切的起点

无论是 React 还是 Vue,应用都需要一个挂载点,即在 HTML 页面中找到一个元素,将整个组件应用渲染进去。React 的现代挂载方式清晰地体现了其纯粹的组件思想

JavaScript

// index.js 或 main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'

// 挂载根组件
// react 一开始就是组件思想,非常的纯粹
const root = document.getElementById('root'); // 1. 找到 HTML 中的挂载点 <div id="root"></div>
createRoot(root).render( // 2. 创建 React 根容器,并调用 render 方法渲染
  <StrictMode>
    <App /> {/* 3. 将根组件 <App /> 渲染到根容器中 */}
  </StrictMode>,
)

代码分析:

  1. createRoot(element):这是 React 18+ 的新 API,用于创建 React 应用程序的根容器,它支持并发渲染(Concurrent Mode)等新特性。
  2. App /> 这就是根组件。可以看到,整个应用的起点就是组件App 组件返回的 JSX 结构,将从这里开始,被 React 渲染成最终的 DOM 结构。
  3. <StrictMode> 严格模式,它不会渲染可见的 UI,但会为它内部的组件(包括 App)启用额外的检查和警告,帮助我们在开发过程中及早发现潜在问题。

🧠 四、组件的“数据之魂”:useState 详解

仅仅会写 UI 描述(JSX)是不够的,一个组件必须能够管理自己的数据状态和业务逻辑。在函数式组件中,我们通过 React Hooks 来实现这些功能,其中最基础的就是 useState

1. useState 的作用与结构

useState Hook 的作用就是为函数组件添加“状态”(State)管理的能力。它接收一个参数(状态的初始值),并返回一个包含两个元素的数组

JavaScript

import { useState } from 'react';

function App() {
    // [当前状态值, 更新状态值的函数] = useState(初始值);
    const [getname, setName] = useState("vue"); 
    const [gettodos, setTodos] = useState([
        // ... 待办事项初始数据
    ]);
    const [isloggedIn, setIsLoggedIn] = useState(true);
    // ...
}

① 数组的第一个元素:状态值(如 getname

它是当前时刻的状态值,用于在 JSX 中展示。

② 数组的第二个元素:更新状态的函数(如 setName

这是一个专用的函数,用于更新状态值

⚠️ 关键点:

  1. 不可直接修改状态值:你必须调用更新函数,例如 setName("react")
  2. 触发重新渲染:当调用这个更新函数时,React 会检测到状态变化,重新执行组件函数(即 App 函数),从而实现响应式更新 UI。

2. useState 与 Vue 响应式数据的对比

特性 React (useState) Vue (Composition API / Setup)
数据定义 const [value, setValue] = useState(initial) const value = ref(initial)
数据访问 直接使用 value 需要使用 value.value (在 <script> 块中)
数据更新 调用专用的更新函数:setValue(newValue) 直接赋值:value.value = newValue
更新机制 组件重新执行 (Re-render) :更新状态后,React 重新渲染整个函数组件。 精确追踪 (Proxy) :Vue 通过 Proxy 机制精确追踪哪些地方使用了数据,只重新渲染使用该数据的部分 DOM。

对比总结: Vueref/reactive劫持数据,更新数据就是直接赋值;而 ReactuseState函数调用,更新状态就是调用一个 setter 函数,触发组件重新渲染。这是两者响应式机制的根本区别。

示例:通过事件更新状态

JavaScript

const toggleLogin = () => {
    // 调用 setIsLoggedIn,传入新值(当前值的反面),触发 App 组件重新渲染
    setIsLoggedIn(!isloggedIn);
}

return (
    <>
      {/* 状态依赖 UI 自动更新 */}
      {isloggedIn?<p>已登录</p>:<p>未登录</p>}
      <button onClick={toggleLogin}> {/* onClick 绑定 JS 函数 */}
          {isloggedIn?"退出登录":"登录"}
      </button>
    </>
)

💻 五、JSX 的底层真相与 createElement 的角色

1. JSX 是什么?

JSX 仅仅是语法糖。它需要被编译(通常由 Babel 完成)才能被浏览器识别。

2. createElement 做了什么?

JSX 的编译目标就是 React.createElement() 函数。

  • JSX 形式:

    JavaScript

    const element = <h2>JSX 是 React 中用于描述用户界面的语法拓展</h2>
    
  • 编译后的原始 React API 形式:

    JavaScript

    // createElement(type, props, ...children)
    const element2 = createElement("h2", null, "JSX 是 React 中用于描述用户界面的语法拓展");
    

createElement 函数的职责是创建出一个 React 元素(React Element) ,这是一个轻量级的 JavaScript 对象,它描述了你希望在屏幕上看到什么。它是 React 应用的骨架,是对真实 DOM 元素用户自定义组件的一种抽象描述。React 拿到这个描述对象后,会根据它来构建和维护虚拟 DOM(Virtual DOM) ,最终高效地将其同步到浏览器的真实 DOM 上。


🔍 六、实战总结:纯粹的组件思想

通过掘金首页的示例,我们再次明确了 React 的开发模式:

  • 核心思想: 一个组件就是 JSX (UI) + 逻辑 (Hooks/状态/事件) 的完整封装。
  • 开发模式: 组件是由 js/css/html 组合起来,完成一个相对独立的功能。我们像搭积木一样将它们组装起来,从根组件 <App /> 开始,由 React 负责最终的渲染。

React 的这种纯粹的组件和 JavaScript 驱动的思想,使得它在处理大型、复杂应用时,逻辑清晰、边界分明。虽然它要求开发者对 JavaScript 更加依赖,但它带来的强大灵活性和可维护性是其最大的优势。


结语

恭喜你,现在你已经掌握了 React 开发的两大核心武器:JSX 语法组件化思想,并且理解了它与 Vue 哲学的主要区别!

  1. JSX 让你能够在 JavaScript 中优雅地描述 UI。
  2. 组件 让你以模块化、可复用的方式构建应用,从根组件开始。
  3. useState 为你的函数组件注入了响应式的数据活力。
  4. React 与 Vue 的对比让你更深刻地理解了框架背后的设计哲学。

React 的旅程才刚刚开始,接下来还有 useEffectuseContext 等更多强大的 Hooks 等待你去探索。记住,多写多练,将每一个 UI 模块都看作一个独立的组件,你很快就能成为一名优秀的 React 开发者!

❌