站在高角度来审视前端框架
Ember、Angular、React、Vue
每种主流的 JavaScript 框架都有自己不同的方式更新 DOM、处理浏览器事件并为开发者提供愉快的使用体验,这篇文章将探索“四大”框架的主要特性,从较高的层次探讨框架的工作方式以及它们之间的区别。
框架特性
框架有什么特性?或者说为我们带来了什么?
-
领域特定语言 DSL。 所有框架都基于 JavaScript,并且都允许你使用领域特定语言(DSL)来构建应用程序。React 已经普及了使用 JSX/TSX 来编写其组件,Ember 使用 Handlebars。与 HTML 不同,这些语言知道如何读取数据变量,并且此数据可用于简化编写 UI 的过程。DSL 不能直接由浏览器解析;它们首先要被转换成 JavaScript 或 HTML。
-
简化冗余的 DOM 操作。这是最基本,也是最重要的。框架改变了我们默认的页面元素渲染方式。虚拟 DOM、增量 DOM(Angular )
- 虚拟 DOM 是一种方法,此时关于浏览器的 DOM 信息被存储在 JavaScript 内存中。你的应用程序更新这个 DOM 副本,然后将其与“真正的”DOM(为你的用户实际渲染的 DOM)进行比较,以决定要渲染什么。应用程序建立一个“diff“来比较更新的虚拟 DOM 和当前渲染的 DOM 之间的差异,并使用该差异将更新应用到真实 DOM。React 和 Vue 都利用虚拟 DOM 模型,但它们建立“diff”或渲染应用的逻辑并不完全相同。
- 增量式 DOM 与虚拟 DOM 类似,它建立一个 DOM“diff”来决定渲染什么,但不同的是,它不在 JavaScript 内存中创建一个完整的 DOM 副本。它忽略了 DOM 中不需要被改变的部分。Angular 是本模块到目前为止讨论的唯一一个使用增量 DOM 的框架。
-
组件化(components)。框架支持将用户界面拆分成可重用、可嵌套、易维护且可以互相通信的代码块。与组件相关的所有代码都可以存在于一个文件(或几个特定文件)中,因此可以轻松地知道去哪里修改目标组件。在原生 JavaScript 中,你就必须花时间创建自己的一套高效、可扩展的编码约定来实现这一点。
-
路由。Web 最重要的特点是它允许用户从一个页面导航到另一个页面——毕竟,它是一个相互链接的文档网络。
当你点击网站上的链接时,你的浏览器会与目标服务器通信,获取新内容后将其显示给你。当浏览器这样做时,地址栏中的 URL 会发生变化。你可以记下来这个新 URL 并稍后返回该页面——或者把这个 URL 分享给其他人,以便他们轻松找到相同的页面。你的浏览器会记住你的导航历史记录,并允许你来回导航(译者注:其实就是浏览器的前进后退功能)。这被称作服务端路由。
现代 Web 应用程序通常不会获取和渲染新的 HTML 文件——它们加载单个 HTML shell,并不断更新其中的 DOM 而无需将用户导航到 Web 上的新地址。(这被称为单页应用程序(single page app) 或 SPA)。每个新的伪网页通常称为一个 view,且在默认情况下,不会做任何路由。当 SPA 足够复杂并呈现足够多的独特视图时,将路由功能引入你的应用程序非常重要。人们习惯于能够链接到应用程序中的特定页面,在他们的浏览器中前进和后退等等,当这些标准的 Web 功能被破坏时,他们的体验会受到影响。当客户端应用程序以这种方式处理路由时,它被恰当地称为客户端路由。
可以使用 JavaScript 和浏览器的原生功能来实现路由功能,但是流行的、活跃开发的框架具有配套库,使路由功能在开发过程中更直观。
-
相关生态工具。每个框架都有一个庞大而活跃的社区,因此每个框架的体系都提供了工具来改善开发体验。这些工具让诸如添加测试(确保你的应用表现应有的行为)和 linting(确保你的代码没有错误且排版统一)变得更加容易。
莫为使用框架而使用框架
熟悉工具:就像原生 JavaScript 一样,框架需要时间来学习,也有它们自己的特性。在你决定为项目使用框架之前,确保你有足够的时间学习它的特性,使它发挥功效,而不是阻碍你,并确保你的团队成员也对它满意。
过度工程化:如果你的 web 开发项目是一个只有几个页面的个人作品集,并且这些页面几乎没有交互功能,那么可能根本不需要框架(及其所有的 JavaScript)。也就是说,框架并不是完全统一的,其中一些框架比其他框架更适合于小型项目。Sarah Drasner 在 Smashing 杂志的一篇文章中写道:作为一种使网页的一小部分具有交互性的工具 Vue 是如何取代 jQuery 的 。
大型代码库与抽象:通过在幕后处理 DOM 交互,框架允许你编写更多的声明式代码,有时总体上可以编写更少的代码。这种抽象对于你作为开发者的体验非常好,但它也是有代价的。为了将你编写的内容转换为 DOM 的变更,框架必须运行自己的代码,这反过来又会使你最终的软件变得更大,并且花费更高的运行成本。
一些额外的代码是必不可少的,且一个支持 tree-shaking 的框架(在构建过程中删除应用程序实际未使用的代码)将使你保持应用程序的小型化;但这些额外的代码仍然是你在考虑应用程序性能时需要记住的一个因素,尤其是在网络或存储限制更严格的设备上,比如手机。
框架的抽象不仅影响 JavaScript,还影响你与 web 的关系。无论你如何构建 web,最终,用户都是与 HTML 交互。用 JavaScript 编写整个应用可能会使你忽略 HTML 及其各种标签的用途,并导致产出一个无语义且难以使用的 HTML 文档。实际上,完全依赖 JavaScript 有可能写出脆弱的应用,且没有 JavaScript 就无法运行。
框架不是问题的根源。错误的优先级可能使得任何应用变得脆弱、臃肿和难以使用。框架对开发者很友好,如果你的首要任务是制作一个复杂的 web 应用程序,那么很容易做到。然而,如果你没有考虑性能和无障碍,那么框架将放大这种脆弱、臃肿和难以使用。现代开发者的这种重心放在了框架上,已经在许多地方颠倒了 web 的结构。现代 web 通常把 JavaScript 放在首位,用户体验放在最后,而不是一个健壮的、内容优先的文档网络。
如何选择一个框架
- 框架支持哪些浏览器?
- 框架使用哪些领域特定语言?
- 该框架是否有强大的社区和良好的文档(和其他支持)可用?
框架 | 浏览器支持 | DSL 偏好 | 支持的 DSL |
---|---|---|---|
Angular | IE9+ | TypeScript | 基于 HTML、TypeScript |
React | 现代的浏览器(IE9+ with Polyfills) | JSX | JSX、TypeScript |
Vue | IE9+ | 基于 HTML | 基于 HTML、JSX、Pug |
Ember | 现代的浏览器(IE9+ in Ember version 2.18) | Handlebars | Handlebars、TypeScript |
框架替代方案
如果你正在寻找工具来加快 Web 开发过程,并且你知道你的项目不需要很多客户端 JavaScript,你可以寻求其他几种构建 Web 的解决方案:
- 内容管理系统
- 服务端渲染
- 静态站点生成器
内容管理系统(CMS)是任何允许用户在不直接编写代码的情况下创建网页内容的工具。对于大型项目来说,它们是一种很好的解决方案,尤其是那些需要由编码能力有限的内容编写者来编写的项目,或者希望节省时间的程序员。然而,它们确实需要大量的时间来设置,使用 CMS 意味着你至少放弃了对网站最终输出的一些控制。例如:如果你选择的 CMS 默认不编写无障碍的内容,通常很难改进这一点。
受欢迎的 CMS 的一些例子:Wordpress、Joomla 和 Drupal。
服务端渲染(SSR)是一种应用程序体系结构,在该体系结构中,呈现单页应用程序是服务器的工作。这与客户端渲染相反,服务端渲染是构建 JavaScript 应用程序最常见、最直接的方式。服务端渲染对于客户端的设备压力更小,因为你只发送渲染过的 HTML 文件,但它比客户端渲染更加难以构建。
本模块中介绍的所有框架都支持服务端渲染和客户端渲染。给 React 的 Next.js,给 Vue 的 Nuxt.js(是的,这很令人困惑,它们没有关系),给 Ember 的 FastBoot 还有给 Angular 的 Angular Universal 。
备注: 有些 SSR 解决方案是由社区编写和维护的,而有些是由框架的维护者提供的“官方”解决方案。
静态网站生成器(SSG) 是动态生成多页面网站的所有网页的程序——包括任何相关的 CSS 或 JavaScript——这样它们就可以在任何地方发布。发布主机可以是一个 GitHub Page,一个 Netlify 实例,或者任何你选择的私有服务器。这种方法有很多优点,主要是在性能方面(用户的设备不使用 JavaScript 构建页面,它已经完成了)和安全性(对静态页面的攻击更少)。这些网站仍然可以使用 JavaScript,它们需要它,但并不依赖于它。静态网站生成器需要时间来学习,就像任何其他工具,它可能是你开发过程中的障碍。
静态网站可以可以生成你想要独特的页面。正如框架使你能够快速编写客户端 JavaScript 应用程序一样,静态站点生成器使你能够快速创建本来需要单独编写的 HTML 文件。与框架一样,静态站点生成器允许开发者编写定义网页公共部分的组件,并将这些组件组合在一起创建最终页面。在静态站点生成器的相关术语中,这些组件称为模板。由静态站点生成器构建的 Web 页面甚至可以成为框架应用程序的主页:例如,如果你想让静态生成的网站的一个特定页面在用户访问 React 应用程序时启动它,你可以这样做。
静态网站生成器已经存在了相当长的时间,它们在 web 近来的历史上看到了一线生机。现在有一些非常好的选择,例如 Hugo、Jekyll, Eleventy 和 Gatsby。
组件的自我修养
-
编写组件:属性 Props、状态 State、事件 Event
-
为组件添加样式:CSS、Sass、Less、TailwindCSS、PostCSS
-
嵌套组件的注入依赖
通过许多层组件传递数据的问题被称为“属性穿透”,它对大型应用来说并不理想。 为了规避属性穿透,框架提供了依赖注入的功能,这是一种将某些数据直接传递给需要它的组件的方法,而不需要通过中间的层次。每个框架都以不同的名称和方式来实现依赖注入,但效果最终是一样的。 Angular 把这个过程称为依赖注入;Vue 有
provide()
和inject()
组件方法;React 有一个 Context API;Ember 通过服务分享状态。 -
组件的生命周期
在框架上下文中,一个组件的生命周期是一个组件从被追加到 DOM 然后被浏览器渲染(通常称为挂载)到从 DOM 中移除(通常称为卸载)所经历的一系列阶段的集合。每个框架对这些生命周期阶段的命名都不同,而且不是所有的框架都能让开发者访问相同的阶段。所有的框架都遵循相同的一般模型:它们允许开发者在组件挂载、渲染和卸载以及这之间的许多阶段执行某些动作。 渲染阶段是最需要了解的,因为它在用户与应用程序交互时重复的次数最多。每当浏览器需要渲染一些新的东西时,它就会运行,无论这些新的信息是对浏览器中的内容进行补充、删除,还是对现有内容进行编辑。
上一篇
清明回了趟母校