提问



假设我熟悉在jQuery中开发客户端应用程序,但现在我想开始使用AngularJS。你能描述一下必要的范式转变吗?以下是一些可能帮助您确定答案的问题:[54] [55]



  • 如何以不同方式构建和设计客户端Web应用程序?最大的区别是什么?

  • 我应该停止做什么/使用什么;我应该开始做什么/使用呢?

  • 是否存在任何服务器端注意事项/限制?



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

最佳参考


1。不要设计你的页面,然后用DOM操作改变它



在jQuery中,您设计了一个页面,然后将其设置为动态。这是因为jQuery是为增强而设计的,并且从这个简单的前提中获得了令人难以置信的增长。[56]


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


2。不要用AngularJS

扩充jQuery

同样地,不要从jQuery做X,Y和Z的想法开始,所以我只是在模型和控制器的基础上添加AngularJS。当你刚刚开始时,这真的诱人,这就是为什么我总是建议新的AngularJS开发人员根本不使用jQuery,至少在他们习惯做Angular Way之前。


我已经看到许多开发人员在这里和邮件列表上创建了这些精心设计的解决方案,其中包含150或200行代码的jQuery插件,然后他们将一系列回调和$apply粘合到AngularJS中,令人困惑和错综复杂;但他们最终得到了它的工作!问题是在大多数的情况下,jQuery插件可以在AngularJS中以一小部分代码重写,突然一切都变得易于理解和直截了当。


最重要的是:在解决问题时,首先要在AngularJS中思考;如果你不能想到一个解决方案,请问社区;如果完全没有简单的解决方案,那么随时可以使用jQuery。但是不要让jQuery成为一个拐杖或者你永远不会掌握AngularJS。


3。总是在架构方面思考



首先要知道单页应用程序是应用程序。他们不不网页。所以我们需要像服务器端开发人员一样思考,以便像客户端开发人员一样思考。我们必须考虑如何划分我们应用于个人,可扩展,可测试的组件。[57]


那么如何你这样做?你如何在AngularJS中思考?以下是一些与jQuery形成对比的一般原则。


该视图是官方记录



在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();


当我们只看这个视图时,这里的任何功能都不是很明显。对于小型应用程序,这很好。但对于非平凡的应用程序,事情很快就会变得混乱和难以维护。


但是,在AngularJS中,视图是基于视图的功能的官方记录。我们的ul声明将是这样的:


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


这两个做同样的事情,但在AngularJS版本中,任何看模板的人都知道应该发生什么。每当开发团队的新成员加入时,她都可以看看这个,然后知道有一个名为dropdownMenu的指令在其上运行;她不需要知道正确的答案或筛选任何代码。该观点告诉我们应该发生什么。更清除。


AngularJS的新手开发人员经常会问一个问题:如何查找特定类型的所有链接并在其上添加指令。当我们回复时,开发人员总是大惊小怪:你不会。但是你不这样做的原因是这就像半jQuery,半AngularJS,并没有好处。这里的问题是开发人员试图在AngularJS的上下文中执行jQuery。这永远不会很好。视图是官方记录。在指令之外(下面有更多内容),你永远不会从不更改DOM 。指令在​​视图中应用,因此意图很明确。


记住:不要设计,然后标记。你必须设计,然后设计。


数据绑定



这是迄今为止AngularJS最强大的功能之一,并且我在上一节中提到了很多需要进行各种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进行编码。我们如何测试除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中,我们有一个单独的模型层,我们可以以任何方式管理,完全独立于视图。这有助于上述数据绑定,保持关注点的分离,并引入更大的可测试性。其他答案提到了这一点,所以我将把它留在那。[58]


关注点分离



以上所有内容都与这个主题相关:将您的担忧分开。你的观点作为应该发生的事情的官方记录(大部分);你的模型代表你的数据;你有一个服务层来执行可重用的任务;你做DOM操作并用指令扩充你的视图;然后将它们与控制器粘合在一起。在其他答案中也提到了这一点,我将添加的唯一内容涉及可测试性,我将在下面的另一部分中讨论。


依赖注入



为了帮助我们分离关注点,依赖注入(DI)。如果你来自服务器端语言(从Java到PHP),你可能已经熟悉这个概念,但如果你是一个来自jQuery的客户端人,这个概念看起来似乎从愚蠢到多余到时髦。但事实并非如此。: - )[59] [60] [61]


从广义的角度来看,DI意味着您可以非常自由地声明组件,然后从任何其他组件声明组件,只需要询问它的实例,它就会被授予。你不必知道加载订单,文件位置或类似的东西。电源可能不会立即可见,但我只提供一个(常见)示例:测试。


