“在AngularJS中思考”如果我有一个jQuery背景?

假设我熟悉在jQuery中开发客户端应用程序,但现在我想开始使用AngularJS 。 你能描述一下必要的范式转变吗? 这里有几个问题可以帮助你构build一个答案:

  • 我如何构build和devise不同的客户端Web应用程序? 最大的区别是什么?
  • 我应该停止做什么/使用什么? 我应该开始做什么/使用?
  • 有没有服务器端的考虑/限制?

我不在寻找jQueryAngularJS之间的详细比较。

1.不要devise你的页面,然后用DOM操作来改变它

在jQuery中,您devise一个页面,然后使其变为dynamic的。 这是因为jQuery被devise用于增强,并且从这个简单的前提已经令人难以置信地增长。

但是在AngularJS中,你必须从头开始考虑你的架构。 不是从思考“我有这块DOM,而是想让它做X”开始,你必须从你想完成的事情开始,然后去devise你的应用程序,然后去devise你的视图。

2.不要用AngularJS来扩充jQuery

同样,不要从jQuery做X,Y和Z这个概念开始,所以我只需要在模型和控制器上添加AngularJS。 当你刚刚起步的时候,这真的很诱人,所以我总是build议新的AngularJS开发者根本不使用jQuery,至less在他们习惯了“Angular Way”之前。

我在这里和邮件列表上看到了很多开发人员用这些150或200行代码的jQuery插件创build了这些精心devise的解决scheme,然后将这些解决scheme粘贴到AngularJS中,使用一系列callback和$apply来混淆和复杂化; 但他们最终得到它的工作! 问题是,在大多数情况下,jQuery插件可以在AngularJS中的一小部分代码重写,突然间一切都变得易于理解和直接。

底线是这样的:在解决时,先“在AngularJS中思考”; 如果你不能想出解决scheme,就向社区问问。 如果毕竟没有简单的解决scheme, 那么请随时联系jQuery。 但是,不要让jQuery成为拐杖,否则你将永远无法掌握AngularJS。

3.总是从架构的angular度思考

首先知道单页面应用程序是应用程序 。 他们不是网页。 所以我们需要像服务器端开发人员一样思考,除了像客户端开发人员一样思考。 我们必须考虑如何将我们的应用程序划分为单个的,可扩展的,可testing的组件。

那么你怎么做呢? 你如何“在AngularJS中思考”? 这里有一些一般的原则,与jQuery形成鲜明对比。

这个观点是“正式logging”

在jQuery中,我们以编程方式更改视图。 我们可以将下拉菜单定义为一个ul如下所示:

 <ul class="main-menu"> <li class="active"> <a href="#/home">Home</a> </li> <li> <a href="#/menu1">Menu 1</a> <ul> <li><a href="#/sm1">Submenu 1</a></li> <li><a href="#/sm2">Submenu 2</a></li> <li><a href="#/sm3">Submenu 3</a></li> </ul> </li> <li> <a href="#/home">Menu 2</a> </li> </ul> 

在jQuery中,在我们的应用程序逻辑中,我们可以用类似的方式来激活它:

 $('.main-menu').dropdownMenu(); 

当我们只看这个视图时,这里并没有什么明显的function。 对于小应用程序,这很好。 但是,对于不平凡的应用程序,事情很快就会变得混乱,难以维护。

然而在AngularJS中,这个视图是基于视图的function的正式logging。 我们的ul声明看起来像这样:

 <ul class="main-menu" dropdown-menu> ... </ul> 

这两个人做同样的事情,但在AngularJS版本中,任何看着模板的人都知道应该发生什么。 每当开发团队的新成员join时,她可以看看这个,然后知道有一个叫做dropdownMenu的指令。 她不需要直觉正确的答案或筛选任何代码。 这个看法告诉我们应该发生什么。 更干净。

AngularJS的新手开发人员经常会问一个问题:我如何find一个特定types的所有链接,并向它们添加一个指令。 当我们回复时,开发者总是大吃一惊:你没有。 但是,你不这样做的原因是,这就像半jQuery,一半AngularJS,并没有好处。 这里的问题是开发人员正在尝试在AngularJS的上下文中“做jQuery”。 这永远不会工作。 这个观点正式logging。 在一个指令之外(更多在这个下面),永远不会改变DOM。 指令在视图中应用,所以意图是明确的。

记住:不要devise,然后标记。 你必须build筑师,然后devise。

数据绑定

这是迄今为止AngularJS最棒的function之一,并且削减了我在上一节中提到的各种DOM操作的需求。 AngularJS会自动更新你的视图,所以你不必! 在jQuery中,我们响应事件,然后更新内容。 就像是:

 $.ajax({ url: '/myEndpoint.json', success: function ( data, status ) { $('ul#log').append('<li>Data Received!</li>'); } }); 

对于一个看起来像这样的看法:

 <ul class="messages" id="log"> </ul> 

除了混淆之外,我们也有和前面提到的意图一样的问题。 但更重要的是,我们必须手动引用和更新DOM节点。 如果我们想删除一个日志条目,我们也必须针对这个DOM进行编码。 我们如何testing除DOM之外的逻辑? 而如果我们想改变演示呢?

这有点凌乱和一点点脆弱。 但是在AngularJS中,我们可以这样做:

 $http( '/myEndpoint.json' ).then( function ( response ) { $scope.log.push( { msg: 'Data Received!' } ); }); 

我们的观点可以像这样:

 <ul class="messages"> <li ng-repeat="entry in log">{{ entry.msg }}</li> </ul> 

