澳门新葡萄京娱乐场 10

澳门新葡萄京娱乐场JavaScript 框架的探索与变迁

本文由码农网 –
李炳辰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

时间: 2017-12-04阅读: 1109标签: 框架译者言

本文由码农网 –
小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

进入2015年以后,关于JS框架,开发人员有了更多选择了。除了 Angular, Ember, React, Backbone, 还出现了大量的竞争者,现在有太多的框架可选。

近几年可谓是 JavaScript
的大爆炸纪元,各种框架类库层出不穷,它们给前端带来一个又一个的新思想。从以前我们用的
jQuery 直接操作 DOM,到 BackboneJS、Dojo 提供监听器的形式,在到
Ember.js、AngularJS 数据绑定的理念,再到现在的 React、Vue 虚拟 DOM
的思想。都是在当前 Web
应用日益复杂的时代,对于如何处理「应用状态」与「用户界面」之间如何更新的问题,带来更先进的解决方案。

选择最适合项目需求的JavaScript框架,可以提高你发布有竞争力的web
app的能力。

每个人可以从不同的角度对比这些框架,但是我认为最有趣的区别之一是它们管理状态的方法。尤其,思考一下当状态经常发生改变的时候,这些框架是如何做的,这是很一件有意义的事情,在这些框架中,他们各自都用什么方法来反应用户界面的变化?

本文是一篇从技术上,以数据变更和UI同步为方向,循序渐进的讲述 JavaScript
框架如何演进过来的。

最后,你对基于JavaScript的app或网站找到了一条奇妙的思路。选择正确的框架可能对你项目的成功有着相当大的影响。它可以影响你按时完成项目并在将来维护代码的能力。JavaScript框架,如Angular.js,Ember.js或React.js,给你的代码带来结构,并保持其有序化,从而使您你的app更灵活,更具可扩展性,并更容易开发。

管理应用的状态和用户界面的一致在很长的时间里都是一个引发UI开发复杂性的根源。到目前为止, 我们有了几个不同的处理方式,本篇文章会浏览一下它们之中的几个:Ember的 数据绑定,angular 的脏检查,React的虚拟DOM 以及它和不可变数据结构的关系。

本篇文章,给了我一个更加高纬度的视角,来看待 JavaScript 这些个框架。

澳门新葡萄京娱乐场 1

显示数据

我们要说的基本任务是关于程序的内部状态以及怎么把它放到屏幕上显示出来的可见元素。你拿到一套对象,数组,字符串和数字,再把它们变成由一个文本组成的树图结构的东西,表单,链接,按钮和图片。在网页开发中,前者经常表达为
JavaScript 数据结构, 后面几个表现为DOM。

我们经常叫这个过程为“渲染”,你可以想象成是把你的数据模型”映射”成可见的用户界面内容。当你用模板渲染数据时,你得到一个 DOM(或者HTML)来表现数据。

这个过程本身听起来够简单的:尽管映射表单数据模型到UI可能不平凡, 但它毕竟是一个很直接的从输入到输出的转换过程。

澳门新葡萄京娱乐场 2

当我们提到数据经常改变的时候, 事情变的有挑战了。当用户和UI交互,或者不知道世界上什么东西的改变更新了数据,反正UI需要反映这些变化。而且,因为重建DOM 树的操作是一个 昂贵的操作,消耗较大,我们愿意做尽可能少的工作来让数据更新到屏幕。

澳门新葡萄京娱乐场 3

相对于仅仅渲染一次UI,这里面有一个更有难度的问题, 因为它涉及到状态更新。这也是产生几个不同方案的地方。

正文

Javascript场景的易变性

Web开发的变化发生的很快。几乎每个月都会引入一个新的JavaScript框架,并且现有的框架经常被更新。由于这些框架是开放源代码的,因此世界各地的大型社区也都可以不断地使之丰满起来。因此,了解每个框架的优点和它们之间的区别并不是一件容易的事情。

服务器端渲染:一切重来

“没有变化,宇宙是不可变的”

在大JavaScript纪元以前,每一个你和网页的交互都会触发一个服务器端的来回交互,每次点击,每次表单的提交,意味着网页的重新加载,一个请求被发送到服务器端,服务器处理并响应一个崭新的页面,浏览器再重新渲染它。

澳门新葡萄京娱乐场 4

这种情况下,前端不用管理任何状态,每次一有什么事情发生了,一切都结束,浏览器什么也不管。无论什么状态, 都是服务器端来管理。前端就是一些服务器端产生的HTML和CSS, 可能还有浅浅的一点 javascript。

在前端角度来看,这是一个非常简单的办法,这样处理也很慢。不仅仅每次交互意味着一个UI的重新渲染,也是一个数据返回远程的数据中心,再从远程回到前台界面的远程交互过程。

