React virtual dom 与 A​​jax 在功能上有何不同?

Nit*_*jes 3 reactjs virtual-dom

我刚刚开始学习 React JS。了解了反应如何更新渲染上的变化,虚拟 dom 如何帮助做到这一点。我是一名开发人员,以前在项目中使用过ajax。我了解了使用 React 的好处和效率。但是在学习过程中,我了解到 React virtual dom 用于仅更新发生更改的对象。如果我没记错的话,Ajax 也能实现同样的效果。有人澄清这两个概念。

小智 5

让我们将上下文分为三个项目;

  1. 互联网
  2. 沟通
  3. 内容(HTML JS 和 CSS)
  4. 浏览器

众所周知;

  • 我们需要浏览器来查看内容。
  • 浏览器通过互联网通过 HTTP 协议进行通信

您很可能听说过文档对象模型 (DOM),但还有另一个方面称为浏览器对象模型 (BOM)。是BOM;

  1. 从地址栏或您点击的锚链接获取 URL,然后获取相关内容并将其转发到 DOM 进行解释。
  2. 一旦 DOM 接收到新内容,它就会解释代码并绘制有意义的视觉表示。
  3. 该解释周期由各种窗口状态和事件表示,即弹出、文档就绪、页面显示、页面隐藏、加载、卸载、调整大小、聚焦、单击等。

为了更好地理解一些图表,请花一些时间来收集它们。

Window、BOM、DOM 和 Javascript 关系

文档对象模型节点树

浏览器对象模型

JavaScript 与 JavaScript 编码标准、DOM 和 BOM 的关系

事情的计划如下;

  1. 获取 URL - 弹出事件

  2. 收到初始 HTML 代码 - 文档就绪状态

  3. HTML 代码被解释,保存在与该特定窗口关联的内存中,作为 DOM 树状态窗口呈现事件

  4. 渲染结果的视觉表示推送到屏幕 - 页面显示事件

  5. 屏幕上逐像素绘制的 DOM 树 - 窗口绘制事件

  6. 同时,正在获取所有其他关联内容,例如 CSS、JS、背景图像等。

  7. 相关内容已完全接收 - 加载事件时

  8. 完成加载事件后,将新收到的 CSS 和 JS 与步骤 3 中保存在关联内存中的状态进行比较。

  9. 如果存在差异,或者有新的说明,请从步骤 3 开始。

简而言之;

  • 我们为单个集体页面渲染和绘制窗口两次。
  • 如今,我们不太注意到这一点,因为浏览器内存已经改善,否则过去的美好时光白色闪光或闪烁是此类状态和事件的影响。
  • 如果我们需要从一页跳到另一页,事情只会变得更糟。首先浏览器必须调用 pop 事件,然后调用页面隐藏,然后调用 before unload 事件,然后从步骤 2 开始,每件事都做两次。
  • 为了真正在开发人员的大脑中运行,DOM 标准(又名 HTML 标准)由 W3C 维护,JavaScript 标准由 ECMA 维护,浏览器被规定为他们选择在 BOM 中包含哪些标准。因此,虽然标签可能在所有其他浏览器中工作,但在 IE 中可能不起作用,或者虽然箭头功能在现代浏览器中可能工作,但在稍旧版本的浏览器中可能不起作用。这就是我们使用 polyfill 的原因,也正是存在各种库和框架(包括 JQuery)的原因。

Ajax 想要实现什么目标?

一旦浏览器进入文档就绪状态,BOM 就会指示导航器功能启动一定数量的 HTTP 连接(一次最多可达 6 个),以便下载嵌入在页面中的各种图像、CSS 和 JS 文件。这一切都会在后台进行。

开发人员讨厌 IE,因为它臭名昭著地没有在 BOM 中实现最新的 DOM 或 JS 功能。然而,如果没有 IE,我们就不会有现在这样的 AJAX。

1996 年,IE 引入了iframe功能,可以下载页面特定区域的外部内容。任何后续的 HTTP 请求都将在屏幕的特定区域中重新绘制,而不是重新绘制整个页面。新颖的想法很简单,就是使用与下载图像相同的方案(iframe)。显然,它必须在 BOM 级别实施。因此IE5以后的iframe标签成为标准功能。一年之内,iframe 被引入为 HTML 4.0 DOM 标准中的标准,所有浏览器都在其 BOM 中默认实现了该技术。