但就此而言,我们的看法可能是这样的:

 <div class="messages"> <div class="alert" ng-repeat="entry in log"> {{ entry.msg }} </div> </div> 

现在,我们使用Bootstrap警报框而不是使用无序列表。 而我们从来没有改变控制器的代码! 但更重要的是,无论日志在哪里如何更新,视图都会改变。 自动。 整齐!

虽然我没有在这里显示,但数据绑定是双向的。 所以这些日志消息也可以在视图中进行编辑: <input ng-model="entry.msg" /> 。 有许多欢乐。

独特的模型层

在jQuery中,DOM有点像模型。 但是在AngularJS中,我们有一个独立的模型层,可以以任何我们想要的方式进行pipe理,完全独立于视图。 这有助于上述数据绑定,保持关注的分离 ,并引入了更高的可testing性。 其他答案提到了这一点,所以我只是把它留在那。

关注点分离

以上所有内容都与这个主题相关:将您的疑虑分开。 你的观点是应该发生的正式logging(大部分); 你的模型代表你的数据; 你有一个服务层来执行可重用的任务; 你做DOM操作并用指令增加你的视图; 而且你用控制器把它们粘在一起 在其他答案中也提到了这一点,我唯一要添加的是可testing性,我将在下面的另一节中讨论这个问题。

dependency injection

为了帮助我们解决问题,需要dependency injection (DI)。 如果你来自服务器端语言(从Java到PHP ),那么你可能已经熟悉了这个概念,但是如果你是来自jQuery的客户端的人,这个概念可以看起来像从愚蠢到多余的时髦。 但事实并非如此。 🙂

从广义的angular度来看,DI意味着您可以非常自由地声明组件,然后从任何其他组件中请求一个实例并授予它。 您不必知道加载顺序或文件位置,或类似的东西。 权力可能不会立即显现,但我只提供一个(常见)例子:testing。

比方说,在我们的应用程序中,我们需要一个通过REST API实现服务器端存储的服务,并且根据应用程序状态,还需要本地存储。 在我们的控制器上运行testing时,我们不希望与服务器通信 – 毕竟我们正在testing控制器 。 我们可以添加一个与原始组件相同名称的模拟服务,并且注入器将确保我们的控制器自动获取假的服务器 – 我们的控制器不会,也不需要知道其中的差别。

说到testing…

4.testing驱动开发 – 永远

这是架构第3部分的真正组成部分,但是把它作为自己的顶层部分是非常重要的。

在你看过,用过或者写过的所有jQuery插件中,有多less人拥有一个随附的testing套件? 不是很多,因为jQuery不是很适合这个。 但AngularJS是。

在jQuery中,testing的唯一方法是通常使用样本/演示页面独立创build组件,我们的testing可以通过该页面执行DOM操作。 那么我们必须单独开发一个组件, 然后将其集成到我们的应用程序中。 多么不方便! 在大多数情况下,使用jQuery进行开发时,我们select迭代而不是testing驱动开发。 谁能责怪我们?

但是因为我们有了分离的关注点,所以我们可以在AngularJS中迭代地进行testing驱动开发! 例如,假设我们想要一个超级简单的指令来在我们的菜单中指明我们当前的路线是什么。 我们可以在我们的应用程序的视图中声明我们想要的:

 <a href="/hello" when-active>Hello</a> 

好的,现在我们可以写一个不存在when-active指令的testing:

 it( 'should add "active" when the route changes', inject(function() { var elm = $compile( '<a href="/hello" when-active>Hello</a>' )( $scope ); $location.path('/not-matching'); expect( elm.hasClass('active') ).toBeFalsey(); $location.path( '/hello' ); expect( elm.hasClass('active') ).toBeTruthy(); })); 

而当我们运行我们的testing,我们可以确认它失败。 只有现在我们应该创造我们的指示:

 .directive( 'whenActive', function ( $location ) { return { scope: true, link: function ( scope, element, attrs ) { scope.$on( '$routeChangeSuccess', function () { if ( $location.path() == element.attr( 'href' ) ) { element.addClass( 'active' ); } else { element.removeClass( 'active' ); } }); } }; }); 

我们的testing现在通过我们的菜单按要求执行。 我们的开发既是迭代的, 也是testing驱动的。 妖兽爽。

从概念上讲,指令不是打包的jQuery

你会经常听到“只在指令中做DOM操作”。 这是必要的。 妥善处理!

但是让我们深入一点

有些指令只是装饰视图中已经存在的东西(想象一下ngClass ),因此有时候直接做DOM操作,然后基本完成。 但是,如果一个指令就像一个“小部件”,并有一个模板,它应该尊重分离关注。 也就是说,模板应该在很大程度上独立于链接和控制器function的实现。

AngularJS带有一套完整的工具,使其变得非常简单。 用ngClass我们可以dynamic地更新这个类; ngModel允许双向数据绑定; ngShowngHide编程方式显示或隐藏一个元素; 还有更多 – 包括我们自己写的。 换句话说,我们可以在没有 DOM操作的情况下做各种精彩的事情。 DOM操作越less,指令越容易testing,风格越简单,将来就越容易改变,而且它们的可重用性和可分配性也越高。

我看到很多新的AngularJS开发者使用指令作为扔jQuery的地方。 换句话说,他们认为“因为我不能在控制器中进行DOM操作,所以我会把这些代码放在一个指令中”。 虽然这当然好多了,但通常还是错的

想想我们在第三部分编写的logging器。即使我们把它写在一个指令中,我们仍然想要做“angular度的方式”。 它仍然不需要任何DOM操作! 有很多次DOM操作是必要的,但比你想象的less得多! 在你的应用程序的任何地方进行DOM操作之前,问问你自己是否真的需要。 可能有更好的办法。