现在,我们大多数已经不再这么做了。我们可以在服务器端初始化我们的应用的状态,然后在前端来管理这些状态(这篇同构 JavaScript很大的篇幅都在说这个),尽管仍然还有一些人成功的使用着这种更复杂的方式。

在 2015 年,JavaScript 框架的选择并不少。在
Angular,Ember,React,Backbone 以及它们众多的竞争者中,有足够多的选择。

深入Angular vs React vs Ember

许多开发人员因为JavaScript框架的种类繁多而感到眼花缭乱——框架外观和功能非常不同。

让我们来比较一下三个最流行和广泛使用的JavaScript框架的优势:AngularJS,ReactJS和EmberJS。

框架

AngularJS

ReactJS

Ember.js

是什么?

超级JavaScript MVW框架

一个不止用于构建用户界面的JavaScript库

一个用于创建高要求的web应用程序的框架

建立

由MiškoHevery建立于2009年

创建者:Jordan Walke,2013年开源

最初由Yehuda Katz于2007年创建叫做SproutCore,后被Facebook收购,并于2011年更名为EmberJS

官方主页

https://angularjs.org/

https://reactjs.net/

http://emberjs.com/

Github

https://github.com/angular/angular.js

https://github.com/facebook/react

https://github.com/emberjs/ember.js

Bug 报告

https://github.com/angular/angular.js/issues

https://github.com/facebook/react/issues

许可证

MIT

MIT

BSD-3-Clause

被使用的热门网站

Youtube, Vevo, Freelancer, Istockphoto, Weather, Sky Store

Facebook, Instagram, Khan Academy, New York Times, Airbnb, Flipkart, Sony Lifelog

Apple Music, Yahoo!, LinkedIn, TinderBox, Netflix, Groupon

最适合使用的地方

构建高度活跃和交互式的Web应用程序。

数据设置频繁更改的大型Web应用程序

动态SPA

第一代 JS : 人工重绘界面

“我不知道要重新绘制哪里,你指出来吧”

第一代javascript 框架, 像Backbone.js, Ext JS,和 Dojo,第一次向浏览器引入了真实的数据模型,代替那些只在DOM上修饰的轻量级脚本。这也意味着,你第一次在浏览器上可以改变状态。数据模型的内容改变了,然后你把这些改变反应到用户界面上。

尽管这些框架都在架构上从模型中分离出了UI代码,可同步两者还是要靠你自己来完成。当变动发生时, 你可以得到一套事件,但是应该由你指出那一部分需要重新渲染,和具体怎么渲染。

澳门新葡萄京娱乐场 5

澳门新葡萄京娱乐场 ,在这种模型的性能方面上留给应用开发者很大的发展空间。既然你控制什么时候什么内容应当更新,只要你愿意, 你可以很好的调优它。简单的重新渲染页面上的大块区域,还是只更新页面上的需要更新的那一小部分,这经常是需要做出一些权衡。

虽然可以通过不少方面来对比这些框架的不同,但是最让人感兴趣的是它们分别如何管理状态(state)的。特别的,通过思考这些框架分别如何处理状态变化是很有用的。它们都提供了什么样的工具让你把这些变化呈现给用户?

AngularJS: 框架领域的冠军

Angular.js是一个开源的Web应用程序框架,具有由Google提供的Model-View-Controller(MVC)架构(Angular
1)和Model-View-ViewModel(MVVM)架构(Angular
2)。它是上面提到的三个框架中最古老的。因此,它拥有最大的社区。
Angular.js通过使用指令扩展HTML的功能来解决开发SPA(单页应用程序)的问题。此框架强调让你的app快速完成和运行。

Ember.js 数据绑定

“因为我控制着模型和视图, 我能精确的知道那些应该被重新绘制。”

可以人工的指出什么状态改变了需要重新渲染,是第一代javascript应用的复杂性的主要来源。大量的框架的目的就是消除这部分问题。Embe.js就是其中之一。

Ember 和 Backbone相似,当变动发生时,从模型往外发出事件。不同在于Ember还为事件的接受端提供一些功能。你可以把UI和数据模型绑定在一起,这意味着,有一个监听器附加到UI去侦听变更事件。这个监听器接到事件以后知道应该更新什么。

澳门新葡萄京娱乐场 6

这就产生了一个很有效的变更机制:通过一开始设置所有的绑定,这样以后同步的花费就变得少了。当某些东西变了,只有应用里面的那些确实需要改变的那一部分会变化。

这种方式里面,最大的折中是当数据模型发生变化,必须通知Ember知道这些变化。这就使你的数据必须要继承Ember的特定API,你要修改你的数据添加特别的set方法。你不能用foo.x=42 你必须用foo.set(‘x’,42),诸如此类。