让我们在我们的应用程序中说,我们需要一个通过REST API实现服务器端存储的服务,并且根据应用程序状态,还需要本地存储。在我们的控制器上运行测试时,我们不希望进行通信与服务器 - 毕竟我们正在测试控制器。我们可以添加一个与原始组件同名的模拟服务,注入器将确保我们的控制器自动获取假的 - 我们的控制人员并不知道差异。[62]


说到测试......


4。测试驱动的开发 - 始终



这实际上是关于体系结构的第3部分的一部分,但它非常重要,我将它作为自己的顶级部分。


在你见过,使用过或编写的所有jQuery插件中,有多少有一个附带的测试套件?不是很多,因为jQuery并不是非常适合的。但AngularJS是。


在jQuery中,唯一的测试方法通常是使用示例/演示页面独立创建组件,我们的测试可以对其执行DOM操作。那么我们必须单独开发一个组件,然后 将它集成到我们的应用程序中。多么不方便!很多时候,在使用jQuery开发时,我们选择迭代而不是测试驱动开发。谁可以怪我们?


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


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


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


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();
}));


当我们运行测试时,我们可以确认它失败了。只有现在我们才能创建我们的指令:


.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' );
                }
            });
        }
    };
});


我们的测试现在通过和我们的菜单按要求执行。我们的开发是两个迭代和测试驱动。妖兽爽。


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



你经常会听到只在指令中操作DOM。这是必要的。以适当的尊重对待它!


但是让我们深入一点......


一些指令只是装饰视图中的内容(想ngClass),因此有时会立即执行DOM操作,然后基本完成。但是如果指令就像一个小部件并且有一个模板,它应该也尊重关注点的分离。也就是说,模板 too 应该在很大程度上独立于链接和控制器功能中的实现。


AngularJS附带了一整套工具,可以轻松实现这一目标。用ngClass我们可以动态更新类; ngModel允许双向数据绑定; ngShowngHide以编程方式显示或隐藏元素;还有更多 - 包括我们自己写的那些。换句话说,我们可以在没有 DOM操作的情况下做各种非常棒的事情。 DOM操作越少,测试指令就越容易,它们的样式就越容易,将来它们就越容易改变,它们的可重用性和可分发性就越高。


我看到许多开发人员对AngularJS很新,使用指令作为抛出一堆jQuery的地方。换句话说,他们认为因为我不能在控制器中进行DOM操作,所以我会把代码放在指令中。虽然这确实好得多,但它经常仍然是错误的。


想想我们在第3节中编写的记录器。即使我们把它放在一个指令中,我们仍然想要做Angular Way。它仍然没有采取任何DOM操作!有很多时候需要进行DOM操作,但它比你想象的更少很多!在您的应用程序中进行DOM操作任何地方之前,请问自己是否真的需要。可能有更好的方法。


这是一个快速示例,显示了我经常看到的模式。我们想要一个可切换的按钮。(注意:这个例子有点人为,并且表示更加复杂的情况,以完全相同的方式解决。)


.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函数的element将已经一个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;
            };
        }
    };
});


同样,模板内容在模板中,因此您(或您的用户)可以轻松地将其换成符合任何必要样式的模板,并且永远不必触及逻辑。可重用性 - 热潮!


而且还有所有其他好处,比如测试 - 这很简单!无论模板中有什么内容,指令的内部API都不会被触及,因此重构很容易。你可以像你一样更改模板希望不要触及指令。无论你改变什么,你的测试仍然通过。


w00t!


因此,如果指令不仅仅是类jQuery函数的集合,那么它们是什么?指令实际上是扩展HTML 。如果HTML没有做某事你需要它做,你写一个指令到为你做,然后使用它,就像它是HTML的一部分。


换句话说,如果AngularJS没有开箱即用,想想团队如何完成它以适应ngClickngClass等。


摘要



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

其它参考1


势在必行→陈述性



在jQuery中,选择器用于查找DOM元素,然后将事件处理程序绑定/注册到它们。当事件触发时,执行(命令性)代码以更新/更改DOM。[63]


在AngularJS中,您需要考虑视图而不是DOM元素。视图是包含AngularJS 指令的(声明性)HTML。指令为我们幕后设置了事件处理程序,并为我们提供了动态数据绑定。选择器很少使用,因此对ID(以及某些类型的类)的需求大大减少。视图与模型(通过范围)相关联。视图是模型的投影。事件更改模型(即数据,范围属性)以及投影这些模型的视图会自动更新。


在AngularJS中,考虑模型,而不是jQuery选择的DOM元素来保存您的数据。将视图视为这些模型的投影,而不是注册回调来操纵用户看到的内容。


关注点分离



jQuery使用不引人注目的JavaScript - 行为(JavaScript)与结构(HTML)分离。[64]


AngularJS使用控制器和指令(每个指令都有自己的控制器和/或编译和链接函数)来从视图/结构(HTML)中删除行为。 Angular还提供服务过滤器,以帮助分离/整理您的应用。


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


应用程序设计



