Angular.js vs Ember.js

简介: Discourse的推出在整个社区赚足了眼球。Discourse选择Ember.JS作为前端MVC框架,其开发者Robin Ward写了博客分享选择Ember.js的理由

Discourse的推出在整个社区赚足了眼球。Discourse选择Ember.JS作为前端MVC框架,其开发者Robin Ward写了博客分享选择Ember.js的理由

最近Quora网站上也有人提问,Angular.jsEmber.js,哪个JavaScript框架更好?

这个问题得到了热烈的回应,两个框架的开发者都参与了。

image.png

Angular.js 拥抱 HTML/CSS

Misko Hevery(Angular.js的开发者之一)回答了这一问题,他的主要观点如下:

在HTML中加入太多逻辑不是好做法。Angular.js只放置绑定,而不是逻辑,建议把逻辑放入控制器中。但绑定同样是信息,通常,这些信息可以放在三个地方:

  • 代码。但这使得程序模块化很成问题,因为HTML与代码紧密耦合,要想重新组成一个应用程序非常困难。
  • HTML。这正是Angular.js所做的。除了放置绑定信息外,你不应该在HTML中做任何事情。任何逻辑都不应该放在这里,否则会导致各种问题。我认为Angular.js做的绑定相当好。
  • 元数据文件:不知道是否有人这样做,如果这么做,就产生了一个新问题,你需要在代码中把HTML和元数据结合起来。


Angular.js的独特之处在于它拥抱HTML/CSS,其他一些框架提供了它们自己的API,偏离了HTML。Angular.js在所有框架中是能体现声明式编程范式的。声明式编程非常适合用来编写用户界面,编写逻辑则交给JavaScript。

Angular.js允许你扩展HTML,所以你在使用Angular.js过程中遇到的任何问题都可以很容易地克服。


Ember.js 更社区化、更适合生产环境

Tom Dale(Ember.js的开发者之一)仔细比较了Angular.js和Ember.js.


Ember.js 由来

Dale首先来介绍了Ember.js项目的由来。从2009年开始,我就一直在苹果公司参与 SproutCore 项目的开发,SproutCore 是一个 类似Cocoa的JavaScript开源框架,后来演变成了iCloud。当时,我身边是一些世界上最好的Cocoa开发者。

问题在于,客户端应用程序这么多年来似乎并没有真正新的突破。自80年代以来就一直遵循的基本模型——代码运行在本地计算机上,从网络上获取数据,然后在本地处理,并显示在屏幕上;而如今唯一改变的是——代码运行在浏览器的沙箱环境中,然后加载所需的“二进制”文件,而不是由用户安装到硬盘上的文件。


在考虑这些问题时,我首先去想,在我们之前,人们已经做了什么?我认为框架的作用无需争辩。比如Cocoa,无论在Mac还是iOS上,Cocoa都可以让开发者轻松编写受用户喜爱的应用程序。


我们希望开发者能够创建雄心勃勃的、能够与本地应用竞争的Web应用。要达成这一目标,开发者需要先进的工具和正确的理念。

Ember.js刚开始开发的时候,我们从Cocoa等本地应用程序框架引入一些概念,不过后来我们觉得这些概念弊大于利,或者说它们和Web应用程序格格不入。因此,我们开始从Ruby on Rails和Backbone.js 等开源项目中寻找灵感。


Ember.js 更适合生产环境

在Dale看来,与Ember.js相比,Angular.js更像一个研究项目。比如,在学习文档中,Ember.js主要讨论模型、视图和控制器,而Angular.js指南要求你去学习一些类似于范围、指示符和transclusion方面的内容等。


一些大公司已经在Ember.js上投入了大量时间和精力,比如ZenDesk对Backbone.js失望后使用Ember.js重写,Square的整个Web层面也是基于Ember.js的,Groupon的移动版Web应用也是使用Ember.js开发的。此外,还有很多创业公司通过Ember.js获得了成功,并开始回馈Ember.js社区。


而目前所看到使用Angular.js开发的大多数应用程序只是演示项目,或是Google的内部项目。


Ember.js 更社区化

Yehuda(Ember.js开发者之一)和我也一直积极邀请真正的用户参与Ember.js框架的设计和维护,这可以确保我们在Ember.js中添加的功能对于实际开发是有用的。