将来,这个方式可能在 ECMAScript6
的到来后获益。它可用绑定方法来让Ember修饰一般对象,那么所有的与这个对象交互的代码不必再使用这种set的转换。

如何处理应用状态(app state)与用户界面(user
interface)之间的同步,长期以来都是用户界面开发如此复杂的主要原因。现在,我们有几个不同的处理方案。本文探索以下:Ember
的数据绑定,Angular 的脏检查、React
的虚拟DOM以及它与不可变数据结构(immutable data structures)之间的联系。

Angularjs的优缺点

优点:

  • 创建自定义的文档对象模型(DOM)元素。
  • 简单的UI设计和更改。
  • 在HTML文档中创建输入字段时,将为每个已渲染字段创建单独的数据绑定。Angular倾向于在重新渲染之前检查页面上的每个单个绑定字段的任何变化。
  • 依赖注入。
  • 简单路由。
  • 易于测试的代码。
  • 此框架利于HTML语法的扩展,并通过指令创建可重用的组件。
  • 强大的模板构建解决方案。在HTML属性中使用绑定表达式来驱动模板功能。Angular的模板引擎对DOM有着深入的理解,且其结构良好的模板减少了创建结果页面所需的代码总量。
  • 数据建模限于小数据模型的使用,以使代码简单易于测试。
  • 在渲染静态列表时速度快。
  • 伟大的代码重用(Angular库)。

缺点:

  • 指令API的复杂性。
  • 对于具有许多交互元素的页面,Angular变得缓慢。
  • 原始设计往往很慢。
  • 由于许多DOM元素,性能方面有问题。
  • 复杂的第三方集成。
  • 陡峭的学习曲线。
  • 范围很容易使用,但很难调试。
  • 路由受限。

注意。Angular 2的功能与上述不同。Angular 2不是从Angular
1重新设计的,它被完全重写了。两个版本的框架之间的巨大变化在开发人员之间引起了相当大的争议。

AngularJS:  脏检查

“我不知道什么改变了,我只是检查需要更新的所有一切”

和Ember相似,Angular的目标也是解决有变更以后的不得不手工重新渲染的问题。可是,它用的是另一个方式。

当你参考你的Angular 模板代码,比如 这个表达式{{foo.x}},Angular 不仅监听这个数据, 还创建一个这个值的观察器。在此之后, 不论应用中什么发生变动,Angular都检查观察器中的这个值和上一次比是不是变了。如果变了,就重新渲染这个值到UI。这个处理检查观察器的方式就叫 脏检查。

澳门新葡萄京娱乐场 7

这种检测方式的最大好处就是,你可以在模型中随便用什么,angular对此没有约束—它也不关心这个。不需要继承基础对象也不需要实现特定的API。

缺点方面就是既然数据模型没有内建的探测器来告诉框架什么变了,框架也就没办法知道是不是有变化,或者究竟哪里变了。这就意味着需要通过外部来检查模型变更,Angular就是这么做的:不论什么东西变了,所有的观察器都跑一遍:点击事件的处理,HTTP响应的处理,时间超时等等,都会产生一个摘要,这就是负责运行观察器的过程。

每次都运行所有的观察器听上去像是一个性能噩梦,但是它实际上是飞快的。这个通常是因为直到实际检测出一个改变,才会有DOM访问发生,而纯java script检查引用的消耗还是相当低的。但是当你遇到大的UI或者需要经常性的重新渲染,额外的优化措施就是必不可少的了。

象Ember,Angular也会受益于即将到来的标准:EMACScript7有Object.observe方法很适合Angular,它给你一个本地API来观察对象的属性改变。尽管这并不能满足Angular所有需求,因为观察器不仅仅观察简单对象属性。

即将到来的Angular2 也会带来一些有趣的关于前端更新检查的更新内容,最近有篇文章说道了这个Victor Savkin发表的文章 ,也可以看看这个Victor在 ng-conf 说的话

数据映射 Projecting Data

ReactJS: 在块上的新生儿

ReactJS是一个开源的JavaScript库,用于构建高性能的用户界面,专注于由Facebook引入和提供的惊人的渲染性能。React专注于模型视图控制器(Model
View
Controller)架构中的“V”。在React第一次发布后,它迅速吸引了大量用户。它是为了解决与其他JavaScript框架的常见问题——大数据集的高效渲染而创建的。

React: 虚拟DOM

“我不知道什么变了, 所以我将渲染一切,看看有什么不同”

React有很多有趣的特性,其中最有趣的就是虚拟DOM。

React和Angular相似,并不强制你使用一个模型API,你可以使用认为合适的任何对象和数据结构。那么,它是通过什么来保持UI在改变以后的更新呢?

