【前端架构】从 JQuery 到 React、Vue、Angular——前端框架的演变及其差异

简介: 【前端架构】从 JQuery 到 React、Vue、Angular——前端框架的演变及其差异

这是前端面试中必然会问到的问题


前端开发多年来一直在不断改进。从简单的静态页面到现在复杂的单页面应用程序,我们的工具变得越来越强大。现在,三大前端框架统治着前端开发,那么你知道这三个框架的区别吗?为什么一直保持着三足鼎立的局面,而不是某种框架来统一其他人?让我们在本文中讨论这些问题。

前端开发的演变

PHP && JSP

早些年,网页的动态内容是在服务器端渲染的,主要使用PHP、JSP等技术。

此时,服务器通过模板引擎填充数据,然后生成HTML,并将HTML返回给浏览器进行渲染。

<!DOCTYPE html>

<html>

<body><h1>My first PHP page</h1><?php

echo "Hello World!";

?></body>

</html>

AJAX

后来有了 AJAX 技术,JavaScript 可以直接在浏览器中发送异步 HTTP 请求,动态地从服务器获取数据,而不是把所有的数据都放在 HTML 中。

<body>

 <h2>Hello world</h2>

 <div id="demo"></div>

 <script>

   var xhttp = new XMLHttpRequest();

   xhttp.onreadystatechange = function () {

     if (this.readyState == 4 && this.status == 200) {

       // Typical action to be performed when the document is ready:

       document.getElementById("demo").innerHTML = xhttp.responseText;

     }

   };

   xhttp.open("GET", "/api/data", true);

   xhttp.send();

 </script>

</body>

最早的 AJAX 是基于 XML 的,所以现在我们用 JavaScript 发送 HTTP 请求时,使用的函数叫做 XMLHttpRequest。但是XML中有很多不必要的标签,浪费了服务器带宽,所以JSON格式的数据占据了主流位置。

DOM API && jQuery

过去开发网页时,主要是通过浏览器提供的DOM API来操作DOM。

但是 DOM API 比较繁琐,在不同的浏览器中存在兼容性问题。为了简化dom操作和兼容不同的浏览器,jQuery开始流行起来。在那个时候,jQuery可以说是前端开发者必学的技术。

$( "button.continue" ).html( "Next Step..." )

前端框架

然后在开发网页的时候,我们发现一个网页需要做的就是先从服务器获取数据,然后根据数据更新DOM。

而且这个过程是固定的。为了简化 DOM 操作,人们发明了 MVVM 框架来自动将数据更改映射到 DOM 更新,而无需手动操作 DOM。这就是前端框架 Angular、React、Vue 所做的。

import { useState } from 'react'function Counter() {

 

 const [count, setCount] = useState(0)  return (

   <div>

     <p>you clicked {count} times</p>

     <button onClick={() => setCount(count + 1)}>increase</button>

     <button onClick={() => setCount(count - 1)}>decrease</button>

 </div>)

}

export default Counter

同时前端框架也支持DOM的逻辑划分。我们可以将 DOM 的一部分封装成组件,将组件相互组合,形成整个应用程序。

这种思路让我们可以将一个复杂的页面拆分成不同的组件,方便我们开发项目。

 

React、Vue、Angular 之间的区别

这些前端框架主要使用以下思想:

UI = f(state)

我们只需要声明一个组件的状态、视图和组件之间的依赖关系,就会自动生成组件的UI。

尽管它们的核心思想相同,但这些框架的实现细节却有所不同。下面我们来分析一下。

React JSX 与 Vue 模板

React 和 Vue 在描述视图层时给出了不同的解决方案。React 选择扩展 JavaScript 并引入 JSX。而 Vue 创建了一个独立的模板语法。

React JSX:

export default function TodoList() {

 let list = ['JavaScript', 'React', 'Vue']

 return <div>

   {

     list.map(item => <li>{ item }</li>)

   }

 </div>

}

Vue模板:

<ul id="array-rendering">

 <li v-for="item in items">

   {{ item.message }}

 </li>

</ul>

JSX 的优点:

  • 在编写 JSX 时,开发人员可以使用他们现有的 JavaScript 知识,而无需太多额外的学习成本。
  • JSX 可以利用 JavaScript 本身的特性,因此更加强大。
  • JSX 代码和普通的 JavaScript 代码将在同一个执行上下文中执行,因此 JSX 可以很容易地与 TypeScript 结合。Vue Template 和 JavaScript 执行上下文是分开的,所以在 Vuejs 中引入 TypeScript 比较困难。您需要分别声明 prop、method 和 data 的类型。

当然,Vue Template 也有自己的优势。由于 Vue Template 只能使用有限的语法,因此 Vue 可以更轻松地对其进行静态分析和性能优化,这在 JSX 中是很难做到的。