下面是一个显示我最常看到的模式的简单示例。 我们想要一个可切换的button。 (注意:这个例子有一点点人为的devise,而skosh详细来表示更复杂的案例,这些案例的解决方法完全一样。)

 .directive( 'myDirective', function () { return { template: '<a class="btn">Toggle me!</a>', link: function ( scope, element, attrs ) { var on = false; $(element).click( function () { on = !on; $(element).toggleClass('active', on); }); } }; }); 

这有几个问题:

  1. 首先,jQuery从来没有必要。 我们在这里没有任何需要jQuery的东西!
  2. 其次,即使我们的页面上已经有jQuery,也没有理由在这里使用它; 我们可以简单地使用angular.element ,当放入一个没有jQuery的项目时,我们的组件仍然可以工作。
  3. 第三,即使假定这个指令需要jQuery,jqLit​​e( angular.element )也会一直使用jQuery。 所以我们不需要使用$ – 我们可以使用angular.element
  4. 第四,与第三个密切相关的是,jqLit​​e元素不需要被包装在$ – 传递给link函数的元素已经是一个jQuery元素!
  5. 第五,我们在前面的部分提到过,为什么我们将模板的东西混合到我们的逻辑中?

这个指令可以被重写(即使对于非常复杂的情况也是如此):

 .directive( 'myDirective', function () { return { scope: true, template: '<a class="btn" ng-class="{active: on}" ng-click="toggle()">Toggle me!</a>', link: function ( scope, element, attrs ) { scope.on = false; scope.toggle = function () { scope.on = !scope.on; }; } }; }); 

再一次,模板的东西在模板中,所以你(或你的用户)可以很容易地将其交换出来,以满足任何需要的样式,并且逻辑从来不必被触及。 可重用性 – 繁荣!

还有所有其他的好处,比如testing – 这很容易! 无论在模板中,指令的内部API都不会被触及,所以重构很简单。 您可以根据需要更改模板,而无需触摸指令。 不pipe你改变什么,你的testing仍然通过。

w00t!

因此,如果指令不仅仅是类似于jQuery的函数的集合,它们是什么? 指令实际上是HTML的扩展 。 如果HTML没有做你需要做的事情,你可以写一个指令来为你做,然后像使用HTML一样使用它。

换一种说法,如果AngularJS没有提供一些开箱即用的function,那么请考虑一下团队如何完成它,以适应ngClickngClass等。

概要

甚至不要使用jQuery。 甚至不包括它。 它会阻止你。 当你遇到一个问题,你认为你已经知道如何在jQuery中解决,在你到达$ ,尝试考虑如何在AngularJS的范围内做到这一点。 如果你不知道,问! 20次中的19次,最好的办法是不需要jQuery,并尝试用jQuery来解决这个问题,为你做更多的工作。

命令式→声明式

在jQuery中, select器用于查找DOM元素,然后绑定/注册事件处理程序。 当事件触发时,(命令式)代码执行更新/更改DOM。

在AngularJS中,您想要考虑视图而不是DOM元素。 视图是包含AngularJS 指令的 (声明式)HTML。 指令为我们在幕后设置事件处理程序,并给予我们dynamic的数据绑定。 select器很less使用,所以对ID(以及某些类的types)的需求大大减less。 视图与模型绑定(通过范围)。 视图是模型的投影。 事件更改模型(即数据,范围属性),以及投影这些模型的视图“自动”更新。

在AngularJS中,考虑模型,而不是jQueryselect的DOM元素来保存你的数据。 将视图看作是对这些模型的预测,而不是注册callback来操纵用户所看到的内容。

关注点分离

jQuery采用不显眼的JavaScript – 行为(JavaScript)与结构(HTML)分离。

AngularJS使用控制器和指令(每个控制器和指令都可以有自己的控制器,和/或编译和链接函数)来从视图/结构(HTML)中移除行为。 Angular也有服务filter来帮助分离/组织你的应用程序。

另见https://stackoverflow.com/a/14346528/215945

应用程序devise

一种deviseAngularJS应用程序的方法:

  1. 想想你的模型。 为这些模型创build服务或您自己的JavaScript对象。
  2. 想想你想如何展示你的模型 – 你的观点。 为每个视图创buildHTML模板,使用必要的指令获取dynamic数据绑定。
  3. 将控制器连接到每个视图(使用ng-view和routing或ng-controller)。 让控制器只查找/获取视图需要完成工作的任何模型数据。 使控制器尽可能薄。

原型inheritance

在不了解JavaScript原型inheritance如何工作的情况下,您可以用jQuery做很多事情。 在开发AngularJS应用程序时,如果您对JavaScriptinheritance有很好的理解,您将避免一些常见的陷阱。 推荐阅读: AngularJS中范围原型/原型inheritance的细微差别是什么?

AngularJS与jQuery

AngularJS和jQuery采用非常不同的思想。 如果你来自jQuery,你可能会发现一些惊人的差异。 angular度可能会让你生气。

这是正常的,你应该通过。 angular是值得的。

差异很大(TLDR)

jQuery为您提供了一个工具包,用于selectDOM的任意位并对其进行临时更改。 你几乎可以做任何你喜欢的事情。

AngularJS改为给你一个编译器

这意味着AngularJS从上到下读取整个DOM,并将其视为代码,从字面上看就是编译器的指令。 在遍历DOM时,它会查找特定的指令 (编译器指令),告诉AngularJS编译器如何操作以及如何操作。 指令是一些JavaScript对象,可以匹配属性,标签,类甚至注释。