React做的就是让我们退回到老的服务器端渲染的那些日子,我们可以简单的不管什么状态改变: 每当某个地方有变动发生,它就重新绘制整个UI。这个可以极大的简化UI代码。你并不关心怎么在React 组件里面维护状态。就像服务器端渲染,你渲染一次就行了。当一个组件需要改变,它就再次重新渲染。在第一次渲染和以后的数据更新渲染没有什么不同。

这个听上去极其没有效率。如果React仅仅做到此, 那当然就是这样了。然而,React使用了特殊的方式来重新渲染。

当React UI渲染的时候, 它首先渲染到一个虚拟DOM,它不是一个实际的DOM对象,而是一个轻量的纯javascript的对象结构,里面是简单对象和数组来表达真实的DOM对象。会有一个特殊处理过程来取得这个虚拟DOM,来创建能在屏幕上显示的真实的DOM元素。

澳门新葡萄京娱乐场 8

然后,当有改变的时候,一个新的虚拟DOM就从变化中产生。这个新的虚拟DOM反应了数据模型的新状态。React现在有2个虚拟DOM:新的和老的。它对这两个虚拟DOM用一个差异比较算法得到变动的集合。这些变动,也仅仅是这些变动会被应用到真实的DOM:新增加元素,元素的属性值改变等等。

澳门新葡萄京娱乐场 9

用React一个非常大的好处, 或者至少好处之一就是你不需要跟踪变动。无论新的结果里面何时何处有变动,你只需要重新渲染整个UI。虚拟DOM的差异检查方式自动为你做这些,这样就减少了很多的昂贵DOM操作。

我们首先讨论程序内部的状态与屏幕所看到的内容之间的映射。你把各种诸如
object,arrays,strings,以及 numbers 转换成一颗由诸如
texts、forms、links、buttons 和 images 组成的树状结构。在 Web
中,前者通常指 JavaScript 中的数据结构,而后者指的是DOM (Document
Object Model)

Reactjs的优缺点

优点:

  • 简单的界面设计和学习API。
  • 比其他JavaScript框架显着的性能提升。
  • 更快的更新。React使用最新的数据创建新的虚拟DOM和修补机制,并高效地将其与以前的版本进行比较,创建一个最小的更新部分列表,使其与真正的DOM同步,而不是每次更改时重渲染整个网站。
  • 服务器端渲染允许创建同构/通用web app。
  • 容易导入组件,尽管具有很少的依赖性。
  • 良好的代码重用。
  • 非常适合JavaScript调试。
  • 完全有可能用React增强Angular以增强麻烦的组件的性能。
  • 完全基于组件的架构。
  • JSX,一种JavaScript扩展语法,允许引用HTML并使用HTML标记语法来渲染子组件。
  • React本地库。

缺点:

  • 不是一个完整的框架,而是一个库。
  • 非常复杂的视图层。
  • Flux架构不同于开发人员习惯的范例。
  • 很多人不喜欢JSX。
  • 陡峭的学习曲线。
  • 将React集成到传统的MVC框架,如Rails中需要一些配置。

Om: 不可变数据结构

“我能很明确的知道那些东西没变”

尽管React的虚拟DOM技术已经很快了,但当你想渲染的页面很大或者很频繁的时候(超过 每秒60次),仍然会有性能瓶颈。

重新渲染整个(虚拟的和真实的)DOM这件事是真的没有办法避免的,除非你在变动数据模型的时候,做一些特别的控制,就像Ember那样。

一个控制变动的途径是不可变的持久数据结构。

他们看起来能够很好的和React的虚拟DOM方法一起协作, 就像David Nolen的工作用Om 库演示的那样,演示基于React 和 ClojureScript.。

关于不可变数据结构的说法是这样,顾名思义,你不能改变一个对象,你只能产生它的一个新的版本:当你想改变一个对象的属性的时候,如果你不能改变它,那么你只能产生一个新的对象并且设置为这个新的属性。因为持久化数据的工作方式,这个在实际工作中比听起来更有效。

当React组件状态都是用不可变数据组成的,变动检查就会变成这样的情形:当你重新渲染一个组件的时候,如果组件的状态仍指向上次你渲染过的同样的数据结构, 那么你可以跳过这次渲染,你可以继续使用这个组件上一次的虚拟DOM,以及整个以这个未变化组件为树枝节点的内部组件。这时候不需要继续深入检测了, 因为没有任何状态变化。

澳门新葡萄京娱乐场 10