检查数据更新的不同方法

这三个前端框架都需要观察数据变化来决定是否需要更新 UI,但是他们选择了完全不同的方式来做这件事。

Angular 采用的方式是脏检查。每条可能修改数据的语句执行完毕后,Angular 都会对比前后的数据,判断是否有数据变化。

Vue 直接使用 JavaScript 的原生特性来监控数据变化。Vue2 使用了 Object.defineProperty ,而 Vue3 使用了 Proxy。

另一方面,React 采取了不同的策略。React 并不直接监控数据变化,而是在数据和 UI 之间添加了一个虚拟 DOM。每次组件应该更新后都会重新生成一个虚拟 DOM,React 会获取新虚拟 DOM 和旧虚拟 DOM 之间的差异。然后 React 决定是否以及如何更新真实的 DOM。

Vue 和 React 的优化

Vue 的数据监视是在组件级别。当组件内部有很多地方可以看数据变化时,一次更新可能需要大量的计算,这可能会导致丢帧,也就是渲染卡顿。所以Vue的优化方法是将大组件拆分成小组件,这样每个数据不会有太多的watcher。

React 不会观察数据变化,而是渲染整个虚拟 dom,然后进行 diff。所以 React 的优化方法是对于不需要重新渲染的组件,通过 shouldComponentUpdate 跳过渲染。

但是,当应用程序的组件树非常大的时候,仅仅使用 shouldComponentUpdate 来跳过一些组件的渲染,可能仍然是非常耗费计算量的。大量的计算也可能导致渲染冻结。那么我们应该怎么做呢?

树遍历有两种方法:深度优先和广度优先。组件树的渲染是深度优先的,一般通过递归来实现。递归调用不能暂停,可能会导致页面冻结。

但是如果我们用链表来记录访问路径,就可以把树的递归遍历变成数组的循环遍历。循环遍历数组时,可以根据时间片进行分段,这样虚拟dom的生成就不会再阻塞页面渲染了。这与操作系统对多个进程的分时调度非常相似。

将组件树变为链表,将virtual dom的生成由递归变为循环的机制有一个著名的名字:React Fiber。


与之前的组件节点相比,Fiber节点没有parent和children属性,但是有child、sibling和return属性。React 通过 Fiber 链表树优化渲染性能。

在这里我们可以发现,Vue 的性能优化与 React 有很大的不同:

  • Vue 使用组件级的数据监视解决方案。当一个属性有太多的watcher时,可能会出现性能瓶颈,所以优化思路是把大组件拆分成小组件,保证每个属性不会有太多的watcher。
  • 但是,React 不会监视或检查数据更改。它每次渲染生成virtual dom,然后对比新旧virtual dom。优化思路是使用 shouldComponentUpdate 跳过部分组件的渲染。

重用代码的不同方法

组件之间会有一些共同的逻辑需要重用。React 和 Vue 有不同的解决方案。

Vue的组件都是option对象的形式,所以很自然的想到通过对象属性来进行mixins进行逻辑复用。Vue2组件的内部逻辑复用方案确实是mixin,但是mixin很难区分自己的属性和混合属性,也无法判断方法的来源。所以 mixin 的代码很乱,维护也很差。但是没有更好的解决方案。

React 在开始时也支持 mixins,但后来被弃用了。

React 组件有两种形式:类组件和函数式组件。对于类组件,像高阶函数这样的高阶组件(HOC)是重用代码的一种自然方式。具体来说,我们可以使用父组件包装子组件,在父组件中执行一些逻辑,然后渲染子组件。

除了使用 HOC,我们还可以直接将一些 JSX 作为 props 传递给另一个组件进行复用,也就是 render props。

HOC 和 render props 是 React 的类组件支持的两种逻辑复用方案。

原始功能组件是无状态的,仅作为类组件渲染的辅助而存在。

然而,HOC 的逻辑复用方式最终导致了组件的深度嵌套。而且,类的内部生命周期很多,把不同的逻辑放在一起会使组件更加复杂。

如何解决类组件的深度嵌套?并且解决方案不能进行重大更新。

所以 React 团队看了一下功能组件。他们希望在功能组件中扩展一些 API 以支持状态。

如果一个功能组件要支持状态,那么状态应该存储在哪里?

类组件本身是有状态的,成为纤节点后还是有状态的。功能组件一开始没有状态,成为光纤节点后也没有。

这样想,给功能组件的光纤节点添加状态还不够吗?

所以 React 将 memorizedState 属性添加到功能组件的一个 Fiber 节点中来存储数据,然后开发者可以通过 API 使用功能组件中的数据。这些 API 被称为 React Hooks。因为数据是在光纤节点上使用的,所以 API 被命名为 useXxx。

结论