当Angular编译器确定一段DOM匹配特定的指令时,它会调用指令函数,将它传递给DOM元素,任何属性,当前的$ scope(这是一个局部variables存储)以及一些其他有用的位。 这些属性可能包含可以被指令解释的expression式,以及告诉它如何渲染以及何时应该重绘自己的expression式。

然后,指令可以依次引入额外的Angular组件,例如控制器,服务等等。编译器的底部是一个完全形成的Web应用程序,已经连接起来并准备好了。

这意味着Angular是模板驱动的 。 您的模板驱动JavaScript,而不是相反。 这是angular色的彻底颠覆,与我们在过去10年左右一直在写的不引人注目的JavaScript截然相反。 这可能需要一些习惯。

如果这听起来可能是过分规定和限制的话,那么事实就没有什么可说的了。 由于AngularJS将HTML视为代码,因此您可以在Web应用程序中获得HTML级别的粒度 。 一切都是可能的,一旦你进行了一些概念上的飞跃,大部分事情都是非常容易的。

让我们回到本质上。

首先,Angular不会取代jQuery

Angular和jQuery做不同的事情。 AngularJS为您提供了一套工具来生成Web应用程序。 jQuery主要为您提供修改DOM的工具。 如果你的页面上有jQuery,AngularJS会自动使用它。 如果不是的话,AngularJS提供了jQuery Lite,这是一个简化,但仍然完美的jQuery版本。

Misko喜欢jQuery,并不反对你使用它。 然而,随着您的发展,您将会发现,使用范围,模板和指令可以完成大部分工作,而且您应该尽可能使用此工作stream程,因为您的代码将更加独立,更易于configuration,而且更多angular。

如果你确实使用jQuery,你不应该把它撒在所有的地方。 AngularJS中DOM操作的正确位置在一个指令中。 更多关于这些以后。

带有select器和声明模板的不显眼的JavaScript

jQuery通常应用不显眼。 您的JavaScript代码在页眉(或页脚)中链接,并且这是唯一提到的地方。 我们使用select器来挑选页面的各个部分,并编写插件来修改这些部分。

JavaScript是在控制之中。 HTML有一个完全独立的存在。 即使没有JavaScript,你的HTML仍然是语义的。 Onclick属性是非常糟糕的做法。

你会注意到关于AngularJS的第一件事情是自定义属性无处不在 。 你的HTML将会被ng属性所占据,而这些属性本质上是类固醇上的onClick属性。 这些是指令(编译器指令),是模板挂钩到模型的主要方式之一。

当你第一次看到这个时,你可能会试图把AngularJS写成老派入侵的JavaScript(就像我最初做的那样)。 事实上,AngularJS并不遵守这些规则。 在AngularJS中,你的HTML5是一个模板。 它由AngularJS编译生成你的网页。

这是第一个很大的区别。 对于jQuery,您的网页是一个DOM被操纵。 对于AngularJS,您的HTML是要编译的代码。 AngularJS读入您的整个网页,并使用其内置的编译器将其编译成新的网页。

你的模板应该是声明式的; 通过阅读它的含义应该是清楚的。 我们使用有意义的名字的自定义属性 我们用有意义的名字组成新的HTML元素。 一个具有最小的HTML知识和没有编码技能的devise师可以阅读你的AngularJS模板,并理解它在做什么。 他或她可以进行修改。 这是angular度的方式。

模板在驾驶座位上。

在启动AngularJS并运行教程时,我问自己的第一个问题是“我的代码在哪里? 。 我没有写JavaScript,但我有这一切的行为。 答案是显而易见的。 由于AngularJS编译DOM,AngularJS将HTML视为代码。 对于很多简单的情况,只需要编写一个模板并让AngularJS将它编译成一个应用程序就足够了。

你的模板驱动你的应用程序 它被视为DSL 。 您可以编写AngularJS组件,而AngularJS将会根据您的模板结构在正确的时间处理这些组件。 这与标准MVC模式非常不同,模板仅用于输出。

例如,它比Ruby on Rails更类似于XSLT 。

这是一个需要一些习惯的控制的彻底颠倒。

停止尝试从你的JavaScript驱动你的应用程序。 让模板驱动应用程序,并让AngularJS负责将组件连接在一起。 这也是angular度的方式。

语义HTML与语义模型

用jQuery你的HTML页面应该包含语义上有意义的内容。 如果JavaScript被closures(通过用户或search引擎),您的内容仍然可以访问。

因为AngularJS把你的HTML页面当成模板。 模板不应该是语义的,因为您的内容通常存储在您的模型中,最终来自您的API。 AngularJS使用模型编译你的DOM来产生一个语义网页。

您的HTML源不再是语义的,而是您的API和编译的DOM是语义的。

在AngularJS中,意味着生活在模型中,HTML只是一个模板,仅用于显示。

在这一点上,你可能有关于search引擎优化和可访问性的各种问题,这是正确的。 这里有一些公开的问题。 大多数屏幕阅读器现在将parsingJavaScript。 search引擎也可以索引AJAX的内容。 不过,你会想确保你使用pushstate的URL,你有一个体面的网站地图。 请参阅此处以了解有关此问题的讨论: https : //stackoverflow.com/a/23245379/687677

分离问题(SOC)与MVC

问题分离 (SOC)是由于多种原因(包括search引擎优化(SEO),可访问性和浏览器不兼容性)而在多年的networking开发中长大的一种模式。 它看起来像这样:

  1. HTML – 语义。 HTML应该是独立的。
  2. CSS – 样式,没有CSS的页面仍然可读。
  3. JavaScript – 行为,没有脚本的内容仍然存在。