就像Ember,那些像Om这样的类库不允许你在数据中使用任何老的javascript对象图。你只能用不可变数据结构从底层开始来构建你的模型才行。我会争辩说区别就是这一次你不用为了满足框架的要求来做这件事。你这么做就是简单因为这是一个更好的管理应用状态的办法。使用不可变数据结构的好处不是为了提示渲染的性能,而是简化你的应用架构。

Om和ClojureScript在组合React和 不可变数据结构上也是有用的,但他们不是必不可少的。可能仅仅使用纯粹React和一个像Facebook的Immutable-js那样的库也就足够了。Lee Byron,这个库的作者,在React.js Conf上给出了一个关于这个主题的精彩介绍。

我推荐你去看看Rich Hickey的持久化数据结构和引用管理,这也是一篇关于状态管理方法的介绍。

我在waxing poetic用过不可变数据结构有一段时间了。尽管我不能想当然地预见到它会被应用在前端UI架构。不过看起来这个事情正在发生,Angular团队的人也在做增加支持这些内容的事情。

我们经常称这个过程为渲染(rendering),你可以想象这个过程是从数据模型到用户界面的一个映射。当你把数据渲染成一个模板,你得到的是一个
DOM(或者说 HTML)。

EmberJS: 所有的繁重工作

EmberJS是一个用于创建单页面客户端Web应用程序的开源JavaScript应用程序框架,使用Model-View-Controller
(MVC)模式。此框架提供通用数据绑定和URL驱动方法,用于构建不同的应用程序,重点放在可扩展性。

Ember在2007年最初被发布时,叫做SproutCore。2011年,它被Facebook收购,并重命名为Ember。它结合了本地框架,例如Apple的Cocoa的经过验证的概念以及轻量级的敏感性。

总结

变动检测是UI开发中的中心问题,各种javascript框架都采用各自的办法来给出不同的解决方式。

EmberJS在当变动发生的当时就可以检测到改变,是因为他控制了数据模型API,当你调用API的做出数据改变时候,就会触发相应的事件。

Angular.js 在变动发生以后检测到改变,它的做法是重新跑一遍你注册在UI上的数据绑定,然后看是不是有值发生了改变。

纯React通过重新渲染整个UI到一个 新的虚拟DOM,然后和旧的虚拟DOM做比较来检测数据改变。发现有什么改变了,然后作为修订发送给真实DOM。

React和不可变数据结构可以作为纯React解决方案的加强版,它可以快速的标记组件树为未变化状态,因为在React组件内部是不允许状态改变的。不允许改变内部状态并不是为了性能原因,而是这么做对你的应用程序架构有积极影响。

这个过程本身已经足够简单了,数据模型到用户界面之间的映射,并不总是那么的琐碎。它基本只是一个接受输入然后直接输出的函数。

Embersjs的优缺点

优点:

  • 约定优于配置。Ember.js不是为应用程序中的各种路由提供详细的配置,而是喜欢遵循命名约定并自动生成结果代码,仅在不遵守约定的情况下指定配置。
  • 客户端渲染和结构到可扩展的web应用程序超出视图层。
  • URL支持。
  • Ember的对象模型利于键值观察。
  • 嵌套的UI。
  • 最小化DOM。
  • 适用于大型应用程序生态系统。
  • 强数据层与Java集成良好。
  • 完全成型的模板机制(Handlebars模板引擎构建在流行的Mustache
    模板引擎上)减少了编写的代码总量。它对DOM一无所知,而是依赖于直接的文本操作,动态地构建HTML文档。
  • 使用观察者来改变值,这将导致仅渲染更改的值。
  • 通过使用附件避免“脏检查”。
  • 更快的启动时间和固有的稳定性。
  • 性能焦点。
  • 友好的文档和API。

缺点:

  • Ember.js缺少控制器级别的组件重用。
  • 有很多过时的不再工作的内容和示例。
  • 陡峭的学习曲线。
  • Handlebars使用许多<script>标记来污染DOM,用作标记以使模板保持更新到模型。
  • 当走出其典型用途时会很麻烦。
  • Ember的对象模型实现膨胀Ember的整体大小并在调试时调用堆栈。
  • 最有见地和最重的框架。
  • 对于小项目而言过大。
  • 测试用例似乎模糊/不完整。

译者信息

译者:李炳辰,就职 HP软件开发部门,10年以上JAVA产品开发经验,熟悉C#,
Python,
 Nodejs。在互联网电商平台, 企业软件开发管理方面均有丰富的经验。目前兴趣在于前端开发,数据统计分析在金融业务方面的应用。

在我们需要考虑数据开始随着时间而变化的时候,这件事就变得更有挑战性了。当用户进行操作或者其它某些操作导致数据产生变化的时候,用户界面需要呈现出这些变化。而且,由于重新构建
DOM 树的代价是极其昂贵的,我们要尽可能产生小的影响。