到了 1999 年,在文档就绪状态后进行幕后沟通的新颖想法引发了进一步的“假设”。概念。如果使用 JavaScript 我们可以获取任何内容(例如 iframe)并更新屏幕上的任何给定区域,会怎么样?IE 再次提出了名为XMLHTTP ActiveX 控件的解决方案。不久之后,Mozilla、Safari、Opera 和其他浏览器后来将其实现为XMLHttpRequest JavaScript 对象。同样是它的 BOM 功能,也可能是您必须编写此代码的原因。

    function Xhr(){ /* returns cross-browser XMLHttpRequest, or null if unable */
    try {
        return new XMLHttpRequest();
    }catch(e){}
    try {
        return new ActiveXObject("Msxml3.XMLHTTP");
    }catch(e){}
    try {
        return new ActiveXObject("Msxml2.XMLHTTP.6.0");
    }catch(e){}
    try {
        return new ActiveXObject("Msxml2.XMLHTTP.3.0");
    }catch(e){}
    try {
        return new ActiveXObject("Msxml2.XMLHTTP");
    }catch(e){}
    try {
        return new ActiveXObject("Microsoft.XMLHTTP");
    }catch(e){}
    return null;
}
Run Code Online (Sandbox Code Playgroud)

感谢我亲爱的主赐予 John Resig 开发 JQuery 的勇气,这使得 AJAX 变得轻而易举。

我们从 AJAX 中获得了什么?
优点

  • 我们通过BOM的JS编程参考图3,通过文档级Navigator实例进行通信,而不是Window、BOM、DOM和Javascript关系的窗口级Navigator事件参考图1。
  • 重新渲染 DOM 树后,仅重新绘制相关的 DOM 树部分,而不是重新绘制整个 DOM 树,即重新绘制整个页面。因此没有白色闪烁。
  • 重新渲染后,我们可以遍历和操作新内容,就好像它是原始内容的一部分一样。
  • 我们可以触发最多六个异步运行的导航器实例,遵循上述彼此独立的模式,如上所述。

缺点

  • 由于没有窗口级导航器事件,BOM 不会调用历史功能。因此没有弹出状态,因此很可能没有缓存,并且地址栏中绝对没有 URL 更改。
  • 为了利用这些缺失的功能,人们必须以编程方式实例化它们。默认为不执行任何操作。

React 想要实现什么目标?

自从 AJAX 出现以来,可扩展的 Web 应用程序开始出现。这与网页形成对比。单页应用程序 (SPA) 只是同一上下文的另一个名称。SPA 作为概念很快导致了基于 AJAX 的 Web 组件开发,例如 AJAX 表单提交、自动完成以及变色消息铃等等。

回到 DOM,每次我们收到初始 HTML 代码作为窗口弹出事件时,DOM 解析器都会从顶行到底行遍历代码。一旦越过这条线,就不会再回升。每次传递该行时,它都会解析该行并将其添加到正在渲染的 DOM 树中,该树将在稍后绘制。示例如下;

<!DOCTYPE html>
<html>
<body>

<h1>My First Heading</h1>
<p>My first paragraph.</p>

</body>
</html>
Run Code Online (Sandbox Code Playgroud)

解析器读取第一个标签以确定要遵循的标准,然后一旦涉及到 body 标签,它就会应用该元素的默认属性,如果未显式声明,则 h1 标签将应用默认属性。默认属性由 W3C 在 HTML 5 标准中定义。

现在我们已经在内存中渲染了 DOM 树,必须将其绘制到屏幕上。这就是乐趣开始的地方。参考第四张 JavaScript 与 ECMA、DOM 和 BOM 的关系图。BOM调用JS引擎在屏幕上完成毕加索的工作。

简而言之,这就是所谓的;

  • Hard DOM - 最初通过 pop 事件接收的 DOM
  • 虚拟 DOM - 一种在内存中被解析并由 DOM 树组成的模型
  • HARD DOM - 再次从虚拟 DOM 绘制到屏幕上
  • Shadow DOM - DOM 树的某些元素具有固定的行为和属性,一旦实现,就称为该特定 DOM 树元素的影子 DOM。

影子 DOM 示例

<input type="text" name="FirstName" value="Mickey"></input>
Run Code Online (Sandbox Code Playgroud)

已应用 Shadow DOM,如下所示;

<input type="text" name="FirstName" value="Mickey">
#shadow-root (user-agent)
<div>Mickey</div>
</input>
Run Code Online (Sandbox Code Playgroud)

啊哈,所以输入可能实际上是一个可编辑的 div。现在您知道contenteditable="true"属性在 div 标签上的作用了。

所以事情的计划如下;

  1. 收到 HTML 代码
  2. HTMl 被解析为 Virtual DOM
  3. 并行地将 Shadow DOM 应用到每个相关的树项上
  4. 虚拟 DOM 和 Shadow DOM 都保存在内存中
  5. 它们都作为扁平的 HARD DOM 树一起绘制在屏幕上。

我们可以轻松遍历访问 HARD DOM 和 Virtual DOM,但访问 Shadow DOm 是全新的游戏。所以我们就这样吧。

