React 从零入门:组件化开发与状态管理实战指南

44 阅读7分钟

什么是 React?

React 是由 Facebook(现在的 Meta)开发的一个用于构建用户界面的 JavaScript 库。它的核心思想是组件化开发,让我们可以像搭积木一样组合组件来构建网页。

React 的特点

  • 组件化:将页面拆分成独立的、可复用的组件
  • 声明式:只需要描述 UI 应该是什么样子,React 会自动更新
  • 高效:使用虚拟 DOM 技术,只更新变化的部分

1. React 项目结构

入口文件:main.jsx

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

// 挂载根组件
// react 一开始就是组件思想,非常的纯粹
createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

解释:

  • main.jsx 是应用的入口文件
  • createRoot 创建一个 React 根节点
  • render 方法将组件渲染到页面上
  • <App /> 是我们的根组件,所有其他组件都是它的子组件
  • StrictMode 是 React 的严格模式,帮助我们发现潜在问题

2. 什么是 JSX?

JSX 是 JavaScript XML 的缩写,它是 React 中用于描述用户界面的语法扩展。

JSX 文件后缀

在 React 中,我们使用 .jsx 作为文件后缀(也可以使用 .js,但 .jsx 更明确表示这是 React 组件)。

JSX 的本质

JSX 主要是为了简化模板开发,提升代码的可读性。它看起来像 HTML,但实际上是 JavaScript。

// JSX 写法(推荐)
const element = <h2>JSX 是React 中用于描述用户界面的语法扩展</h2>

// 等价于原生 JavaScript(不推荐)
const element2 = createElement('h2', null, 'JSX 是React 中用于描述用户界面的语法扩展')

JSX 的优势:

  • 更直观,像写 HTML 一样
  • 更容易理解和维护
  • 编译时会自动转换成 JavaScript

JSX 的规则

  1. 最外层只能有一个元素

    //  正确:用一个 div 包裹
    return (
      <div>
        <h1>标题</h1>
        <p>内容</p>
      </div>
    )
    
    //  错误:两个并列的元素
    return (
      <h1>标题</h1>
      <p>内容</p>
    )
    
  2. 使用 Fragment(文档碎片)包裹多个元素

    //  使用 <> </> 包裹(推荐)
    return (
      <>
        <h1>标题</h1>
        <p>内容</p>
      </>
    )
    
  3. 使用 className 而不是 class

    //  正确
    <div className="title">Hello</div>
    
    //  错误(class 是 JavaScript 关键字)
    <div class="title">Hello</div>
    
  4. 使用大括号 {} 嵌入 JavaScript 表达式

    const name = "React"
    return <h1>Hello {name}</h1>  // 输出:Hello React
    

3. 组件(Component)

什么是组件?

组件是由 js/css/html 组合起来,完成一个相对独立的功能。

组件是 React 开发的基本单位。函数将 JSX + 逻辑封装成一个组件,JSX 负责 UI(用户界面)。

组件的定义方式

方式一:函数声明(推荐)

function App() {
  return <h1>Hello React</h1>
}

方式二:箭头函数

const App = () => {
  return <h1>Hello React</h1>
}

注意: 在 React 中,函数就是组件。JavaScript 没有 class(虽然 ES6 有,但 React 推荐使用函数组件)。

组件的特点

  • 返回 JSX 的函数就是 组件
  • 组件可以像 HTML 标签一样使用
  • 组件可以组合:大组件由小组件组成,形成组件树

4. 组件化开发 - 像搭积木一样

传统前端开发 vs React 开发

传统前端:

  • HTML 标签、CSS 规则是开发的基本单位
  • 就像建筑里的砖头和沙子

React 开发:

  • 组件是开发的基本单位
  • 就像包工头,先分工(组件化),然后组件组合起来组成网页
  • 组件化让我们像搭积木一样组合成页面

实际例子:组件组合

// 头部组件
function JuejinHeader() {
  return (
    <div>
      <header>
        <h1>JueJin首页</h1>
      </header>
    </div>
  )
}

// 文章列表组件
const Articles = () => {
  return (
    <div>
      Articles
    </div>
  )
}

// 签到组件
const Checkin = () => {
  return (
    <div>
      Check in 
    </div>
  )
}

// 热门文章组件
const TopArticles = () => {
  return (
    <div>
      TopArticles
    </div>
  )
}

// 根组件:组合所有子组件
function App2() {
  return (
    <div>
      {/* 头部组件 */}
      <JuejinHeader />
      <main>
        {/* 组件也和html一样声明,自定义组件 */}
        {/* 组件化让我们像搭积木一样组合成页面 */}
        <Articles />
        <aside>
          <Checkin />
          <TopArticles />
        </aside>
      </main>
    </div>
  )
}

说明:

  • 每个组件负责一个独立的功能
  • 在根组件中,我们可以像使用 HTML 标签一样使用自定义组件
  • <JuejinHeader /> 就是使用我们定义的组件

5. 状态管理 - useState

什么是状态(State)?

State(状态) 是组件的数据。当状态改变时,React 会自动更新页面。

useState Hook

useState 是 React 提供的一个 Hook(钩子函数),用于在函数组件中添加状态。

import { useState } from 'react'

function App() {
  // useState 返回一个数组:[状态值, 更新状态的函数]
  const [name, setName] = useState("vue")
  
  return <h1>Hello {name}</h1>
}