比较Angularjs Vs Reactjs Vs Emberjs功能

特性

AngularJS

ReactJS

Ember.js

动态UI绑定

允许在纯对象或甚至属性级别使用UI绑定。可以同时更新多个绑定,而不需要耗时的DOM更新。

直截了当地将状态直接链接到UI。状态参数作为对象传递,并合并到React组件的内部参考状态。

使用Handlebars默认模板引擎。你必须在模型上使用特定的setter方法来更新绑定到UI的值,在Handlebars渲染页面的时候。其他绑定选项包括一个可能性以让你的Model在View和甚至另一个Model之间用一种要么单向要么双向的绑定模式。

可重复使用的组件

Angular组件称为“指令”,它们比Ember组件强大得多。它们能够创建你自己语义的和可重用的HTML语法。

在视图和控制器级别使用mixin,因此组件不必UI相关,并且可能只包含一些实用程序或甚至复杂的程序逻辑。

基于Widget的方法称为Ember组件。Handlebars布局和Ember的后端基础设施允许编写你自己的特定于应用程序的HTML标签。然后,可以在任何Handlebar模板中使用自定义元素。

路由

需要模板或控制器到其路由器配置,必须手动管理。

React不处理路由。但是有很多模块用于路由,如react-router,flow-router。

更强大的路由,以牺牲可增加的复杂性为代价。

意见

灵活的意见。给出一点灵活性来实现你自己的客户端堆栈。

灵活的意见。给出一点灵活性来实现你自己的客户端堆栈。

灵活的意见。给出一点灵活性来实现你自己的客户端堆栈。

数据绑定

双向

单向

双向

因为状态产生了变化,这比只是一次性渲染用户界面变得更加难。这就到了以下解决方案开始表演的时候了。

定义你的需求并使选定的框架发挥最大的作用

确定哪个框架适合你,只需要评估应用程序的需求以及每个框架的优势即可。这需要深入了解所考虑的每个框架的优点和缺点,以及它们如何在不同用例下竞争。所有框架都有很多共同点:开源,在许可证下发布,并创建具有MVC设计模式的SPA。它们都有视图,事件,数据模块和路由。然而,不同的JavaScript框架更适合不同类型的应用程序。

如果你正在决策创建一个web
app,对于长期支持和活跃的社区,Angular,React和Ember是最安全的。此外,目前Angular是这三个中最受欢迎的。你可以一站式使用。它是大型企业的首选框架。Ember是那些寻求全工具包含框架方法的人的最佳解决方案。Ember可以帮助你做出许多决策,所以你不必花时间研究和胶合库。由于Ember需要很长时间学习,所以它适合长期项目。React是上面提名的三个框架中最轻量级的。它的伟大在于一件事:渲染UI组件。许多人甚至将其与前面提到的框架进行配对。如果你需要逐渐现代化现有的代码库,那么这是一个合适的选择。

正如你看到的,没有明确的胜利者。有的框架比其他框架更适合特定的项目。当然,你也可以从几个不同的角度检查你的项目,包括成熟度,大小,依赖性,互操作性,功能等,并联系专业的前端web开发公司来构建完美的网站架构和网站设计,以便于更好地满足你的业务。

服务器渲染 Server-Side Rendering

宇宙是永恒不变的,没有任何变化

在 JavaScript 新纪元之前,你的 Web
应用的任何交互都会触发一趟服务器的环绕旅行。每一个点击和每一个表单提交都会卸载当前页面,一个请求发送到服务器,服务器响应一个新的页面,然后浏览器重新渲染。

这种方式不需要前端管理任何的状态(state)。就前端范畴而言,当一些事情发生了(后端返回的数据),整个过程就结束了。就算有状态,那也只是后端的范畴。前端只是由
HTML 和 CSS 构成,也许有时候会有些 JavaScript 撒在表面调味。

从前端来说,这是一个很简单的实现方式,但也是一个很慢的方式。每一个交互并不仅仅触发UI的重渲染,还涉及服务器的数据查询以及服务端渲染。

大多数人已经不再这样做了,我们可以在服务器端初始化我们的应用,然后转移到前端来做状态的管理(这也是isomorphic
JavaScript致力于的。)。已经有人在类似的更复杂的设计思想中取得成功。

JS第一代革命:手动重渲染

我不知道哪些需要渲染的,你来告诉我。

第一代革命的 JavaScript 框架,如:Backbone.js, Ext JS 以及
Dojo。第一次在浏览器端引入了数据模型(Data
Model)的概念,代替了以前那些直接操作 DOM
的轻量级的脚本代码。这意味着你终于可以在浏览器端管理状态了。当数据模型的上下文改变时,你需要做一些工作,让改变呈现在用户界面中。