设计AngularJS应用程序的一种方法:



  1. 想想你的模特。为这些模型创建服务或您自己的JavaScript对象。

  2. 想想你想要展示模特的方式 - 你的观点。为每个视图创建HTML模板,使用必要的指令来获取动态数据绑定。

  3. 将控制器连接到每个视图(使用ng-view和routing,或ng-controller)。让控制器只查找/获取视图完成其工作所需的任何模型数据。使控制器尽可能薄。



原型继承



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

其它参考2


AngularJS与jQuery



AngularJS和jQuery采用了截然不同的意识形态。如果您来自jQuery,您可能会发现一些令人惊讶的差异.Angular可能会让您生气。


这很正常,你应该坚持下去。 Angular值得。


差异很大(TLDR)



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


相反,AngularJS会为您提供编译器


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


当Angular编译器确定DOM的一部分与特定指令匹配时,它调用指令函数,向其传递DOM元素,任何属性,当前$ scope(本地变量存储)以及一些其他有用位。这些属性可能包含可由指令解释的表达式,它告诉它如何渲染,以及何时应重绘自身。


然后,指令可以引入额外的Angular组件,例如控制器,服务等。编译器底部出现的是一个完整形成的Web应用程序,已连线并准备就绪。


这意味着Angular是模板驱动的。您的模板驱动JavaScript,而不是相反。这是角色的彻底颠倒,与我们过去10年左右写的不引人注目的JavaScript完全相反。这可能需要一些时间来适应。


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


让我们深入了解细节。


首先,Angular不会取代jQuery



Angular和jQuery做了不同的事情。 AngularJS为您提供了一组用于生成Web应用程序的工具。 jQuery主要为您提供修改DOM的工具。如果您的页面上存在jQuery,AngularJS将自动使用它。如果不是这样,AngularJS附带了jQuery Lite,这是一个减少但仍然完美可用的jQuery版本。


Misko喜欢jQuery并且不会反对你使用它。但是你会发现,当你使用范围,模板和指令的组合完成所有你的工作时,你应该尽可能地选择这个工作流程。因为您的代码将更加离散,更具可配置性,并且更具角度。


如果你确实使用了jQuery,你就不应该把它洒到整个地方。在AngularJS中DOM操作的正确位置是一个指令。稍后会详细介绍。


使用选择器与声明模板的不显眼的JavaScript



jQuery通常不引人注意地应用。你的JavaScript代码链接在标题(或页脚)中,这是它唯一提到的地方。我们使用选择器来挑选页面的位并编写插件来修改这些部分。


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


您将注意到的关于AngularJS的第一件事是自定义属性无处不在。您的HTML将充满ng属性,这些属性基本上是类固醇上的onClick属性。这些是指令(编译器指令),并且是模板挂钩到模型的主要方式之一。


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


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


你的模板应该是声明性的;通过阅读它的含义应该很清楚。我们使用有意义名称的自定义属性。我们再次使用有意义的名称组成新的HTML元素。具有最少HTML知识且无编码技能的设计人员可以阅读您的AngularJS模板并了解它的作用。他或她可以进行修改。 这是Angular方式。


模板处于驾驶席位。



在开始使用AngularJS并运行教程时,我问自己的第一个问题是我的代码在哪里?。我没有写过任何JavaScript,但我有这些行为。答案是显而易见的。因为AngularJS编译DOM,AngularJS将你的HTML视为代码。对于许多简单的情况,只需编写一个模板就可以了AngularJS将它编译成一个应用程序。


您的模板可以驱动您的应用它被视为DSL。您编写AngularJS组件,AngularJS将负责将它们拉入并根据模板的结构在适当的时间使它们可用。这与标准MVC模式非常不同,其中模板仅用于输出。[67] [68]


例如,它比Ruby on Rails更类似于XSLT。[69] [70]


这是一种彻底的控制反转,需要一些人习惯。


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


语义HTML与语义模型



使用jQuery,您的HTML页面应包含具有语义意义的内容。如果JavaScript(由用户或搜索引擎)关闭,您的内容仍然可以访问。


因为AngularJS将您的HTML页面视为模板。模板不应该是语义的,因为您的内容通常存储在最终来自API的模型中。 AngularJS使用模型编译DOM以生成语义Web页面。


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


在AngularJS中,意思是生活在模型中,HTML只是一个模板,仅供显示。


在这一点上,你可能有各种关于SEO和可访问性的问题,这是正确的。这里存在未解决的问题。大多数屏幕阅读器现在将解析JavaScript。搜索引擎也可以索引AJAXed内容。不过,您需要确保使用的是pushstate URL,并且您有一个不错的站点地图。请参阅此处以了解该问题的讨论:https://stackoverflow.com/a/23245379/687677 [71] [72]


关注点分离(SOC)与MVC