AngularJS再一次没有按照他们的规则来玩。 一举中AngularJS取消了十年的智慧 ,而是实现了一种MVC模式,即模板不再是语义的,甚至不是一点点。

它看起来像这样:

  1. 模型 – 您的模型包含您的语义数据。 模型通常是JSON对象。 模型作为名为$ scope的对象的属性存在。 你也可以在你的模板可以访问的$ scope中存储方便的实用程序函数。
  2. 查看 – 您的意见是用HTML编写的。 视图通常不是语义的,因为您的数据存在于模型中。
  3. 控制器 – 您的控制器是一个将视图挂接到模型的JavaScript函数。 它的function是初始化$范围。 根据您的应用程序,您可能需要也可能不需要创build一个控制器。 你可以在页面上有许多控制器。

MVC和SOC不在同一尺度的两端,它们在完全不同的轴上。 SOC在AngularJS环境中没有任何意义。 你必须忘记它,继续前进。

如果像我一样,你经历了浏览器的战争,你可能会觉得这个想法很冒犯。 克服它,这是值得的,我保证。

插件与指令

插件扩展jQuery。 AngularJS指令扩展了浏览器的function。

在jQuery中,我们通过向jQuery.prototype添加函数来定义插件。 然后,我们通过select元素并在结果上调用插件将这些钩到DOM中。 这个想法是扩展jQuery的function。

例如,如果你想在你的页面上有一个传送带,你可以定义一个无序的graphics列表,也许包裹在一个导航元素中。 然后,你可能会写一些jQuery来select页面上的列表,并将其重新设置为带有超时的画廊来执行滑动animation。

在AngularJS中,我们定义了指令。 指令是一个返回JSON对象的函数。 这个对象告诉AngularJS要查找哪些DOM元素,以及对它们做些什么改变。 使用您创build的属性或元素,将指令挂钩到模板。 这个想法是用新的属性和元素来扩展HTML的function。

AngularJS的方式是扩展原生HTML的function。 你应该写HTML看起来像HTML,扩展自定义属性和元素。

如果你想要一个轮播,只需使用一个<carousel />元素,然后定义一个指令来拉入一个模板,并使该吸盘工作。

很多小指令与configuration开关的大插件

The tendency with jQuery is to write great big plugins like lightbox which we then configure by passing in numerous values and options.

This is a mistake in AngularJS.

Take the example of a dropdown. When writing a dropdown plugin you might be tempted to code in click handlers, perhaps a function to add in a chevron which is either up or down, perhaps change the class of the unfolded element, show hide the menu, all helpful stuff.

Until you want to make a small change.

Say you have a menu that you want to unfold on hover. Well now we have a problem. Our plugin has wired in our click handler for us, we're going to need to add a configuration option to make it behave differently in this specific case.

In AngularJS we write smaller directives. Our dropdown directive would be ridiculously small. It might maintain the folded state, and provide methods to fold(), unfold() or toggle(). These methods would simply update $scope.menu.visible which is a boolean holding the state.

Now in our template we can wire this up:

 <a ng-click="toggle()">Menu</a> <ul ng-show="menu.visible"> ... </ul> 

Need to update on mouseover?

 <a ng-mouseenter="unfold()" ng-mouseleave="fold()">Menu</a> <ul ng-show="menu.visible"> ... </ul> 

The template drives the application so we get HTML level granularity. If we want to make case by case exceptions, the template makes this easy.

Closure vs. $scope

JQuery plugins are created in a closure. Privacy is maintained within that closure. It's up to you to maintain your scope chain within that closure. You only really have access to the set of DOM nodes passed in to the plugin by jQuery, plus any local variables defined in the closure and any globals you have defined. This means that plugins are quite self contained. This is a good thing, but can get restrictive when creating a whole application. Trying to pass data between sections of a dynamic page becomes a chore.

AngularJS has $scope objects. These are special objects created and maintained by AngularJS in which you store your model. Certain directives will spawn a new $scope, which by default inherits from its wrapping $scope using JavaScript prototypical inheritance. The $scope object is accessible in the controller and the view.

This is the clever part. Because the structure of $scope inheritance roughly follows the structure of the DOM, elements have access to their own scope, and any containing scopes seamlessly, all the way up to the global $scope (which is not the same as the global scope).

This makes it much easier to pass data around, and to store data at an appropriate level. If a dropdown is unfolded, only the dropdown $scope needs to know about it. If the user updates their preferences, you might want to update the global $scope, and any nested scopes listening to the user preferences would automatically be alerted.

This might sound complicated, in fact, once you relax into it, it's like flying. You don't need to create the $scope object, AngularJS instantiates and configures it for you, correctly and appropriately based on your template hierarchy. AngularJS then makes it available to your component using the magic of dependency injection (more on this later).

Manual DOM changes vs. Data Binding

In jQuery you make all your DOM changes by hand. You construct new DOM elements programatically. If you have a JSON array and you want to put it to the DOM, you must write a function to generate the HTML and insert it.

In AngularJS you can do this too, but you are encouraged to make use of data binding. Change your model, and because the DOM is bound to it via a template your DOM will automatically update, no intervention required.

Because data binding is done from the template, using either an attribute or the curly brace syntax, it's super easy to do. There's little cognitive overhead associated with it so you'll find yourself doing it all the time.

 <input ng-model="user.name" /> 

Binds the input element to $scope.user.name . Updating the input will update the value in your current scope, and vice-versa.

