• Angular.js vs Ember.js


    http://segmentfault.com/a/1190000000362479


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

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

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

    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>

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

    <p id="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>
      <li ng-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() {    return this.get('width') * this.get('height');
      }.property('width', 'height')
    });

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

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

    var room = App.Room.create({ 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() {  return this.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的属性,你必须使用getter和setter。这意味着需要一点点额外的代码,但你收获的是和模板中JavaScrip一样的好处:用函数替换primitive可以工作!

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

    console.log(room.inhabitant.name);

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

    // 输出 undefinedconsole.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端再次获取数据!)。

    你是否曾经也纠结于Angular.js和Ember.js的选择,欢迎分享你的经验和心得。


  • 相关阅读:
    Algorithm Gossip (48) 上三角、下三角、对称矩阵
    .Algorithm Gossip (47) 多维矩阵转一维矩阵
    Algorithm Gossip (46) 稀疏矩阵存储
    Algorithm Gossip (45) 费氏搜寻法
    Algorithm Gossip (44) 插补搜寻法
    Algorithm Gossip (43) 二分搜寻法
    Algorithm Gossip (42) 循序搜寻法(使用卫兵)
    Algorithm Gossip (41) 基数排序法
    Algorithm Gossip (40) 合并排序法
    AlgorithmGossip (39) 快速排序法 ( 三 )
  • 原文地址:https://www.cnblogs.com/danghuijian/p/4399909.html
Copyright © 2020-2023  润新知