关注点分离(SOC)是一种在多年的Web开发中长大的模式,其原因有多种,包括SEO,可访问性和浏览器不兼容性。它看起来像这样:[74]



  1. HTML - 语义。 HTML应该是独立的。

  2. CSS - 样式,没有CSS,页面仍然可读。

  3. JavaScript - 行为,没有脚本,内容仍然存在。



同样,AngularJS不遵守他们的规则。一举一动, AngularJS取消了十年的智慧,而是实现了一种MVC模式,其中模板不再是语义,甚至不是一点点。


它看起来像这样:



  1. 模型 - 您的模型包含您的语义数据。模型通常是JSON对象。模型作为名为$ scope的对象的属性存在。您还可以在$ scope上存储方便的实用程序函数,然后模板可以访问这些函数。

  2. 查看 - 您的观看次数以HTML格式编写。视图通常不是语义的,因为您的数据存在于模型中。

  3. Controller - 您的控制器是一个JavaScript函数,它将视图挂钩到模型。它的功能是初始化$ scope。根据您的应用程序,您可能需要也可能不需要创建控制器。您可以在页面上拥有多个控制器。



MVC和SOC不在相同比例的两端,它们位于完全不同的轴上。 SOC在AngularJS上下文中没有任何意义。你必须忘记它并继续前进。[75]


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


插件与指令



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


在jQuery中,我们通过向jQuery.prototype添加函数来定义插件。然后我们通过选择元素并在结果上调用插件将它们挂钩到DOM中。我们的想法是扩展jQuery的功能。


例如,如果您想在页面上使用轮播,则可以定义无序的图表列表,可能包含在nav元素中。然后,您可以编写一些jQuery来选择页面上的列表,并将其重新设置为具有超时的库以执行滑动动画。


在AngularJS中,我们定义了指令。指令是一个返回JSON对象的函数。该对象告诉AngularJS要查找哪些DOM元素,以及要对它们进行哪些更改。使用您发明的属性或元素将指令挂钩到模板。我们的想法是使用新的属性和元素扩展HTML的功能。


AngularJS方法是扩展本机外观HTML的功能。您应该编写看起来像HTML的HTML,并使用自定义属性和元素进行扩展。


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


许多小指令与配置开关的大插件



jQuery的趋势是编写像灯箱这样的大插件,然后我们通过传递大量的值和选项来配置。


这是AngularJS中的一个错误。


以下拉列表为例。在编写下拉插件时,您可能会想要在单击处理程序中进行编码,也许是一个添加到V形图中的功能,可以是向上或向下,也许更改展开元素的类,显示隐藏菜单,所有有用的东西。


直到你想做一个小改动。


假设您有一个要悬停的菜单。那么现在我们有一个问题。我们的插件已连接到我们的点击处理程序,我们需要添加一个配置选项,以使其在这种特定情况下的行为不同。


在AngularJS中,我们编写较小的指令。我们的下拉指令非常小。它可能保持折叠状态,并提供fold(),展开()或toggle()的方法。这些方法只会更新$ scope.menu.visible,它是一个保持状态的布尔值。


现在在我们的模板中我们可以将其连线:


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


需要在mouseover上更新?


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


该模板驱动应用程序,因此我们获得HTML级别的粒度。如果我们想要逐案例外,模板可以轻松实现。


关闭与$ scope



JQuery插件是在闭包中创建的。在该关闭内保持隐私。您可以在该闭包中维护您的作用域链。您只能访问通过jQuery传入插件的DOM节点集,以及闭包中定义的任何局部变量以及您定义的任何全局变量。意味着插件是完全自包含的。这是一件好事,但在创建整个应用程序时会受到限制。尝试在动态页面的各个部分之间传递数据变成了一件苦差事。


AngularJS有$ scope对象。这些是由AngularJS创建和维护的特殊对象,您可以在其中存储模型。某些指令将生成一个新的$ scope,默认情况下,它使用JavaScript原型继承继承其包装$ scope。 $ scope对象可在控制器和视图中访问。


这是聪明的部分。因为$ scope继承的结构大致遵循DOM的结构,所以元素可以无缝地访问它们自己的范围,任何包含范围,一直到全局$ scope(与全局范围不同)。


这使得传递数据和在适当级别存储数据变得更加容易。如果下拉列表展开,则只有下拉列表$ scope需要了解它。如果用户更新其首选项,您可能希望更新全局$ scope,并且将自动提醒监听用户首选项的任何嵌套作用域。


这可能听起来很复杂,事实上,一旦你放松它,它就像飞行。你不需要创建$ scope对象,AngularJS根据你的模板层次结构正确适当地为你实例化和配置它。然后,AngularJS使用依赖注入的魔力使其可用于您的组件(稍后将详细介绍)。


手动DOM更改与数据绑定