Likewise:

 <p> {{user.name}} </p> 

will output the user name in a paragraph. It's a live binding, so if the $scope.user.name value is updated, the template will update too.

Ajax all of the time

In jQuery making an Ajax call is fairly simple, but it's still something you might think twice about. There's the added complexity to think about, and a fair chunk of script to maintain.

In AngularJS, Ajax is your default go-to solution and it happens all the time, almost without you noticing. You can include templates with ng-include. You can apply a template with the simplest custom directive. You can wrap an Ajax call in a service and create yourself a GitHub service, or a Flickr service, which you can access with astonishing ease.

Service Objects vs Helper Functions

In jQuery, if we want to accomplish a small non-dom related task such as pulling a feed from an API, we might write a little function to do that in our closure. That's a valid solution, but what if we want to access that feed often? What if we want to reuse that code in another application?

AngularJS gives us service objects.

Services are simple objects that contain functions and data. They are always singletons, meaning there can never be more than one of them. Say we want to access the Stack Overflow API, we might write a StackOverflowService which defines methods for doing so.

Let's say we have a shopping cart. We might define a ShoppingCartService which maintains our cart and contains methods for adding and removing items. Because the service is a singleton, and is shared by all other components, any object that needs to can write to the shopping cart and pull data from it. It's always the same cart.

Service objects are self-contained AngularJS components which we can use and reuse as we see fit. They are simple JSON objects containing functions and Data. They are always singletons, so if you store data on a service in one place, you can get that data out somewhere else just by requesting the same service.

Dependency injection (DI) vs. Instatiation – aka de-spaghettification

AngularJS manages your dependencies for you. If you want an object, simply refer to it and AngularJS will get it for you.

Until you start to use this, it's hard to explain just what a massive time boon this is. Nothing like AngularJS DI exists inside jQuery.

DI means that instead of writing your application and wiring it together, you instead define a library of components, each identified by a string.

Say I have a component called 'FlickrService' which defines methods for pulling JSON feeds from Flickr. Now, if I want to write a controller that can access Flickr, I just need to refer to the 'FlickrService' by name when I declare the controller. AngularJS will take care of instantiating the component and making it available to my controller.