事实上,在过去的几个月中,大多数Ember.js开发工作都是由Ember.js社区的核心贡献组完成的,他们来自不同的公司。如果Yehuda和我哪天有什么事情,或者我们的公司倒闭了,Ember.js还将会持续发展。这是一个真正的社区项目,而不是“Google”项目。


模板

Angular.js使用有语义意义的属性(比如data-ng-repeat)来实现模板。


而Ember.js使用Handlebars来描述HTML。


Handlebars语法(类似{{\#each}}),和Angular.js那样使用额外的属性做法,哪种更美观,是一个见仁见智的问题。我个人认为,HTML属性有点杂乱,可读性要差些。当然,如果Ember.js不存在,而我又必须使用一个使用了数据属性的框架,那么我会考虑Angular.js。


抛开美观不谈,我相信,Ember.js使用基于字符串的模板有如下优势:

  • 模板可以在服务器上预编译。这意味着减少启动时间,也意味着渲染一个模板可以像调用一个函数一样简单。而Angular.js需要你在应用程序启动时遍历整个DOM,你的应用程序越大,启动速度越慢。
  • 如果你想在服务器上渲染你的应用程序(方便搜索引擎索引或让首次加载时显示速度更快),Angular.js需要启动整个浏览器环境,例如PhantomJS,这是资源密集型的。而Handlebars是100%的JavaScript字符串,所有你需要的只是node.js或Rhino之类的东西。
  • 如果你的应用程序变得越来越大,那么字符串模板可以很容易地分割和惰性加载。


此外,Handlebars只让你绑定属性,而Angular.js允许你嵌入实时更新的任意表达式。刚开始很多人认为这是Ember.js的局限性,但实际上:


  • 使用JavaScript来创建可计算属性非常容易,它可以包含任意表达式。Ember.js只要求你指定你的依赖,这样在更新时可以智能些。
  • 一旦有新的变化,Angular.js就必须重新计算这些表达式,这意味着需要在你的应用程序中绑定更多的元素,因此速度会变慢。
  • 因为Ember.js只允许你绑定属性,我们将可以很容易地利用ECMAScript 6的性能优势,如Object.observes。由于Angular.js发明了自己的带有 自定义解析器的JavaScript子集,这对于浏览器来说,优化代码变得比较困难。


Angular.js通常依靠一种叫做“dirty checking”的机制来确定对象是否已进行更改。在你扫描每个对象和其所有绑定属性时,比较当前值和之前已知的值。如果它发生了变化,就需要更新绑定。但Angular.js开发者非常聪明,使用“脏检查”,你不需要使用accessors。你可以用person.name = "Bill"来代替person.set('name', "Bill"),就像在Ember.js 或 Backbone.js中的一样。然而,使用“脏检查”,你无法一次有超过2000个绑定对象。


我认为这很好地说明了Ember.js 和 Angular.js理念上的区别。Ember.js 和 Angular.js都力求简单和易用。而Ember.js使你不必担心代码中是否有超过2000个绑定。如果你正在编写大型应用程序,那么你已经解决了你所担心的最大的事情。对于中小规模的应用程序来说,Angular.js同样是伟大的,因为这些应用程序不会触及Angular.js的限制区。

在Ember.js中,我们总是希望利用浏览器和语言中的新功能,以便使事情变得更容易。例如,一旦ES6中 代理对象(proxies)可用,我们不会再要求你使用get()set()

所以这就是为什么我认为——如果你想构建雄心勃勃的应用程序,你应该选择Ember.js。

此外,在开发过程中,我们对于性能方面和如何利用语言新特性方面也考虑了很久。Yehuda Katz和我一起开发Ember.js,他同时也是TC39(负责JavaScript下一个版本的制定)的成员,在此方面相当有经验。


Angular.js符合Web的未来

angularjs_scaffold的开发者Patrick Aljord也参与了讨论。

angularjs_scaffold是基于Angular.js编写的针对scaffolding视图的Rails插件。

Patrick Aljord阐述了选择Angula.js的理由。


事实上,我原本打算在项目中使用Ember.js,因为我比较信赖Yehuda(Ember.js开发者之一),他在Rails和jQuery方面的工作很杰出。但是Ember.js中随时会变化的API和匮乏的文档,使我一再推迟使用它。偶然发现了Angular.js之后,我被它吸引了。

正如Tom Dale(Ember.js开发者之一)所说,Ember.js受到了Cocoa 和Rails启发。问题在于,在Ember.js下工作,我并没有真正感觉到像在写一个Web应用程序。而Angular.js让我感觉像在写一个Web应用程序,它真正支持所有的Web概念,并以一种非常自然的方式来扩展HTML。


事实上,Angular.js并没有使用自己的对象或重写JS方法,当你使用Angular.js时,你就使用了纯JS,并且Angular.js实现的许多概念都将直接进入下一个版本的Javascript中。

学习Angular.js,就意味着学习未来的Javascript,而学习Ember.js,你只是学习到了Ember的特有概念。


来看个例子。HTML是伟大的,因为它是声明式的,如果想要定义一个段落,你只需写如下代码:

<p>Hello world</p>

但是如果你想非常动态地实现?你需要通过类似于下面的代码来引导浏览器:

<pid="greeting1"></p>

<script>

   var isIE = document.attachEvent;

   var addListener = isIE

     ? function(e, t, fn) {

         e.attachEvent('on' + t, fn);}

     : function(e, t, fn) {

         e.addEventListener(t, fn, false);};

   addListener(document, 'load', function(){

     var greeting = document.getElementById('greeting1');

     if (isIE) {

       greeting.innerText = 'Hello World!';

     } else {

       greeting.textContent = 'Hello World!';

     }

   });

</script>

来看看Angular.js如何实现:

<p>{{hello}}</p>

再来看一个示例,如果你要遍历一个数组,只需:

<ul>

 <ling-repeat="element in array">element</li>

</ul>

这个语法看起来像新的 MDV标准。这看起来比Ember.js更加简洁。另外,Angular.js被优化得非常快,开发团队通过如下措施来实现:

  • 脏检查
  • 只检查当前视图
  • 只在变化发生时检查
  • 通过和Chrome团队协作来利用JIT

一些显示Angular.js的速度要快于Ember.js,例如 Angular VS Knockout VS Ember

Angular.js未来会拥有可复用的组件,这允许你编写非常简洁的代码。这是Web的未来。

此外,Angular.js还拥有一个庞大的社区和 大量的贡献者


AngularJS 的缺陷

Discoures开发者Evil Trout在自己的博客上对比了这两个框架。Evil Trout列举了AngularJS的一些缺陷:


“简单”的陷阱

现在我知道现在为什么AngularJS势头越来越大:因为它很简单。一个精简了许多高级概念与实现的框架,会因此变得更容易学习。如果要我给这些框架排个名次的话,Angularjs大概是介于Backbone和Ember之间。


如果您的应用程序是简单,那么使用简单的框架想来也是极好。但如果你是要构建大规模的应用程序的话就要谨慎选择了,而且要进行长期的维护。


比起AngularJS,Ember有更多需要学习的概念。当你由于Ember的复杂性放弃它的时候,请考虑为什么开发人员添加了这些所谓多余的东西。事物的存在总有它的道理。

你会发现Ember是一个充满概念与实用的工具集,如果你想建立一个庞大的、可维护的应用程序。它的API侧重于通过一个健全的方式帮助你结构代码。Ember有一些AngularJS框架没有的理念。


AngularJS的Model层

AngularJS吹捧自己为MVC框架,或者是MVW(Model View Whatever)框架。

很明显的,AngularJS的View层是:让你通过ng-*属性和handlebars风格的{{variable}}表达式来标注HTML文档。Controller层是JavaScript类通过ng-controller属性的元素绑定DOM元素。


特别是,如果你有一个Server端的MVC背景, AngularJS的Model层该是什么样的,这点并不明确。而且在AngularJS中,并没有标准来定义了一个模型应该是Model基类,还是一个component(组件)或interface(接口)。

在一个AngularJS的Controller层中,有一个$scope对象。所有附加的数据通过它绑定在你的HTML模板:

function SomeCtrl($scope) {

 $scope.countries = ['can', 'usa', 'fra', 'jap'];

 $scope.user = {name: "Evil Trout"};

 $scope.age = 34;

 // 我们的模板现在可以渲染 {{age}}, {{user.name}} 和很多国家了!

}


根据AngularJS的文档,在AngularJS中所有声明在$scope上的对象都是一个Model,不仅仅对象和数组是Model,连primitive也是!

在模板中,AngularJS提供给你所需的工具来管理单一数据来源。这是一个叫数据绑定的概念。如果我们创建了一个模板中有一个AngularJS表达式{{age}},我们说这绑定于$scope.age这个Model。如果你在一个模板中多处书写{{age}},并在Controller层中执行 $scope.age = 40,所有绑定的值都会同时更新。

然而,如果你真正想表达单一数据来源,你所需要的是在二级的数据绑定,就在你的数据Model本身。换句话说,AngularJS的短板在于:只允许将数据绑定在$scope和模板之间,而不是在Javascript代码的结构中。

在Ember中,所有Model扩展在 Ember.Object基类上。因此你能够在Model内部声明对象之间的关系。例如:

App.Room = Ember.Object.extend({

 area: function() {

   returnthis.get('width') * this.get('height');

 }.property('width', 'height')

});

在这里,我们已经创建了一个名为Room的Model。我们已经声明area为计算属性。property通知Ember,Roomarea属性取决于其widthheight属性。

创建一个Room Model的实例还是很容易的:

varroom = App.Room.create({width: 10, height: 5});

现在我们可以创建一个模板:

<p>Room:</p>

<p>{{width}} ft.</p>

<p>{{height}} ft.</p>

<p>{{area}} sq ft.</p>

相应的Ember会正确地渲染这些属性。在这种情况下,area不得不与 width和 height同步更新。如果这两个属性的变化,area将自动更新。

因为在AngularJS中,Model都是普通的Javascript对象,AngularJS没有计算属性。但是,您可以在相应的对象上通过函数模拟来实现:

var Room = function(args) {

 this.width = args.width;

 this.height = args.height;

}

Room.prototype.area = function() {

 returnthis.width * this.height;

}

要访问我们的房间的面积,你必须添加一组括号area()调用:

<p>Room:</p>

<p>{{width}} ft.</p>

<p>{{height}} ft.</p>

<p>{{area()}} sq ft.</p>

这显示了Ember和AngularJS之间的关键区别。Ember遵循统一访问原则 。 在一个Ember模板中,无论你所访问的是计算属性还是primitive,表达方式看上去是一样的。而在AngularJS中,必须明确区分函数。

这可能会导致可维护性的恶梦。在一个大型软件项目中,随着时间的推移,你将不可避免地要迭代原有的代码。在Ember中,你可以轻而易举地做到这点;而在AngularJS你就不得不更新每一个绑定于这个Model的模板。


使用getter和setter

这个相关的权衡是值得讨论的,你可能已经注意到,在Ember中,为了访问一个Model的属性,你必须使用gettersetter。这意味着需要一点点额外的代码,但你收获的是和模板中JavaScrip一样的好处:用函数替换primitive可以工作!

使用gettersetter的另一个好处是可以保证安全。思考下面的代码:

console.log(room.inhabitant.name);

如果inhabitant不存在,会发生什么事? 你会得到一个JavaScript错误。而在Ember中,你会得到undefined返回值,这使得你更容易编写健壮的代码。

// 输出 undefined

console.log(room.get('inhabitant.name'));

复用对象实例

AngularJS相比Ember来说更难复用对象实例。例如在Ember模板中,可以通过{{linkTo}} helper链接到另一个路由:

<ul>

{{#each user in users}}

 <li>{{linkTo'users.show' user}}Show {{username}}{{/linkTo}}</li>

{{/each}}

</ul>

这里,我们遍历一个用户列表,并创建一个链接。当你的鼠标悬停在链接上,如果你的路由配置正确,你会看到一些/users/show/123之类的文字。 然而,你点击链接时,Ember实际上通过你所配置的其他路由到达相关的用户页面。

Ember的路由器足够聪明,如果这个用户的id已经在内存中,Ember不会重复解析。而在AngularJS中,每次访问路由,它传递一个id并在Controller层进行解析。

一个长存的浏览器应用程序的巨大优势之一是可以重用的对象,就像上面那个用户导航的例子。AngularJS并没有遵循这一理念,它鼓励你扔掉它,然后再次找到它(可能是从Server端再次获取数据!)。

相关文章
|
5天前
|
开发框架 前端开发 JavaScript
React、Vue.js 和 Angular主流前端框架和选择指南
在当今的前端开发领域,选择合适的框架对于项目的成功至关重要。本文将介绍几个主流的前端框架——React、Vue.js 和 Angular,探讨它们各自的特点、开发场景、优缺点,并提供选择框架的建议。
25 6
|
15天前
|
前端开发 JavaScript API
React、Vue.js 和 Angular前端三大框架对比与选择
前端框架是用于构建用户界面的工具和库,它提供组件化结构、数据绑定、路由管理和状态管理等功能,帮助开发者高效地创建和维护 web 应用的前端部分。常见的前端框架如 React、Vue.js 和 Angular,能够提高开发效率并促进团队协作。
34 4
|
28天前
|
前端开发 JavaScript 开发者
Express.js与前端框架的集成:React、Vue和Angular的示例与技巧
本文介绍了如何将简洁灵活的Node.js后端框架Express.js与三大流行前端框架——React、Vue及Angular进行集成,以提升开发效率与代码可维护性。文中提供了详细的示例代码和实用技巧,展示了如何利用Express.js处理路由和静态文件服务,同时在React、Vue和Angular中构建用户界面,帮助开发者快速掌握前后端分离的开发方法,实现高效、灵活的Web应用构建。
38 3
|
2月前
|
开发者 Java 存储
JSF 与 CDI 携手共进,紧跟技术热点,激发开发者情感共鸣,开启高效开发新征程
【8月更文挑战第31天】JavaServer Faces (JSF) 与 Contexts and Dependency Injection (CDI) 在 Java EE 领域中紧密协作,助力开发者高效构建现代 Web 应用。JSF 凭借其丰富的组件库和页面导航功能受到青睐,而 CDI 则优雅地管理对象生命周期并实现依赖注入。两者结合,不仅简化了复杂企业应用的开发,还实现了松耦合架构,增强了代码的灵活性、可维护性和可扩展性。通过示例展示了如何利用 CDI 将业务服务对象注入 JSF Managed Bean,以及如何在不同页面间共享数据,突显了这一组合的强大功能。
33 0
|
2月前
|
JavaScript 前端开发 C++
【Vue.js的终极对决】服务端渲染VS客户端渲染:一场关乎速度与SEO的生死较量!
【8月更文挑战第30天】Vue.js 是一个流行的 JavaScript 框架,支持服务端渲染(SSR)和客户端渲染。SSR 在服务器生成完整 HTML,有利于 SEO 并缩短首屏加载时间,但增加服务器负担;客户端渲染则在浏览器生成页面,提升交互性,降低服务器负载。本文通过代码示例对比两者优劣,并提供选择指南,帮助开发者根据 SEO 需求、交互性需求及服务器资源等条件,选择合适的渲染方式,从而优化应用性能和用户体验。
45 0
|
2月前
|
存储 JavaScript 数据库
如何使用 Socket.IO、Angular 和 Node.js 创建实时应用程序
如何使用 Socket.IO、Angular 和 Node.js 创建实时应用程序
20 0
|
2月前
|
前端开发 JavaScript 开发者
如何在 Angular 中使用 ng2-charts 来使用 Chart.js
如何在 Angular 中使用 ng2-charts 来使用 Chart.js
34 0
|
3月前
|
JavaScript 前端开发 数据可视化
js 实现动画的两种方案对比:setTimeout vs RAF (requestAnimationFrame)
js 实现动画的两种方案对比:setTimeout vs RAF (requestAnimationFrame)
56 2
|
4月前
|
JavaScript 前端开发 API
ECMAScript vs JavaScript: 理解两者间的联系与区别
ECMAScript vs JavaScript: 理解两者间的联系与区别
|
3月前
|
JavaScript C++
js【详解】原型 vs 原型链
js【详解】原型 vs 原型链
35 0

热门文章

最新文章