在jQuery中,您可以手动完成所有DOM更改。您以编程方式构造新的DOM元素。如果您有一个JSON数组并且想要将它放到DOM中,则必须编写一个函数来生成HTML并插入它。


在AngularJS中,您也可以这样做,但我们鼓励您使用数据绑定。更改您的模型,并且因为DOM通过模板绑定到它,您的DOM将自动更新,无需干预。


因为数据绑定是从模板完成的,使用属性或大括号语法,所以它非常容易实现。与之相关的认知开销很小,所以你会发现自己一直在做这件事。


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


将输入元素绑定到$scope.user.name。更新输入将更新当前范围中的值,反之亦然。


同样:


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


将在段落中输出用户名。这是一个实时绑定,所以如果更新$scope.user.name值,模板也会更新。


始终使用Ajax



在jQuery中进行Ajax调用是相当简单的,但它仍然是你可能会三思而后行的东西。思考的复杂性增加了,并且需要维护相当多的脚本。


在AngularJS中,Ajax是您的默认首选解决方案,它一直在发生,几乎没有您注意到。您可以包含ng-include模板。您可以使用最简单的自定义指令应用模板。您可以在服务中包装Ajax调用并创建一个GitHub服务或Flickr服务,您可以轻松访问它。[76] [77]


服务对象与助手功能



在jQuery中,如果我们想完成一个小的非dom相关任务,比如从API中提取一个feed,我们可能会在我们的闭包中写一个小函数来完成它。这是一个有效的解决方案,但是如果我们想要经常访问该数据包呢?如果我们想在另一个应用程序中重用该代码怎么办?


AngularJS为我们提供服务对象。


服务是包含函数和数据的简单对象。他们总是单身,这意味着他们永远不会超过一个。假设我们想要访问Stack Overflow API,我们可能会写一个StackOverflowService来定义这样做的方法。


假设我们有一个购物车。我们可以定义一个ShoppingCartService来维护我们的购物车,并包含添加和删除项目的方法。因为服务是一个单独的,并且由所有其他组件共享,所以任何需要可以写的对象到购物车并从中提取数据。它总是相同的购物车。


服务对象是自包含的AngularJS组件,我们可以根据需要使用和重用它们。它们是包含函数和数据的简单JSON对象。它们总是单例,因此如果您将数据存储在一个地方的服务中,您可以通过请求相同的服务将数据传输到其他地方。


依赖注入(DI)与Instatiation - 又称de-spaghettification



AngularJS为您管理您的依赖项。如果你想要一个对象,只需引用它,AngularJS就会为你得到它。[78]


在你开始使用它之前,很难解释这是多么大的时间。在jQuery中没有像AngularJS DI那样的东西。


DI意味着您不是编写应用程序并将它们连接在一起,而是定义一个组件库,每个组件都由一个字符串标识。


假设我有一个名为FlickrService的组件,它定义了从Flickr中提取JSON提要的方法。现在,如果我想编写一个可以访问Flickr的控制器,我只需要在声明控制器时按名称引用FlickrService。 AngularJS将负责实例化组件并使其可供我的控制器使用。


例如,我在这里定义一个服务:


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


现在,当我想使用该服务时,我只是按名称引用它:


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


AngularJS将认识到需要一个FlickrService对象来实例化控制器,并为我们提供一个。


这使得连接在一起非常容易,并且几乎消除了任何倾向于spagettification的趋势。我们有一个平面的组件列表,当我们需要时,AngularJS将它们逐个交给我们。


模块化服务架构



jQuery对如何组织代码几乎没有说明。 AngularJS有意见。


AngularJS为您提供了可以放置代码的模块。例如,如果您正在编写一个与Flickr对话的脚本,您可能需要创建一个Flickr模块来包装所有与Flickr相关的函数。模块可以包含其他模块(DI)。您的主应用程序通常是一个模块,这个应该包括您的应用程序将依赖的所有其他模块。


您可以获得简单的代码重用,如果您想基于Flickr编写另一个应用程序,您可以只包含Flickr模块,您可以访问新应用程序中的所有Flickr相关功能。


模块包含AngularJS组件。 当我们包含一个模块时,该模块中的所有组件都可以作为由其唯一字符串标识的简单列表提供给我们。然后我们可以使用AngularJS的依赖注入机制将这些组件相互注入。


总结



AngularJS和jQuery不是敌人。可以非常好地在AngularJS中使用jQuery。如果你正在使用AngularJS(模板,数据绑定,$ scope,指令等),你会发现你需要一个很多少jQuery比你可能需要的更多。


要实现的主要是您的模板驱动您的应用程序。停止尝试编写可以完成所有操作的大插件。而是写一些做一件事的指令,然后编写一个简单的模板将它们连接在一起。


少考虑不引人注目的JavaScript,而是考虑HTML扩展。


我的小书



