从原生JavaScript到React深入理解

作者:白露

时间:2026-10-25

浏览:132

本文深入解析React框架的核心原理,对比原生JavaScript DOM操作与React的虚拟DOM机制。通过React.createElement和JSX语法示例,详细阐述组件创建、属性传递及渲染流程,帮助开发者理解React如何简化Web应用开发并提升代码可维护性。

文章目录

深入解析 React:从原生 JavaScript 起步

作者:Stéphane Bégaudeau

原文链接 https://www.sbegaudeau.com/2018/10/01/from-vanilla-javascript-to-react.html

React 是构建用户界面的 JavaScript 框架,旨在通过动态操作页面内容来开发 Web 应用。尽管浏览器已提供 DOM API 来创建元素,但理解 React 的价值及其与 DOM 的关联至关重要。

原生 JavaScript 与 DOM 交互

JavaScript 提供了全局作用域下的对象和函数以构建应用。在 Web 环境中,开发者可直接访问文档对象模型 (DOM) API;而在 Node.js 等非浏览器环境中,则需导入如 JSDOM 等替代实现。

DOM 提供了操作 HTML 文档的 API,允许以任意方式修改页面结构。通过全局document对象,开发者即可开始使用这些功能。

从document对象出发,开发者可以便捷地创建新元素、修改属性,并将其作为子元素添加到其他节点中。借助 DOM,即便过程繁琐,也能以编程方式生成任何 HTML 文档。

以下示例展示了如何在 HTML 文档中通过编程方式创建一个简单的标题元素。

<!DOCTYPE html>
<html>
  <head>
    <script src="app.js"></script>
  </head>
  <body>
    <div id="app" />
  </body>
</html>

具体操作是创建一个 h1 元素,并将其插入到 HTML 页面的 body 中。

// The document object is accessible since it is in the global scope
const h1Element = document.createElement('h1');
h1Element.setAttribute('class', 'title');
const textElement = document.createTextNode('I am Groot');
h1Element.appendChild(textElement);
// document.getElementById('app') will retrieve the div with the identifier app
document.getElementById('app').appendChild(element);

上述代码首先创建了一个新元素,随后向该 h1 元素添加了一个名为 class、值为title的属性。接着,代码创建了一个文本节点,内容为 'I am Groot',并将其作为子元素添加到 h1 中。最后,通过 HTML 文档获取 id 为 app 的 div 节点,将 h1 标签追加其中。执行该代码后,生成的 HTML 文档结构如下所示:

<!DOCTYPE html>
<html>
  <head>
    <script src="app.js"></script>
  </head>
  <body>
    <div id="app">
      <h1 class="title">I am Groot</h1>
    </div>
  </body>
</html>

利用 DOM,开发者还可通过 className 属性直接操作元素的类名(因为 class 是 JavaScript 的保留字)。因此,以下代码能产生完全相同的效果。

const h1Element = document.createElement('h1');
// h1Element.setAttribute('class', 'title');
h1Element.className = 'title';
const textElement = document.createTextNode('I am Groot');
h1Element.appendChild(textElement);
document.getElementById('app').appendChild(element);

React 核心机制解析

多数 React 教程直接展示其高级用法。本文采取不同策略,从编写通常不再手动维护的 React 代码入手,以深入理解其工作原理。

React 的设计初衷是服务于 Web 场景,其部分 API 设计灵感源自 DOM。为阐明这一点,我们将探讨 React 的核心 API 之一:React.createElement。

要利用 React 操作 DOM,需引入 React 和 ReactDOM 两个依赖库。React.createElement 用于创建轻量且高效的虚拟 DOM 数据结构,以表征用户界面;ReactDOM 则负责将虚拟 DOM 渲染至浏览器真实的 DOM 中。

React.createElement 函数接收三个参数以构建虚拟 DOM 元素:

  • 待创建元素的标签名称
  • 元素的属性对象
  • 元素的子节点
import React from 'react';
const name = 'h1';
const props = { className: 'title' };
const children = 'I am Groot';
const element = React.createElement(name, props, children);

