React 教程通常会跳过的概念

2025-05-24

React 教程通常会跳过的概念

虚拟 DOM

vDOM的内存 JavaScript 表示DOM。正如 DOM 由节点构成一样,vDOM 由虚拟节点(vNode)构成。

vNodes大致可以分为两类:虚拟元素(vElement)和虚拟文本元素(vText)。这些虚拟节点可以分别映射到 DOM 的HTMLElementTextNode

虚拟 DOM 是什么样的

vDOM 只是指实际 DOM 的 JavaScript 表示。虚拟 DOM 的外观并没有严格的规定。例如,我们可以这样表示这个 DOM 节点……

<p class="emphasis">Hello, world!</p>
Enter fullscreen mode Exit fullscreen mode

(1)

const vNode = {
    tagName: "p",
    attrs: {
        className: "emphasis"
    },
    children: ["Hello, world!"]
}
Enter fullscreen mode Exit fullscreen mode

或 (2)

const vNode = {
    type: "p",
    props: {
        className: "emphasis"
    },
    descendents: ["Hello, world!"]
}   
Enter fullscreen mode Exit fullscreen mode

只要我们能够找到一种可靠的方法来使用其虚拟表示的任何版本重建实际的 DOM,那就没问题了。

createElement(类型,道具,...孩子)

大多数虚拟 DOM 实现都会有一个createElement类似的函数React.createElement()。该函数只需给定一些参数(描述我们想要创建的元素类型)即可返回一个虚拟元素。

const createElement = (type, props = {}, ...children) => {
  return {
    type,
    props,
    children,
  };
};

const vApp = createElement(
  "div",
  { className: "app" },
  createElement("p", { className: "emphasis" }, "Hello, world!")
);
Enter fullscreen mode Exit fullscreen mode

如果你登录vApp,它应该看起来像这样:

{
  type: 'div',
  props: { className: 'app' },
  children: [
    {
      type: 'p',
      props: { className: 'emphasis' },
      children: [ 'Hello, world!' ]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

vDOM 到 DOM

vDOM 是一个普通的 JavaScript 对象,我们无法将其神奇地插入到原生 DOM 中。浏览器需要实际的原生节点来显示 HTML。React 使用一个render函数,该函数接受一个 vDOM 节点作为参数,并返回一个可以插入或附加到 DOM 的原生 DOM 节点。

DOM 复习

vDOM 应该具备在真实 DOM 中创建等效表示所需的所有细节。如果您不记得 DOM 相关的方法,我已将它们列在下面。


// Creating an element
const $el = document.createElement("h1");

// Setting non-style attributes
$el.className = "emphasis";

// Setting style attributes
$el.style.border = "1px solid black";

// Appending a child element
const textEl = document.createTextNode("Hello, world!"); 
$el.appendChild(textEl)
Enter fullscreen mode Exit fullscreen mode

JSX

如果您阅读官方 Babel JSX 文档,您就会知道 Babel 会转译此代码:

<ul className="list">
  <li>item 1</li>
  <li>item 2</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

进入这个

React.createElement("ul", { className: "list" },
  React.createElement("li", {}, "item 1"),
  React.createElement("li", {}, "item 2"),
);
Enter fullscreen mode Exit fullscreen mode

我们一直在做类似的事情。React.createElement我们用 来代替 。但如果我们可以不用显式调用,而像在 React 中一样直接编写 JSX,createElement那岂不是很棒!是的,你真的可以用一个名为 的插件来实现。使用 yarn 或 npm 安装该插件,我们现在可以在源文件顶部添加一行类似注释的JSX 指令:createElementbabel-plugin-transform-react-jsx

/** @jsx createElement */
<ul className=list>
  <li>item 1</li>
  <li>item 2</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

这会告诉 Babel 使用我们的createElement函数而不是来转译 JSX React.createElement。转译后,我们得到以下内容:

createElement(
  "ul",
  { className: "list" },
  createElement(
    "li",
    {},
    "item 1"
  ),
  createElement(
    "li",
    {},
    "item 2"
  )    
);
Enter fullscreen mode Exit fullscreen mode

您很少会发现需要创建自己的createElement函数。这仅供您参考。

将组件名称大写

在转译 JSX 时,Babel 会根据标签名称的大小写来判断我们描述的是组件还是 HTML 元素。因此,我们总是以大写字母开头组件名称。

始终从“react”导入 React

即使我们在代码中任何地方都看不到对 React 的引用,也请务必导入 React,因为请记住:JSX 最终会转换为一堆React.createElement。我们需要对 React 的引用。

// do this
import React from 'react';
Enter fullscreen mode Exit fullscreen mode

希望你喜欢这篇快速的概念介绍,我希望在我刚开始学习 React 的时候有人教过我。显然,对于许多不关心实现细节的人来说,这些细节并不重要。至少,我希望这些概念对你有帮助!

附言:有时候看看引擎盖下的东西也很有趣!

热情地,
DH

文章来源:https://dev.to/icncsx/what-does-the-virtual-dom-look-like-4c7j
PREV
2025 年 21+ 个最佳免费开源图标库
NEXT
单元测试:最佳实践 测试什么 为什么需要单元测试 模块化和依赖性 测试结构 何时不需要单元测试