我对AngularJS感到非常兴奋,我写了一本关于它的简短书籍,非常欢迎您在线阅读http://nicholasjohnson.com/angular-book/。我希望它有所帮助。[79]

其它参考3



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



势在必行与声明


使用 jQuery ,您可以一步一步地告诉DOM需要发生什么。使用 AngularJS ,您可以描述您想要的结果,但不能说明如何执行此操作。更多关于这里。另外,请查看Mark Rajcok的回答。[80]



  如何以不同方式构建和设计客户端Web应用程序?



AngularJS是一个使用MVC模式的完整客户端框架(查看其图形表示)。它非常注重关注点的分离。[82] [83]



  最大的区别是什么?我应该停止做什么/使用什么;我应该开始做什么/使用呢?



jQuery 是一个库


AngularJS 是一个漂亮的客户端框架,高度可测试,它结合了许多很酷的东西,如MVC,依赖注入,数据绑定等等。 [84]


它侧重于关注点和测试(单元测试和端到端测试)的分离,这有助于测试驱动的开发。[85] [86]


最好的方法是通过他们的精彩教程。你可以在几个小时内完成这些步骤;但是,如果你想掌握幕后的概念,它们包含了无数的进一步阅读参考。[87]



  有任何服务器端考虑因素/限制吗?



您可以在已经使用纯jQuery的现有应用程序上使用它。但是,如果您想充分利用AngularJS功能,可以考虑使用RESTful方法对服务器端进行编码。[88]


这样做将允许您利用他们的资源工厂,它创建服务器端RESTful API的抽象,并使服务器端调用(获取,保存,删除等)非常容易。[89] [90]

其它参考4


为了描述范式转换,我认为一个简短的回答就足够了。


AngularJS改变了找到元素的方式



jQuery 中,您通常使用选择器来查找元素,然后将它们连接起来:

$('#id .class').click(doStuff);


AngularJS 中,您可以使用指令直接标记元素,以便将它们连接起来:

<a ng-click="doStuff()">


AngularJS不需要(或想要)使用选择器查找元素 - AngularJS的 jqLit​​e 与完整的 jQuery 之间的主要区别在于jqLit​​e不支持选择器。 [91]


因此,当人们说根本不包含jQuery时,主要是因为他们不希望你使用选择器;他们希望你学习使用指令。直接,而不是选择!

其它参考5


的jQuery



jQuery使getElementByHerpDerp缩短和跨浏览器等JavaScript命令变得非常冗长。


AngularJS



AngularJS允许您创建自己的HTML标记/属性,这些标记/属性可以很好地处理动态Web应用程序(因为HTML是为静态页面设计的)。


编辑:



说我有一个jQuery背景我如何在AngularJS中思考?就像说我有一个HTML背景我如何在JavaScript中思考?你问这个问题的事实表明你很可能不理解这两种资源的根本目的。这就是为什么我选择通过简单地指出基本区别来回答问题,而不是通过列表说AngularJS使用指令,而jQuery使用CSS选择器来创建一个jQuery对象来执行此操作等等...... 。这个问题不需要冗长的答案。


jQuery是一种使浏览器中的JavaScript编程更容易的方法。更短,跨浏览器的命令等


AngularJS扩展了HTML,所以你不必将<div>放在所有地方只是为了创建一个应用程序。它使HTML实际上适用于应用程序而不是它的用途专为静态教育网页而设计。它使用JavaScript以迂回的方式实现这一点,但从根本上说它是HTML的扩展,而不是JavaScript。

其它参考6


jQuery:你对DOM元素的查询DOM和做某事有很多想法。[92]


AngularJS:模型是事实,你总是从那个角度思考。


例如,当您从服务器获取要在DOM中以某种格式显示的数据时,在jQuery中,您需要1. FIND在DOM中您要放置此数据的位置,2。UPDATE/APPEND通过创建新节点或仅设置其innerHTML来实现它。然后,当您想要更新此视图时,然后3.查找该位置和4.更新。在AngularJS中,在从服务器获取和格式化数据的相同上下文中完成的查找和更新周期都已消失。[93]


使用AngularJS,你有你的模型(你已经习惯的JavaScript对象),模型的值告诉你模型(显然)和视图,模型上的操作自动传播到视图,所以你不要我必须考虑一下。你会发现自己在AngularJS中不再在DOM中找到东西。


换句话说,在jQuery中,你需要考虑CSS选择器,即具有类或属性等的divtd,以便我可以得到它们HTML或颜色或值,但在AngularJS中,你会发现自己这样想:我正在处理什么模型,我会将模型的值设置为true。你不会在思考反映这个值的视图是否是一个选中框或驻留在td元素中(在jQuery中经常需要考虑的细节)。


在AngularJS中使用DOM操作,您会发现自己添加了指令和过滤器,您可以将其视为有效的HTML扩展。