这就是下图中的结果; HTML 解析到绘制之旅

而在后期,JS 引擎运行批量命令并创建虚拟 DOM 树中渲染的每个项目的对象标识符。如果您要自己创建它,下面只是一个示例。

var btn = document.createElement("BUTTON");   
btn.innerHTML = "CLICK ME";                   
document.body.appendChild(btn);
Run Code Online (Sandbox Code Playgroud)

一旦创建元素函数被调用,虚拟 DOM 就会渲染另一个元素。然后你就可以用它做任何你想做的事。

然而,在你调用append child之前,它永远不会进入HARD扁平化DOM的领域。然后,在进入 Hard DOM 后,您就可以做任何您想做的事情了。

那么所有虚拟 DOM 和硬 DOM 的意义何在呢?

让我们探索一下。在正常情况下,如果我要遍历硬 DOM,我将必须查询当前文档以遍历其所有 DOM 树并找到我们正在查找的元素。这就是 Jquery 所做的,结果称为 HTML 集合。下面的例子;

var btn = document.createElement("BUTTON");   
btn.innerHTML = "CLICK ME";                   
document.body.appendChild(btn);
// manipulate for the created element via hard DOM way but first find it
document.querySelector("BUTTON").innerHTML = "OPPS ME";
Run Code Online (Sandbox Code Playgroud)

假设有 5 个按钮,那么上面的查询将操作哪个按钮。只是第一个。

要仅操作第三个,我需要首先将 HTML 集合生成到数组中,然后运行该数组以查找所需元素的引用,然后操作它。下面的例子;

document.querySelectorAll("BUTTON")[2].innerHTML = "OPPS ME";
Run Code Online (Sandbox Code Playgroud)

仅更改一个按钮的文本就需要大量的工作。如果我希望以虚拟方式进行操作,我所要做的就是调用这段代码;

  btn.innerHTML = "OPPS ME";
Run Code Online (Sandbox Code Playgroud)

React 打算采用虚拟方式。

  • 它表明不会有初始的 HARD DOM HTML 代码。如果有的话,只需在 body 标签中添加 JS 即可。
  • 它运行批量的 jS 创建元素函数来生成 DOM 树并创建对新创建元素的引用。
  • 一旦生成整棵树,它就会推动它进行绘画。
  • 这样做可以减少解析、渲染、绘制、重新解析、重新渲染、然后重新绘制的腿部工作。
  • 当将来需要更新某些内容时,它会调用参考并像我们一样发挥神奇作用。
  • 默认情况下,浏览器 BOM 始终保持虚拟 DOM 与硬 DOM 以及硬 DOM 与虚拟 DOM 同步。如果其中任何一件事发生变化,它就会以镜像的形式反映在另一件事上。
  • 更重要的是,如果您可以记录更改的内容以及参考内容,您就可以来回实施和重新实施它们,就像它们缓存在历史记录中一样。
  • BOM 已经在表单输入Ctrl+ Z, Ctrl+上执行了此操作Y。只有在 React 中,你才通过 JS 对所有元素进行操作。我的朋友,这是状态管理的基础。

我们从 React 中获得了什么?

优点

  • 节省了解析、渲染、绘制、查找、操作 DOM 树的时间和头痛。

  • 这样做时,仅重新绘制 DOM 树的相关部分,而不是重新绘制整个 DOM 树,即重新绘制整个页面。因此不会出现类似于 AJAX 的白色闪烁。

  • 可以预先对数据进行预渲染计算,仅在条件满足时才执行操作。

  • 您控制状态管理。

缺点

  1. 没有弹出状态,因此必须进行编程才能利用这些功能。
  2. 必须建立路由系统,否则简单的 F5 会将您带回第一步,就好像什么都不存在一样。
  3. 严重依赖 JS,几乎放弃了 DOM 环境所能提供的辉煌潜力,CSS 等只是同父异母的兄弟。
  4. SPA 概念已有近十年的历史,从那时起人们就意识到它并不能解决所有问题。现代移动环境需要更多。
  5. 结束脚本臃肿。

React 不关心什么?

React 并不关心新数据如何来以及从哪里来。无论是ajax,还是用户提供的,它所做的只是管理数据的状态,egold 按钮文本是“某某”,无论是否进行更改,新数据都是“某某”。如果进行了更改,请记录下来。

React 和 Ajax 都希望借鉴 BOM 流程,并根据渐进增强和用户体验来启动功能。

一种是通过操纵通信的方式来实现这一点,另一种是通过最终如何呈现通信中的数据来实现这一点。

因此,两者本质上都是 SPA 概念的一部分,可以相互补充,但在两个不同的领域中相互依赖地发挥作用。