这些框架的体系能分离你的模型和界面代码,但同时也留下了一大部分同步的工作给你。你可以监听某类事件的发生,但是你有义务去计算如何重新渲染以及如何落实到用户界面中。

基于这种模型,作为开发者,你需要考虑大量的性能问题。由于你能控制什么时候和怎么处理更新,你可以从中做任意的做一些调整。这经常会面临一些权衡:简单的处理导致大面积的页面更新,或者强性能的处理来更新一小块页面。

Ember.js: 数据绑定

由于我在控制你的模型和试图,我会确切知道如何重新渲染。

当应用状态改变的时候,手动处理渲染工作,无可避免的增加了复杂度。很多框架旨在解决这个问题,Ember.js就是其中之一。

Ember,像 Backbone
一样,当数据模型改变的时候会触发某个事件。不同之处在于 Ember
同时提供了一些方法来接收这些事件。你可以把 UI
绑定到数据模型中,这意味着有一个监听器绑定到了 UI
上。该监听器当收到事件的时候,知道如何更新 UI。

这是一个高效率的机制。尽管设置全部的监听器需要在初始化时多出一些工作,但是之后就能保证同步状态时的最小影响。当状态产生变化时,
只有真正需要更新的部分才会发生改变。

这种方式最大的牺牲是 Ember 需要时刻盯着数据模型。这意味着你需要通过
Ember 的 API
封装你的数据,以及你要更新数据的时候是使用foo.set(‘x’,42)而不是foo.x =
42,以此类推。

在未来 ES6 的 Proxies 可能会对这种模式产生一定的帮助。它让 Ember
可以通过装饰 object 来绑定那些监听器的代码。这就不用像传统方式那样重写
object 的 setter 方法了。

AngularJS:脏检查

我不知道什么更新了,所以当更新的时候,我只能检查所有的东西。

AngularJS 类似于
Ember,当状态改变的时候,必须人工去处理。但不同的是,AngularJS
从不同的角度来解决问题。

当你在 Angular 模板中引用你的数据,例如这样的语句{{foo.x}},Angular
不仅仅只是渲染数据,而且会这个特定的数据创建一个观察者。如此,只要你的应用中发生任何变化,Angular
都会检查这个观察者检视着的数据是否发生了改变。如果发生了改变,就会重新渲染这个数据对应的用户界面。这个过程称作脏检查(Dirty
Checking)。

这种监听改变的风格最大的好处就是,你可以在你的数据模型中使用任何姿势。Angular
对此没有任何限制,它不关心这个。没有基础的对象需要扩展,也没有 API
需要调用。

但坏处就是现在数据模型没有任何内建的检测手段告诉告诉框架哪些东西发生了改变,框架对是否或者哪里发生了改变没有任何洞察力。这意味着数据模型需要通过外部来监听改变,而
Angular
就是这样子做的:所有观察者在任何时间发生的任何改变,都需要被执行一次。点击事件,HTTP
响应,timeout 方法的触发,对于这些,观察者都需要执行一遍。

经常去执行所有观察者,这听起来像是性能的噩梦,但是它令人惊讶的快。这主要是因为在检查到任何改变之前,没有
DOM 的操作过程,而原生的 JavaScript
引用对象的检查平均消耗的性能是廉价的。但是当你要处理大量的 UI
或者经常性触发重新渲染,那么额外的性能优化手段就变得很有必要了。

Ember 和 Angular 都即将得益于即将到来的标准:ECMAScript7
的Object.observe功能,很适合 Angular。它提供了原生的 API
给你用来监听对象属性的变化。尽管这样,Angular 不需要支持所有的用例,因为
Angular 的观察者相对于简单的监听对象属性,可以做到的更好。

即将到来的 Angular 2 在检测改变这件事上带来了很多有趣的更新,最近Victor
Savkin 的一篇文章有介绍到。

关于这个主题,也可以看:Victor’s ng-conf talk

React: 虚拟 DOM

我不知道到底哪些发生了变化,所以我只能重新渲染所有东西,然后看一下有哪些不同。

React 有很多有趣的特性,但是我们讨论的最有趣的特性是虚拟 DOM。

像 Angular 一样,React
不会对数据模型进行限制,而是让你使用你认为合适的任何对象和数据结构。那么,它是如何在存在改变的情况下使
UI 保持最新呢?

React
所做的是有效的把我们带回服务器渲染时代,当时我们还不关心状态变化:每当某处发生改变的时候,它会从头重新渲染整个
UI。这可以显著的简化 UI 的代码。大部分情况,你不会关心如何在 React
中维护状态。就像服务器渲染一样,渲染一次就算了。当组件需要变更时,它只能再次重新渲染。组价的初始化渲染和更细它的数据之间,没有任何区别。