React.createElement 同样支持接收一个包含所有子元素的数组作为参数。

import React from 'react';
const name = 'h1';
const props = { className: 'title' };
const children = ['I am Groot'];
const element = React.createElement(name, props, children);

children 参数本质上也是元素的一个常规属性,因此它可以作为 props 对象的一部分存在。

import React from 'react';
const props = {
  className: 'title',
  children: ['I am Groot']
};
const element = React.createElement('h1', props);

要在 DOM 中渲染该元素,需指定其挂载点。在本例中,即选取 id 为 app 的 div 元素,并指示 ReactDOM 进行渲染。

import React from 'react';
import ReactDOM from 'react-dom';
const props = {
  className: 'title',
  children: ['I am Groot']
};
const element = React.createElement('h1', ...props);
ReactDOM.render(element, document.getElementById('app'));

文中所有代码示例均可通过引入未压缩版本的 React 和 Babel 进行本地测试。此类配置仅适用于简单测试,因其未经过生产构建的优化。在此特定场景下,应移除 react 和 react-dom 的全局导入(此处均作为全局变量暴露)。

<!DOCTYPE html>
<html>
  <head>
    <title>React</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script type="text/babel">
    const props = {
      className: 'title',
      children: ['I am Groot']
    };
    const element = React.createElement('h1', props);
    ReactDOM.render(element, document.getElementById('app'));
    </script>
  </head>
  <body>
    <div id="app" />
  </body>
</html>

轻松掌握 JSX 语法

尽管上述方法能构建所有 Web 页面,但其代码冗长。为简化 DOM 操作,React 提供了一种名为 JSX 的简洁且强大的语法扩展。

构建工具中的预处理器会在构建阶段将 JSX 转换为标准 JavaScript。常规 React 项目利用预处理器将 JSX 代码编译为对 React.createElement 的调用。因此,JSX 并非由 React 直接解释,开发者甚至可以在完全不使用 JSX 的情况下使用 React。故以下两段代码功能完全等价:首先,以编程方式使用 React:

import React from 'react';
const props = { className: 'title' };
const children = ['I am Groot'];
const element = React.createElement('h1', props, children);

或使用 JSX 语法声明:

import React from 'react';
const element = &lt;h1 className="title"&gt;I am Groot&lt;/h1&gt;;

由于 JSX 代码最终会被编译为对 React.createElement 的调用,因此必须导入 React,即便在 JSX 中看似未直接使用它。

使用 JSX 能以声明方式快速构建大部分 DOM,而 React 底层仅识别对 React.createElement 的调用。鉴于 JSX 元素本质上是对 React.createElement 的封装,children 依然是常规属性。因此,前述示例也可按如下方式编写:

import React from 'react';
const element = &lt;h1 className="title" children="I am Groot"/&gt;;

借助 JSX,开发者可通过花括号语法访问变量:

import React from 'react';
const title = 'title';
const text = 'I am Groot';
const element = &lt;h1 className={title} children={text}/&gt;;

当然,我们也可以将变量直接命名为期望操作的属性名:

import React from 'react';
const className = 'title';
const children = 'I am Groot';
const element = &lt;h1 className={className} children={children}/&gt;;

这使我们能够利用扩展语法(Spread Syntax)来编写更简洁的代码。

import React from 'react';
const props = {
  className: 'title',
  children: ['I am Groot']
};
const element = &lt;h1 {...props}/&gt;;

最后,我们可以像之前一样,在 DOM 中通过 React.createElement 渲染该元素。

import React from 'react';
import ReactDOM from 'react-dom';
const props = {
  className: 'title',
  children: ['I am Groot']
};
ReactDOM.render(&lt;h1 {...props}/&gt;, document.getElementById('app'));

既然已使用 JSX 通过 React 渲染了首个虚拟 DOM 片段,接下来我们将探讨如何利用 React 构建基本应用程序。

立即行动,利用 React 组件开发更多动态交互代码。

以上即为从原生 JavaScript 到 React 深入理解的完整内容,更多关于原生 JavaScript 到 React 的资料请关注本站其它相关文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章