React全家桶笔记(一):React入门 — 虚拟DOM与JSX

1 阅读6分钟

React全家桶笔记(一):React入门 — 虚拟DOM与JSX

本系列笔记基于尚硅谷React全家桶教程整理,适合初学者系统学习React,也可作为面试复习参考。 📺 对应视频:P1 - P7


一、React 简介(P1)

1.1 React 是什么?

React 是 Facebook 开发并开源的一个用于构建 用户界面的 JavaScript 库。

注意关键词:

  • 构建 用户界面 — React 只关注视图层(View),不是一个完整的 MVC 框架
  • JavaScript — 不是框架,是库。框架是全套解决方案,库是解决特定问题的工具

1.2 为什么要学 React?

  • 原生 JS 操作 DOM 繁琐、效率低(DOM-API 操作 UI)
  • 使用 JS 直接操作 DOM,浏览器会进行大量的重绘重排
  • 原生 JS 没有组件化编码方案,代码复用率低

1.3 React 的特点

  • 组件化模式,声明式编码,提高开发效率及组件复用率
  • 在 React Native 中可以用 React 语法进行移动端开发
  • 使用虚拟 DOM + 优秀的 Diffing 算法,尽量减少与真实 DOM 的交互

🔗 概念扩展:声明式 vs 命令式

  • 命令式:告诉计算机"怎么做"(jQuery 就是典型的命令式)
  • 声明式:告诉计算机"要什么"(React/Vue 都是声明式,你描述 UI 长什么样,框架帮你实现)

二、Hello React 案例(P2)

2.1 相关 JS 库

react.development.js       — React 核心库
react-dom.development.js   — React 操作 DOM 的扩展库
babel.min.js               — 将 JSX 转为 JS 的编译器

引入顺序很重要:先引 react 核心库,再引 react-dom。因为 react-dom 依赖 react 核心库。

2.2 第一个 React 程序

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Hello React</title>
</head>
<body>
  <!-- 准备一个容器 -->
  <div id="test"></div>

  <!-- 引入核心库,必须在 react-dom 之前 -->
  <script src="react.development.js"></script>
  <script src="react-dom.development.js"></script>
  <script src="babel.min.js"></script>

  <!-- type 必须写 text/babel,表示这里写的是 JSX -->
  <script type="text/babel">
    // 1. 创建虚拟 DOM
    const VDOM = <h1>Hello, React</h1>
    // 2. 渲染虚拟 DOM 到页面
    ReactDOM.render(VDOM, document.getElementById('test'))
  </script>
</body>
</html>

⚠️ 易错点<script> 标签的 type 必须写 text/babel,否则浏览器会把 JSX 当作普通 JS 解析而报错。


三、虚拟 DOM 的两种创建方式(P3)

3.1 方式一:JSX 创建(推荐)

// JSX 方式 — 简洁直观
const VDOM = (
  <h1 id="title">
    <span>Hello, React</span>
  </h1>
)

3.2 方式二:JS 创建(不推荐)

// 纯 JS 方式 — React.createElement(标签名, 属性, 内容)
const VDOM = React.createElement('h1', { id: 'title' },
  React.createElement('span', {}, 'Hello, React')
)

对比结论

  • JSX 是 React.createElement()语法糖
  • 当结构嵌套复杂时,纯 JS 写法会非常繁琐
  • JSX 更贴近 HTML 的写法,开发体验更好
  • Babel 会把 JSX 编译成 React.createElement() 调用

🔗 概念扩展:语法糖(Syntactic Sugar) 指计算机语言中添加的某种语法,对语言的功能没有影响,但更方便程序员使用。JSX 就是 React.createElement() 的语法糖,本质上做的是同一件事。


四、虚拟 DOM 与真实 DOM(P4)

4.1 虚拟 DOM 本质

const VDOM = <h1>Hello</h1>
console.log(VDOM)          // 输出一个普通的 JS 对象
console.log(typeof VDOM)   // "object"

关键认知

  1. 虚拟 DOM 本质是一个普通的 JavaScript 对象(Object)
  2. 虚拟 DOM 比真实 DOM "轻",因为虚拟 DOM 是 React 内部在用,不需要真实 DOM 上那么多属性
  3. 虚拟 DOM 最终会被 React 转化为真实 DOM,渲染到页面上

4.2 虚拟 DOM vs 真实 DOM

虚拟 DOM:
  { type: 'h1', props: { id: 'title', children: 'Hello' } }
  → 属性很少,很"轻"

真实 DOM:
  一个 <h1> 元素上有几百个属性和方法
  → 非常"重"

🎯 面试高频:虚拟 DOM 的工作流程

  1. 数据变化时,React 用新数据生成新的虚拟 DOM 树
  2. 将新旧两棵虚拟 DOM 树进行 Diff 比较
  3. 找出差异部分,只更新差异部分到真实 DOM
  4. 这就是 React 高效的核心原因 — 最小化 DOM 操作

五、JSX 语法规则(P5-P6)

JSX 全称 JavaScript XML,是 React 定义的一种类似于 XML 的 JS 扩展语法:JS + XML。

