【前端架构】从 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。

结论

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

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

相关文章
|
6天前
|
前端开发 JavaScript 开发者
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
28 9
|
28天前
|
前端开发
深入解析React Hooks:构建高效且可维护的前端应用
本文将带你走进React Hooks的世界,探索这一革新特性如何改变我们构建React组件的方式。通过分析Hooks的核心概念、使用方法和最佳实践,文章旨在帮助你充分利用Hooks来提高开发效率,编写更简洁、更可维护的前端代码。我们将通过实际代码示例,深入了解useState、useEffect等常用Hooks的内部工作原理,并探讨如何自定义Hooks以复用逻辑。
|
26天前
|
前端开发 数据管理 编译器
引领前端未来:React 19的重大更新与实战指南🚀
React 19 即将发布,带来一系列革命性的新功能,旨在简化开发过程并显著提升性能。本文介绍了 React 19 的核心功能,如自动优化重新渲染的 React 编译器、加速初始加载的服务器组件、简化表单处理的 Actions、无缝集成的 Web 组件,以及文档元数据的直接管理。这些新功能通过自动化、优化和增强用户体验,帮助开发者构建更高效的 Web 应用程序。
73 1
引领前端未来:React 19的重大更新与实战指南🚀
|
11天前
|
前端开发 JavaScript Android开发
前端框架趋势:React Native在跨平台开发中的优势与挑战
【10月更文挑战第27天】React Native 是跨平台开发领域的佼佼者,凭借其独特的跨平台能力和高效的开发体验,成为许多开发者的首选。本文探讨了 React Native 的优势与挑战,包括跨平台开发能力、原生组件渲染、性能优化及调试复杂性等问题,并通过代码示例展示了其实际应用。
33 1
|
13天前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】React与Vue:前端框架的巅峰对决与选择策略
|
13天前
|
前端开发 JavaScript 开发者
“揭秘React Hooks的神秘面纱:如何掌握这些改变游戏规则的超能力以打造无敌前端应用”
【10月更文挑战第25天】React Hooks 自 2018 年推出以来,已成为 React 功能组件的重要组成部分。本文全面解析了 React Hooks 的核心概念,包括 `useState` 和 `useEffect` 的使用方法,并提供了最佳实践,如避免过度使用 Hooks、保持 Hooks 调用顺序一致、使用 `useReducer` 管理复杂状态逻辑、自定义 Hooks 封装复用逻辑等,帮助开发者更高效地使用 Hooks,构建健壮且易于维护的 React 应用。
27 2
|
13天前
|
前端开发 JavaScript 数据管理
React与Vue:两大前端框架的较量与选择策略
【10月更文挑战第23天】React与Vue:两大前端框架的较量与选择策略
|
18天前
|
缓存 前端开发 JavaScript
前端serverless探索之组件单独部署时,利用rxjs实现业务状态与vue-react-angular等框架的响应式状态映射
本文深入探讨了如何将RxJS与Vue、React、Angular三大前端框架进行集成,通过抽象出辅助方法`useRx`和`pushPipe`,实现跨框架的状态管理。具体介绍了各框架的响应式机制,展示了如何将RxJS的Observable对象转化为框架的响应式数据,并通过示例代码演示了使用方法。此外,还讨论了全局状态源与WebComponent的部署优化,以及一些实践中的改进点。这些方法不仅简化了异步编程,还提升了代码的可读性和可维护性。
|
12天前
|
前端开发 Android开发 开发者
前端框架趋势:React Native在跨平台开发中的优势与挑战
【10月更文挑战第26天】近年来,React Native凭借其跨平台开发能力在移动应用开发领域迅速崛起。本文将探讨React Native的优势与挑战,并通过示例代码展示其应用实践。React Native允许开发者使用同一套代码库同时构建iOS和Android应用,提高开发效率,降低维护成本。它具备接近原生应用的性能和用户体验,但也面临平台差异、原生功能支持和第三方库兼容性等挑战。
25 0
|
13天前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】 React与Vue:前端框架的巅峰对决与选择策略