你将在AngularJS中体验到的另一件事:在jQuery中你调用jQuery函数很多,在AngularJS中,AngularJS会调用你的函数,所以AngularJS会告诉你如何做事,但是它的好处是值得的,所以学习AngularJS通常意味着学习AngularJS想要的东西或者AngularJS要求你展示你的功能的方式,它会相应地调用它。这是使AngularJS成为框架而不是库的因素之一。

其它参考7


这些是一些非常好的,但冗长的答案。


总结一下我的经历:



  1. 控制器和提供者(服务,工厂等)用于修改数据模型,而不是HTML。

  2. HTML和指令定义布局和与模型的绑定。

  3. 如果您需要在控制器之间共享数据,创建服务或工厂 - 它们是在整个应用程序中共享的单例。

  4. 如果您需要HTML小部件,请创建指令。

  5. 如果您有一些数据,现在正在尝试更新HTML ...停止!更新模型,并确保您的HTML绑定到模型。


其它参考8


jQuery是一个DOM操作库。


AngularJS是一个MV *框架。


事实上,AngularJS是为数不多的JavaScript MV *框架之一(许多JavaScript MVC工具仍属于类别库)。


作为一个框架,它托管您的代码,并拥有决定调用什么以及何时调用的所有权!


AngularJS本身包含一个jQuery-lite版本。因此,对于一些基本的DOM选择/操作,您实际上不必包含jQuery库(它可以节省许多字节以在网络上运行。)


AngularJS具有用于DOM操作和设计可重用UI组件的指令概念,因此您应该在需要执行与DOM操作相关的东西时使用它(指令只是在使用AngularJS时应该编写jQuery代码的地方)。


AngularJS涉及一些学习曲线(超过jQuery :-)。


- >对于任何来自jQuery背景的开发人员,我的第一个建议是在开始使用像AngularJS这样的丰富框架之前,将JavaScript作为一流语言学习!
我用艰难的方式了解了上述事实。


祝你好运。

其它参考9


他们是苹果和橘子。你不想比较它们。它们有两个不同的东西.AngularJs已经内置了jQuery lite,它允许你执行基本的DOM操作,甚至不包括完整的jQuery版本。


jQuery是关于DOM操作的。它解决了所有跨浏览器的痛苦,否则你将不得不处理,但它不是一个允许你将你的应用程序划分为像AngularJS这样的组件的框架。


AngularJs的一个好处是它允许您在指令中分离/隔离DOM操作。有内置指令可供您使用,例如ng-click。您可以创建自己的自定义指令,其中包含所有视图逻辑或DOM操作,因此您不会在应该处理业务逻辑的控制器或服务中混合使用DOM操作代码。


Angular将您的应用分解为
- 控制器
- 服务
- 意见
- 等


还有一件事,那就是指令。它是一个你可以附加到任何DOM元素的属性,你可以在其中使用jQuery,而不必担心你的jQuery与AngularJs组件发生冲突或者与其架构混淆。


我从参加过的聚会中听到,Angular的一位创始人表示他们非常努力地将DOM操作分开,所以不要试图将它们包括在内。

其它参考10


收听播客 JavaScript Jabber:第32集,其中包含AngularJS的原始创作者:Misko Hevery&伊戈尔·米纳尔。他们谈了很多关于从其他JavaScript背景来到AngularJS的感觉,特别是jQuery。[94]


在播客中提出的观点之一让我对你的问题有所了解:



   MISKO :[[...]]我们在Angular中很少考虑的事情之一就是,我们如何提供大量的逃生舱,这样你就可以走出去,基本上找出一条出路。所以对我们来说,答案就是这个叫做指令的东西。 使用指令,你基本上成为一个常规的小jQuery JavaScript,你可以做任何你想做的事。

  
   IGOR :因此,将指令视为编译器的指令,只要您遇到模板中的某个元素或此CSS,就会告诉它,并保留此类代码并且代码负责DOM树中该元素下面的元素和所有内容。



整个剧集的成绩单可在上面提供的链接中找到。


所以,直接回答你的问题:AngularJS是非常自以为是的,是一个真正的MV *框架。但是,你仍然可以在指令中使用jQuery来完成你所熟悉和喜爱的所有非常酷的东西。这不是我如何在jQuery中做我曾经做过的事情?的问题,而是如何使用我以前在jQuery中做的所有事情来补充AngularJS?


这真的是两种非常不同的心态。

其它参考11


我发现这个问题很有意思,因为我第一次认真接触JavaScript编程的是Node.js和AngularJS。我从来没有学过jQuery,我想这是件好事,因为我不必忘记任何事情。事实上,我主动避免jQuery解决方案来解决我的问题,而只是寻找一种AngularJS方式来解决它们。所以,我想我对这个问题的回答基本上归结为想象一个从未学过jQuery的人并避免任何直接合并jQuery的诱惑(显然AngularJS在某种程度上在幕后使用它)。[95]