5.1 核心语法规则

规则1:定义虚拟 DOM 时,不要写引号

// ✅ 正确
const VDOM = <h1>Hello</h1>

// ❌ 错误 — 加了引号就变成字符串了
const VDOM = '<h1>Hello</h1>'

规则2:标签中混入 JS 表达式时,用花括号 {}

const name = 'React'
const VDOM = <h1>Hello, {name}</h1>

规则3:样式的类名用 className ,不用 class

// ✅ 正确
<div className="title">Hello</div>

// ❌ 错误 — class 是 JS 的保留字
<div class="title">Hello</div>

规则4:内联样式用 style={{key: value}} 的形式

// 注意:外层 {} 表示要写 JS 表达式,内层 {} 是一个对象
// CSS 属性名用小驼峰命名
<div style={{color: 'white', fontSize: '20px'}}>Hello</div>

规则5:只能有一个根标签

// ✅ 正确
const VDOM = (
  <div>
    <h1>标题</h1>
    <p>内容</p>
  </div>
)

// ❌ 错误 — 两个根标签
const VDOM = (
  <h1>标题</h1>
  <p>内容</p>
)

规则6:标签必须闭合

// ✅ 自闭合
<input type="text" />

// ✅ 成对闭合
<div></div>

// ❌ 错误
<input type="text">

规则7:标签首字母

  • 小写字母开头:React 会将其转为 HTML 同名元素。如果 HTML 中没有该标签,就报错
  • 大写字母开头:React 会去渲染对应的组件。如果组件未定义,就报错
<div>这是 HTML 标签</div>
<MyComponent>这是 React 组件</MyComponent>

5.2 JSX 小练习 — 动态渲染列表

const data = ['Angular', 'React', 'Vue']

const VDOM = (
  <div>
    <h1>前端框架列表</h1>
    <ul>
      {
        data.map((item, index) => {
          return <li key={index}>{item}</li>
        })
      }
    </ul>
  </div>
)

ReactDOM.render(VDOM, document.getElementById('test'))

⚠️ 易错点:表达式 vs 语句

  • 表达式:会产生一个值,可以放在任何需要值的地方。如 aa+bfn(1)arr.map()function test(){}
  • 语句:控制代码走向,不会产生值。如 if(){}for(){}switch(){}
  • JSX 的 {} 中只能写表达式,不能写语句!

🎯 面试高频:为什么遍历列表要加 key? key 是虚拟 DOM 的标识,在 Diffing 算法中起关键作用。当数据变化时,React 会根据 key 来判断哪些元素是新增的、哪些是修改的、哪些是删除的,从而最小化 DOM 操作。(后续 Diffing 算法章节会详细展开)


六、组件与模块(P7)

6.1 模块

  • 定义:向外提供特定功能的 JS 程序,一般就是一个 JS 文件
  • 为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂
  • 作用:复用 JS,简化 JS 的编写,提高 JS 运行效率
  • 模块化:当应用的 JS 都以模块来编写,这个应用就是一个模块化的应用

6.2 组件

  • 定义:用来实现局部功能效果的代码和资源的集合(HTML/CSS/JS/图片等)
  • 为什么要用组件:一个界面的功能更复杂
  • 作用:复用编码,简化项目编码,提高运行效率
  • 组件化:当应用是以多组件的方式实现,这个应用就是一个组件化的应用

6.3 模块 vs 组件

模块:侧重于 JS 层面的功能拆分
  → 一个 utils.js、一个 api.js 就是一个模块

组件:侧重于 UI 层面的功能拆分
  → 一个 Header、一个 Footer 就是一个组件
  → 组件包含了 HTML + CSS + JS + 图片等所有资源

🔗 概念扩展:组件化开发的思维方式 拿到一个页面设计稿,第一步不是写代码,而是拆分组件

  1. 哪些部分可以抽成独立组件?
  2. 组件之间是什么关系?(父子、兄弟)
  3. 数据应该放在哪个组件中? 这种"自顶向下拆分"的思维方式,是 React 开发的核心。

本章知识图谱

React 入门
├── React 是什么 → 构建 UI 的 JS 库(非框架)
├── 虚拟 DOM
│   ├── 本质:JS 对象(轻量级的 DOM 描述)
│   ├── 创建方式:JSX(语法糖)/ React.createElement(原始)
│   └── 工作流程:数据变化 → 新虚拟DOM → Diff对比 → 最小化更新真实DOM
├── JSX 语法
│   ├── 不加引号
│   ├── {} 中写 JS 表达式(非语句)
│   ├── className 代替 class
│   ├── style={{}} 双花括号 + 小驼峰
│   ├── 单根标签
│   ├── 标签必须闭合
│   └── 首字母大小写决定是 HTML 标签还是组件
└── 组件与模块
    ├── 模块 → JS 功能拆分
    └── 组件 → UI 功能拆分(HTML+CSS+JS+资源)

📌 下一篇:[React全家桶笔记(二):React组件核心 — State、Props、Refs] 我们将深入 React 组件的三大核心属性,这是 React 开发的基石。