解释:

  • useState("vue") 创建一个初始值为 "vue" 的状态
  • name 是当前状态的值
  • setName 是更新状态的函数
  • 当调用 setName("react") 时,name 会变成 "react",页面会自动更新

多个状态

一个组件可以有多个状态:

function App() {
  const [name, setName] = useState("vue")
  const [isLoggedIn, setIsLoggedIn] = useState(false)
  const [todos, setTodos] = useState([
    {
      id: 1,
      title: "学习react",
      done: false,
    },
    {
      id: 2,
      title: "学习node",
      done: false,
    }
  ])
  
  // ...
}

状态更新示例

// 3秒后自动更新状态
setTimeout(() => {
  setName("react")
}, 3000)

当 3 秒后执行 setName("react") 时,页面上的 {name} 会自动从 "vue" 变成 "react"。


6. 事件处理

事件处理函数

在 React 中,事件处理使用 onClickonChange 等属性(注意是驼峰命名)。

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false)
  
  // 定义事件处理函数
  const toggleLogin = () => {
    setIsLoggedIn(!isLoggedIn)  // 切换登录状态
  }
  
  return (
    <button onClick={toggleLogin}>
      {isLoggedIn ? "退出登录" : "登录"}
    </button>
  )
}

重要提示:

  • 使用 onClick 而不是 onclick(React 使用驼峰命名)
  • 事件处理函数用大括号包裹:onClick={toggleLogin}
  • 不要加括号:onClick={toggleLogin} 而不是 onClick={toggleLogin()}

7. 条件渲染

条件渲染就是根据条件决定显示什么内容。

三元运算符

{isLoggedIn ? <div>已登录</div> : <div>未登录</div>}

解释:

  • 如果 isLoggedIntrue,显示 "已登录"
  • 如果 isLoggedInfalse,显示 "未登录"

逻辑与运算符

{todos.length > 0 ? (
  <ul>
    {/* 列表内容 */}
  </ul>
) : (
  <div>暂无待办事项</div>
)}

解释:

  • 如果 todos.length > 0(有待办事项),显示列表
  • 否则显示 "暂无待办事项"

8. 列表渲染

使用 map 方法渲染列表。

const [todos, setTodos] = useState([
  {
    id: 1,
    title: "学习react",
    done: false,
  },
  {
    id: 2,
    title: "学习node",
    done: false,
  }
])

return (
  <ul>
    {todos.map((todo) => (
      <li key={todo.id}>
        {todo.title}
      </li>
    ))}
  </ul>
)

重要提示:

  • 使用 map 方法遍历数组
  • 必须给每个列表项添加 key 属性,且 key 应该是唯一的(通常使用 id
  • key 帮助 React 识别哪些项改变了,提高渲染效率

9. 完整示例

让我们看一个完整的组件示例:

import { useState, createElement } from 'react'
import './App.css'

function App() {
  // 状态定义
  const [name, setName] = useState("vue")
  const [isLoggedIn, setIsLoggedIn] = useState(false)
  const [todos, setTodos] = useState([
    {
      id: 1,
      title: "学习react",
      done: false,
    },
    {
      id: 2,
      title: "学习node",
      done: false,
    }
  ])
  
  // 3秒后更新 name
  setTimeout(() => {
    setName("react")
  }, 3000)
  
  // 事件处理函数
  const toggleLogin = () => {
    setIsLoggedIn(!isLoggedIn)
  }
  
  // JSX 元素
  const element = <h2>JSX 是React 中用于描述用户界面的语法扩展</h2>
  
  return (
    // 使用 Fragment 包裹多个元素
    <>
      {element}
      <h1>Hello <span className="title">{name}</span></h1>
      
      {/* 条件渲染:列表 */}
      {todos.length > 0 ? (
        <ul>
          {todos.map((todo) => (
            <li key={todo.id}>
              {todo.title}
            </li>
          ))}
        </ul>
      ) : (
        <div>暂无待办事项</div>
      )}
      
      {/* 条件渲染:登录状态 */}
      {isLoggedIn ? <div>已登录</div> : <div>未登录</div>}
      
      {/* 事件处理 */}
      <button onClick={toggleLogin}>
        {isLoggedIn ? "退出登录" : "登录"}
      </button>
    </>
  )
}

export default App

image.png

10. 总结

React 的核心概念

  1. 组件化:将页面拆分成独立的组件
  2. JSX:用类似 HTML 的语法写 JavaScript
  3. 状态管理:使用 useState 管理组件数据
  4. 事件处理:使用 onClick 等属性处理用户交互
  5. 条件渲染:根据条件显示不同内容
  6. 列表渲染:使用 map 渲染数组数据

React 开发流程

  1. 设计组件结构:将页面拆分成组件
  2. 定义组件:用函数定义每个组件
  3. 添加状态:使用 useState 管理数据
  4. 处理交互:添加事件处理函数
  5. 组合组件:在根组件中组合所有子组件

常见问题

为什么 React 使用 JSX?

A: JSX 让代码更直观,像写 HTML 一样,提升代码可读性。它会被编译成 JavaScript。

组件必须返回 JSX 吗?

A: 是的,组件必须返回 JSX(或 null)。返回 JSX 的函数就是组件。

什么时候使用 useState?

A: 当你需要存储会变化的数据,并且希望数据变化时页面自动更新,就使用 useState。

key 属性为什么重要?

A: key 帮助 React 识别列表中的每个元素,当列表变化时,React 可以高效地更新 DOM。