其它参考12


AngularJS和jQuery:


除了JQLite功能之外,AngularJs和JQuery在每个级别都完全不同,一旦你开始学习AngularJs的核心功能,你就会看到它(我在下面解释过)。


AngularJs是一个客户端框架,用于构建独立的客户端应用程序。 JQuery是一个围绕DOM的客户端库。


AngularJs Cool Principle - 如果您希望在UI上进行一些更改,请从模型数据更改角度进行思考。更改您的数据和UI将重新呈现自己。你不需要每次都玩DOM,除非并且直到它几乎不需要,并且也应该通过Angular Directives来处理。


要回答这个问题,我想与AngularJS分享我在第一个企业应用程序上的经验。这些是Angular提供的最强大的功能,我们开始改变我们的jQuery思维模式,我们将Angular看作框架而不是库。


双向数据绑定非常棒:
我有一个网格,所有功能都是UPDATE,DELTE,INSERT。我有一个数据对象,使用ng-repeat绑定网格的模型。你只需要编写一行简单的JavaScript代码用于删除和插入即可。当网格模型立即更改时,网格会自动更新。更新功能是实时的,没有代码。
你觉得很棒!


可重复使用的指令是超级的:
在一个地方写指令并在整个应用程序中使用它。我的天啊!!!我使用这些指令进行分页,正则​​表达式,验证等等。真的很酷!


路由很强:
这取决于您的实现如何使用它,但它需要很少的代码行来路由请求以指定HTML和控制器(JavaScript)


控制器很棒:
控制器会处理自己的HTML,但这种分离对于常见功能也很有效。如果要在主HTML上单击按钮调用相同的函数,只需在每个控制器中写入相同的函数名称并编写单独的代码。


插件:
还有许多其他类似功能,例如在您的应用中显示叠加层。你不需要为它编写代码,只需使用一个可用作wc-overlay的覆盖插件,这将自动处理所有XMLHttpRequest(XHR)请求。[96]


RESTful架构的理想选择:
作为一个完整的框架,AngularJS非常适合使用RESTful架构。调用REST CRUD API非常容易,[97]


服务:使用服务编写公共代码,在控制器中编写更少的代码。服务可用于共享控制器之间的共同功能。


可扩展性:Angular使用angular指令扩展了HTML指令。在html中编写表达式并在运行时评估它们。创建自己的指令和服务,并在不需要额外努力的情况下在另一个项目中使用它们。

其它参考13


作为一个JavaScript MV *初学者,纯粹关注应用程序架构(不是服务器/客户端问题),我肯定会推荐以下资源(我很惊讶还没有提到):JavaScript设计模式,作者:Addy Osmani ,作为对不同 JavaScript设计模式的介绍。本答案中使用的术语来自上面的链接文档。我不会在接受的答案中重复措辞。相反,这个答案链接回理论背景,它为AngularJS(和其他图书馆)提供动力。[98]


像我一样,你会很快意识到AngularJS(或Ember.js,Durandal,以及其他MV *框架)是一个复杂的框架,它汇集了许多不同的JavaScript设计模式。[99]


我发现在潜水之前测试(1)本机JavaScript代码以及(2)这些模式单独中的每一个更容易进入一个全球框架。这使我能够更好地理解框架所针对的哪些关键问题(因为您个人面临问题)。


例如:



  • JavaScript面向对象编程(这是一个Google搜索链接)。它不是一个库,但肯定是任何应用程序编程的先决条件。它告诉我原型,构造函数,单例和&的原生实现。装饰图案

  • jQuery/Underscore用于外观模式(就像WYSIWYG用于操作DOM一样)

  • 原型/构造函数/mixin模式
  • 的Prototype.js
  • 模块模式/AMD
  • 的RequireJS/Curl.js
  • KnockoutJS用于可观察,发布/订阅模式



注意:这个列表不完整,也不是最好的图书馆;它们恰好是我使用的库。这些库还包括更多模式,提到的模式只是它们的主要焦点或原始意图。如果您觉得此列表中缺少某些内容,请在评论中提及,我很乐意添加它。[100] [101] [102] [103] [104] [105] [106]

其它参考14


实际上,如果你正在使用AngularJS,你就不再需要jQuery了。 AngularJS本身具有绑定和指令,对于您可以使用jQuery执行的大多数事情来说,这是一个非常好的替代。


我通常使用AngularJS和Cordova开发移动应用程序。我需要的jQuery唯一的东西是Selector。[107]


通过谷歌搜索,我看到有一个独立的jQuery选择器模块。这是嘶嘶声。


我决定制作一个小代码片段,帮助我使用AngularJS快速启动一个具有jQuery Selector功能的网站(使用Sizzle)。


我在这里分享了我的代码:https://github.com/huytd/Sizzular [108]