For example, here I define a service:

 myApp.service('FlickrService', function() { return { getFeed: function() { // do something here } } }); 

Now when I want to use that service I just refer to it by name like this:

 myApp.controller('myController', ['FlickrService', function(FlickrService) { FlickrService.getFeed() }]); 

AngularJS will recognise that a FlickrService object is needed to instantiate the controller, and will provide one for us.

This makes wiring things together very easy, and pretty much eliminates any tendency towards spagettification. We have a flat list of components, and AngularJS hands them to us one by one as and when we need them.

Modular service architecture

jQuery says very little about how you should organise your code. AngularJS has opinions.

AngularJS gives you modules into which you can place your code. If you're writing a script that talks to Flickr for example, you might want to create a Flickr module to wrap all your Flickr related functions in. Modules can include other modules (DI). Your main application is usually a module, and this should include all the other modules your application will depend on.

You get simple code reuse, if you want to write another application based on Flickr, you can just include the Flickr module and voila, you have access to all your Flickr related functions in your new application.

Modules contain AngularJS components. When we include a module, all the components in that module become available to us as a simple list identified by their unique strings . We can then inject those components into each other using AngularJS's dependency injection mechanism.

总结一下

AngularJS and jQuery are not enemies. It's possible to use jQuery within AngularJS very nicely. If you're using AngularJS well (templates, data-binding, $scope, directives, etc.) you will find you need a lot less jQuery than you might otherwise require.

The main thing to realise is that your template drives your application. Stop trying to write big plugins that do everything. Instead write little directives that do one thing, then write a simple template to wire them together.

Think less about unobtrusive JavaScript, and instead think in terms of HTML extensions.

My little book

I got so excited about AngularJS, I wrote a short book on it which you're very welcome to read online http://nicholasjohnson.com/angular-book/ . I hope it's helpful.

你能描述一下必要的范式转变吗?

Imperative vs Declarative

With jQuery you tell the DOM what needs to happen, step by step. With AngularJS you describe what results you want but not how to do it. More on this here . Also, check out Mark Rajcok's answer.

How do I architect and design client-side web apps differently?

AngularJS is an entire client-side framework that uses the MVC pattern (check out their graphical representation ). It greatly focuses on separation of concerns.

最大的区别是什么? 我应该停止做什么/使用什么? what should I start doing/using instead?

jQuery is a library

AngularJS is a beautiful client-side framework, highly testable, that combines tons of cool stuff such as MVC, dependency injection , data binding and much more.

It focuses on separation of concerns and testing ( unit testing and end-to-end testing), which facilitates test-driven development.

The best way to start is going through their awesome tutorial . You can go through the steps in a couple of hours; however, in case you want to master the concepts behind the scenes, they include a myriad of reference for further reading.

有没有服务器端的考虑/限制?

You may use it on existing applications where you are already using pure jQuery. However, if you want to fully take advantage of the AngularJS features you may consider coding the server side using a RESTful approach.

Doing so will allow you to leverage their resource factory , which creates an abstraction of your server side RESTful API and makes server-side calls (get, save, delete, etc.) incredibly easy.

To describe the "paradigm shift", I think a short answer can suffice.

AngularJS changes the way you find elements

In jQuery , you typically use selectors to find elements, and then wire them up:
$('#id .class').click(doStuff);

In AngularJS , you use directives to mark the elements directly, to wire them up:
<a ng-click="doStuff()">

AngularJS doesn't need (or want) you to find elements using selectors – the primary difference between AngularJS's jqLite versus full-blown jQuery is that jqLite does not support selectors .

So when people say "don't include jQuery at all", it's mainly because they don't want you to use selectors; they want you to learn to use directives instead. Direct, not select!

jQuery的

jQuery makes ridiculously long JavaScript commands like getElementByHerpDerp shorter and cross-browser.

AngularJS

AngularJS allows you to make your own HTML tags/attributes that do things which work well with dynamic web applications (since HTML was designed for static pages).

编辑:

Saying "I have a jQuery background how do I think in AngularJS?" is like saying "I have an HTML background how do I think in JavaScript?" The fact that you're asking the question shows you most likely don't understand the fundamental purposes of these two resources. This is why I chose to answer the question by simply pointing out the fundamental difference rather than going through the list saying "AngularJS makes use of directives whereas jQuery uses CSS selectors to make a jQuery object which does this and that etc….". This question does not require a lengthy answer.

jQuery is a way to make programming JavaScript in the browser easier. Shorter, cross-browser commands, etc.

AngularJS extends HTML, so you don't have to put <div> all over the place just to make an application. It makes HTML actually work for applications rather than what it was designed for, which is static, educational web pages. It accomplishes this in a roundabout way using JavaScript, but fundamentally it is an extension of HTML, not JavaScript.

jQuery: you think a lot about 'QUERYing the DOM ' for DOM elements and doing something.

AngularJS: THE model is the truth, and you always think from that ANGLE.

For example, when you get data from THE server which you intend to display in some format in the DOM, in jQuery, you need to '1. FIND' where in the DOM you want to place this data, the '2. UPDATE/APPEND' it there by creating a new node or just setting its innerHTML . Then when you want to update this view, you then '3. FIND' the location and '4. UPDATE'. This cycle of find and update all done within the same context of getting and formatting data from server is gone in AngularJS.

With AngularJS you have your model (JavaScript objects you are already used to) and the value of the model tells you about the model (obviously) and about the view, and an operation on the model automatically propagates to the view, so you don't have to think about it. You will find yourself in AngularJS no longer finding things in the DOM.

To put in another way, in jQuery, you need to think about CSS selectors, that is, where is the div or td that has a class or attribute, etc., so that I can get their HTML or color or value, but in AngularJS, you will find yourself thinking like this: what model am I dealing with, I will set the model's value to true. You are not bothering yourself of whether the view reflecting this value is a checked box or resides in a td element (details you would have often needed to think about in jQuery).

And with DOM manipulation in AngularJS, you find yourself adding directives and filters, which you can think of as valid HTML extensions.

One more thing you will experience in AngularJS: in jQuery you call the jQuery functions a lot, in AngularJS, AngularJS will call your functions, so AngularJS will 'tell you how to do things', but the benefits are worth it, so learning AngularJS usually means learning what AngularJS wants or the way AngularJS requires that you present your functions and it will call it accordingly. This is one of the things that makes AngularJS a framework rather than a library.

jQuery is a DOM manipulation library.

AngularJS is an MV* framework.

In fact, AngularJS is one of the few JavaScript MV* frameworks (many JavaScript MVC tools still fall under the category library).

Being a framework, it hosts your code and takes ownership of decisions about what to call and when!

AngularJS itself includes a jQuery-lite edition within it. So for some basic DOM selection/manipulation, you really don't have to include the jQuery library (it saves many bytes to run on the network.)

AngularJS has the concept of "Directives" for DOM manipulation and designing reusable UI components, so you should use it whenever you feel the need of doing DOM manipulation related stuff (directives are only place where you should write jQuery code while using AngularJS).

AngularJS involves some learning curve (more than jQuery :-).

–>For any developer coming from jQuery background, my first advice would be to "learn JavaScript as a first class language before jumping onto a rich framework like AngularJS!" I learned the above fact the hard way.

祝你好运。

Those are some very nice, but lengthy answers.

To sum up my experiences:

  1. Controllers and providers (services, factories, etc.) are for modifying the data model, NOT HTML.
  2. HTML and directives define the layout and binding to the model.
  3. If you need to share data between controllers, create a service or factory – they are singletons that are shared across the application.
  4. If you need an HTML widget, create a directive.
  5. If you have some data and are now trying to update HTML… STOP! update the model, and make sure your HTML is bound to the model.

They're apples and oranges. You don't want to compare them. They're two different things. AngularJs has already jQuery lite built in which allows you to perform basic DOM manipulation without even including the full blown jQuery version.

jQuery is all about DOM manipulation. It solves all the cross browser pain otherwise you will have to deal with but it's not a framework that allows you to divide your app into components like AngularJS.

A nice thing about AngularJs is that it allows you to separate/isolate the DOM manipulation in the directives. There are built-in directives ready for you to use such as ng-click. You can create your own custom directives that will contain all your view logic or DOM manipulation so you don't end up mingle DOM manipulation code in the controllers or services that should take care of the business logic.

Angular breaks down your app into – Controllers – Services – Views – etc.

and there is one more thing, that's the directive. It's an attribute you can attach to any DOM element and you can go nuts with jQuery within it without worrying about your jQuery ever conflicts with AngularJs components or messes up with its architecture.

I heard from a meetup I attended, one of the founders of Angular said they worked really hard to separate out the DOM manipulation so do not try to include them back in.

Listen to the podcast JavaScript Jabber: Episode #32 that features the original creators of AngularJS: Misko Hevery & Igor Minar. They talk a lot about what it's like to come to AngularJS from other JavaScript backgrounds, especially jQuery.

One of the points made in the podcast made a lot of things click for me with respects to your question:

MISKO : […] one of the things we thought about very hardly in Angular is, how do we provide lots of escape hatches so that you can get out and basically figure out a way out of this. So to us, the answer is this thing called “Directives”. And with directives, you essentially become a regular little jQuery JavaScript, you can do whatever you want.

IGOR : So think of directive as the instruction to the compiler that tells it whenever you come across this certain element or this CSS in the template, and you keep this kind of code and that code is in charge of the element and everything below that element in the DOM tree.

A transcript of the entire episode is available at the link provided above.

So, to directly answer your question: AngularJS is -very- opinionated and is a true MV* framework. However, you can still do all of the really cool stuff you know and love with jQuery inside of directives. It's not a matter of "How do I do what I used to in jQuery?" as much as it's a matter of "How do I supplement AngularJS with all of the stuff I used to do in jQuery?"

It's really two very different states of mind.

I find this question interesting, because my first serious exposure to JavaScript programming was Node.js and AngularJS. I never learned jQuery, and I guess that's a good thing, because I don't have to unlearn anything. In fact, I actively avoid jQuery solutions to my problems, and instead, solely look for an "AngularJS way" to solve them. So, I guess my answer to this question would essentially boil down to, "think like someone who never learned jQuery" and avoid any temptation to incorporate jQuery directly (obviously AngularJS uses it to some extent behind the scenes).

AngularJS and jQuery:

AngularJs and JQuery are completely different at every level except the JQLite functionality and you will see it once you start learning the AngularJs core features (I explained it below).

AngularJs is a client side framework that offers to build the independent client side application. JQuery is a client side library that play around the DOM.

AngularJs Cool Principle – If you want some changes on your UI think from model data change perspective. Change your data and UI will re-render itself. You need not to play around DOM each time unless and until it is hardly required and that should also be handled through Angular Directives.

To answer this question, I want to share my experience on the first enterprise application with AngularJS. These are the most awesome features that Angular provide where we start changing our jQuery mindset and we get the Angular like a framework and not the library.

Two-way data binding is amazing: I had a grid with all functionality UPDATE, DELTE, INSERT. I have a data object that binds the grid's model using ng-repeat. You only need to write a single line of simple JavaScript code for delete and insert and that's it. grid automatically updates as the grid model changes instantly. Update functionality is real time, no code for it. You feel amazing!!!

Reusable directives are super: Write directives in one place and use it throughout the application. 我的天啊!!! I used these directive for paging, regex, validations, etc. It is really cool!

Routing is strong: It's up to your implementation how you want to use it, but it requires very few lines of code to route the request to specify HTML and controller (JavaScript)

Controllers are great: Controllers take care of their own HTML, but this separation works well for common functionality well as. If you want to call the same function on the click of a button on master HTML, just write the same function name in each controller and write individual code.

Plugins: There are many other similar features like showing an overlay in your app. You don't need to write code for it, just use an overlay plugin available as wc-overlay, and this will automatically take care of all XMLHttpRequest (XHR) requests.

Ideal for RESTful architecture: Being a complete frameworks makes AngularJS great to work with a RESTful architecture. To call REST CRUD APIs is very easier and

Services : Write common codes using services and less code in controllers. Sevices can be used to share common functionalities among the controllers.

Extensibility : Angular has extended the HTML directives using angular directives. Write expressions inside html and evaluate them on runtime. Create your own directives and services and use them in another project without any extra effort.

As a JavaScript MV* beginner and purely focusing on the application architecture (not the server/client-side matters), I would certainly recommend the following resource (which I am surprised wasn't mentioned yet): JavaScript Design Patterns , by Addy Osmani, as an introduction to different JavaScript Design Patterns . The terms used in this answer are taken from the linked document above. I'm not going to repeat what was worded really well in the accepted answer. Instead, this answer links back to the theoretical backgrounds which power AngularJS (and other libraries).

Like me, you will quickly realize that AngularJS (or Ember.js , Durandal, & other MV* frameworks for that matter) is one complex framework assembling many of the different JavaScript design patterns.

I found it easier also, to test (1) native JavaScript code and (2) smaller libraries for each one of these patterns separately before diving into one global framework. This allowed me to better understand which crucial issues a framework adresses (because you are personally faced with the problem).

例如:

  • JavaScript Object-oriented Programming (this is a Google search link). It is not a library, but certainly a prerequisite to any application programming. It taught me the native implementations of the prototype, constructor, singleton & decorator patterns
  • jQuery / Underscore for the facade pattern (like WYSIWYG's for manipulating the DOM)
  • Prototype.js for the prototype/ constructor/ mixin pattern
  • RequireJS / Curl.js for the module pattern/ AMD
  • KnockoutJS for the observable, publish/subscribe pattern

NB: This list is not complete, nor 'the best libraries'; they just happen to be the libraries I used. These libraries also include more patterns, the ones mentioned are just their main focuses or original intents. If you feel something is missing from this list, please do mention it in the comments, and I will be glad to add it.

Actually, if you're using AngularJS, you don't need jQuery anymore. AngularJS itself has the binding and directive, which is a very good "replacement" for most things you can do with jQuery.

I usually develop mobile applications using AngularJS and Cordova . The ONLY thing from jQuery I needed is the Selector.

By googling, I see that there is a standalone jQuery selector module out there. It's Sizzle.

And I decided to make a tiny code snippet that help me quickly start a website using AngularJS with the power of jQuery Selector (using Sizzle).

I shared my code here: https://github.com/huytd/Sizzular