三个前端框架各有优缺点。简单地比较谁更好是没有意义的。我们需要做的是为一个应用场景选择一个合适的解决方案。

技术在不断变化,但最终目的是提高工作效率,降低开发成本,保证质量。

相关文章
|
4月前
|
安全 Android开发 iOS开发
深入探索Android与iOS的差异:从系统架构到用户体验
在当今的智能手机市场中,Android和iOS无疑是最受欢迎的两大操作系统。本文旨在探讨这两个平台之间的主要差异,包括它们的系统架构、开发环境、安全性、以及用户体验等方面。通过对比分析,我们可以更好地理解为何不同的用户群体可能会偏好其中一个平台,以及这些偏好背后的技术原因。
|
4月前
|
Android开发 Swift iOS开发
深入探索iOS与Android操作系统的架构差异及其对应用开发的影响
在当今数字化时代,移动设备已经成为我们日常生活和工作不可或缺的一部分。其中,iOS和Android作为全球最流行的两大移动操作系统,各自拥有独特的系统架构和设计理念。本文将深入探讨iOS与Android的系统架构差异,并分析这些差异如何影响应用开发者的开发策略和用户体验设计。通过对两者的比较,我们可以更好地理解它们各自的优势和局限性,从而为开发者提供有价值的见解,帮助他们在这两个平台上开发出更高效、更符合用户需求的应用。
|
6月前
|
IDE Android开发 iOS开发
深入解析Android与iOS的系统架构及开发环境差异
本文旨在探讨Android和iOS两大主流移动操作系统在系统架构、开发环境和用户体验方面的显著差异。通过对比分析,我们将揭示这两种系统在设计理念、技术实现以及市场策略上的不同路径,帮助开发者更好地理解其特点,从而做出更合适的开发决策。
313 2
|
4月前
|
监控 前端开发 数据可视化
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
@icraft/player-react 是 iCraft Editor 推出的 React 组件库,旨在简化3D数字孪生场景的前端集成。它支持零配置快速接入、自定义插件、丰富的事件和方法、动画控制及实时数据接入,帮助开发者轻松实现3D场景与React项目的无缝融合。
307 8
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
|
3月前
|
安全 Android开发 iOS开发
深入探索iOS与Android系统架构差异及其对开发者的影响
本文旨在通过对比分析iOS和Android两大移动操作系统的系统架构,探讨它们在设计理念、技术实现及开发者生态方面的差异。不同于常规摘要仅概述内容要点,本摘要将简要触及核心议题,为读者提供对两大平台架构特点的宏观理解,铺垫
|
4月前
|
IDE 安全 Android开发
深入探索Android与iOS操作系统的架构差异
本文旨在对比分析Android和iOS两大主流移动操作系统在架构设计上的根本差异。通过详细解读两者的系统架构、开发环境、以及安全性等方面,揭示它们各自的特点及优势,为开发者选择合适的平台提供参考。
|
4月前
|
安全 Android开发 iOS开发
深入探讨Android与iOS的系统架构差异
本文旨在通过对比分析Android和iOS两大移动操作系统的系统架构,揭示它们在设计理念、安全性、应用生态及开发环境等方面的显著差异。我们将从底层架构出发,逐步剖析至用户界面层面,为开发者和科技爱好者提供一份详尽的技术参考。
110 1
|
3月前
|
开发工具 Android开发 iOS开发
Android与iOS生态差异深度剖析:技术架构、开发体验与市场影响####
本文旨在深入探讨Android与iOS两大移动操作系统在技术架构、开发环境及市场表现上的核心差异,为开发者和技术爱好者提供全面的视角。通过对比分析,揭示两者如何塑造了当今多样化的移动应用生态,并对未来发展趋势进行了展望。 ####
|
4月前
|
安全 搜索推荐 Android开发
深入探索Android与iOS的系统架构差异
【10月更文挑战第29天】 在当今的智能手机市场中,Android和iOS无疑是两大主流操作系统。本文旨在深入探讨这两个系统的架构差异,从底层的操作系统设计到用户界面的呈现,以及它们如何影响了开发者和用户的体验。通过对比分析,我们可以更清晰地理解这两种平台的优势与局限,为开发者在选择开发平台时提供有价值的参考,同时也为用户选择设备提供一定的指导。
102 2
|
6月前
|
移动开发 前端开发
react项目配合diff实现文件对比差异功能
在React项目中,可以使用`diff`库实现文件内容对比差异功能。首先安装`diff`库,然后在组件中引入并使用`Diff.diffChars`或`Diff.diffLines`方法比较文本差异。通过循环遍历`diff`结果,可以生成不同样式的HTML元素来高亮显示文本差异。
267 1
react项目配合diff实现文件对比差异功能

热门文章

最新文章