如果故事就这么结束的话,它看起来的确非常低效。然而,React
在重新渲染方面,有点特殊。

当 React 进行重新渲染时,它首先会渲染到虚拟 DOM 中,这不是一个实际的 DOM
对象的图。而是一个轻量级的,有纯粹的 object 和 array 组成的纯 JavaScript
的数据结构,它代表着一个真实的 DOM 对象的图。

然后,一个独立的进程会根据虚拟 DOM 的结构来创建那些在屏幕上显示的真实的
DOM 元素。

之后,当变化发生的时候,一个新的虚拟 DOM
会被从头到尾创建出来。这个新的虚拟 DOM 将映射出数据模型的新的状态。现在
React 在手上有两个虚拟 DOM:一个新的,一个旧的。然后会对两个虚拟 DOM
进行一个对比算法,得出它们之间的一组变化。有且只有这些更改会被应用到真实
DOM 中:此元素已添加,此属性以改变,等等。

所以 React
起码至少有一个好处,就是你不用追踪变化了。你只需要每次重新渲染整个 UI
,然后无论改变了什么最终都会得到相应的结果。React 的虚拟 DOM
对比算法,能让你做到这一点,并且最大限度的节省昂贵的 DOM 操作。

Om: 不可改变的数据结构

我确切的知道哪些没有改变。

虽然 React 的虚拟 DOM 相当的块,但是当你的 UI
非常庞大或者经常性渲染的时候(例如:每秒高达 60 次),它依然会面临瓶颈。

问题在于,真的没办法每次都渲染出整个虚拟
DOM,除非你引入一些方法来控制数据模型的改变,就像 Ember 做的一样。

一种控制变化的办法是不可改变的,持久化的数据结构。这些看起来似乎很适合使用在
React 的虚拟 DOM 中,正如 David Nolen 在Om库中所做的工作那样,一个构建于
React 和ClojureScript之上的库。

有一点关于不可改变数据结构的是,顾名思义,你永远不能改变它,只能产生新的版本。如果你想改变一个对象的属性,你只能新建一个对象和属性,因为你不能改变已经存在的那一个。由于持久化数据结构的工作方式,这比听起来更加有效率。

这意味着在检测变化方面,当 React
组件都只由不可变数据组成的时候,只有一个逃生窗口:当你重新渲染一个组件时,组件的状态仍然指向上次渲染时的相同数据结构,你就可以跳过这次重新渲染。你可以使用该组件的先前的虚拟
DOM
以及源自该组件的整个组件树。没有必要进一步挖掘,因为在这个状态中所有东西都不可能改变。

就像 Ember 一样,像 Om 的这种库不允许在你的数据中使用旧的 JavaScript
对象图。你必须在不可变数据结构中构建你的数据模型,从而才能在其中得到好处。我会赞同这样的做法,因为这一次你这样做并不是为了取悦框架本身。你这样做只是因为这是一个又简单又好的方式去管理你的应用状态。使用不可变数据结构的主要好处,并不是提升渲染性能,而是简化你的应用结构。

虽然 Om 和 ClojureScript 已经讲 React
和不可变数据结构融合起来,但是他们并不是圈子里面的唯一组合。而仅仅使用
React 和 Facebook 的Immutable-js是完全可能的。这个库的作者 Lee Byron
在最近的一次 React.js 为主题的会议中进行了一个精彩的介绍。

同时我建议看一下 Rich Hickey’s 的Persistent Data Structures And Managed
References, 去了解状态管理的方法。

我自己现在一直在为不可变数据数据结构写诗,但我绝对没有预见到它会进入前端
UI 框架行列。它看起来似乎不遗余力的发生着,而 Angular
的人正在为支持这个而努力着。

总结

检测变化时 UI 开发中的核心问题,而 JavaScript
框架们以各种方式解决这个问题。

EmberJS 能在它们发生变化的时候检测到,因为它控制着你的数据模型
API,并且可以在你调用它的时候触发事件。

Angular.js 是事后进行检测, 它通过重新运行你已经在 UI
中注册的所有数据绑定,来检测它们的值是否已经发生变化。

React 的检测方法是通过把整个 UI 重新渲染成一个虚拟
DOM,然后和旧的版本进行对比。无论改变了什么,都可以给真实 DOM
打上个补丁。

React 和 不可变数据结构的组合,对比纯粹的 React
有所增强,通过快速的在组件树中标记不可变的节点。因为组件内的变化是不被允许的。但是,这不是主要出于性能的原因,而是由于它对整个应用程序体系结构有积极的影响。

原文链接:Changes and Its detection of JavaScript Framework

发表评论

电子邮件地址不会被公开。 必填项已用*标注