首页 文章

如果我有jQuery背景,“在AngularJS中思考”? [关闭]

提问于
浏览
4523

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

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

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

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

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

15 回答

  • 31

    AngularJS and jQuery:

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

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

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

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

    Two-way data binding is amazing: 我有一个网格,所有功能都是UPDATE,DELTE,INSERT . 我有一个数据对象绑定网格's model using ng-repeat. You only need to write a single line of simple JavaScript code for delete and insert and that'它 . 当网格模型立即更改时,网格会自动更新 . 更新功能是实时的,没有代码 . 你觉得很棒!

    Reusable directives are super: 在一个地方写指令并在整个应用程序中使用它 . 我的天啊!!!我使用这些指令进行分页,正则表达式,验证等等 . 真的很酷!

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

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

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

    Ideal for RESTful architecture: 作为一个完整的框架,AngularJS非常适合使用RESTful架构 . 调用REST CRUD API非常简单

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

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

  • 30

    1.不要设计页面,然后使用DOM操作进行更改

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

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

    2.不要使用AngularJS扩充jQuery

    同样,只需在模型和控制器的基础上添加AngularJS即可 . 当你完全使用jQuery时,这真的很诱人,至少在他们习惯于"Angular Way"之前 .

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

    底线是:解决时,首先"think in AngularJS";如果你想不出解决方案,请问社区;如果完全没有简单的解决方案,那么随时可以找到jQuery . 但是从来没有掌握AngularJS .

    3.总是在架构方面思考

    首先要知道single-page applications是应用程序 . 他们不是网页 . 因此,我们需要像服务器端开发人员一样思考,而不是像客户端开发人员那样思考 . 我们必须考虑如何将我们的应用程序划分为单独的,可扩展的,可测试的组件 .

    那你怎么做的呢?你好吗"think in 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的上下文中使用"do 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中,我们有一个单独的模型层,我们可以以任何方式管理,完全独立于视图 . 这有助于上述数据绑定,维护separation of concerns,并引入更大的可测试性 . 其他答案提到了这一点,所以我就把它留在那里 .

    关注点分离

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

    依赖注入

    帮助我们解决问题的分离是dependency injection(DI) . 如果你来自服务器端语言(从JavaPHP),那么're probably familiar with this concept already, but if you'是一个来自jQuery的客户端人,这个概念看起来似乎从愚蠢到多余到时髦 . 但事实并非如此 . :-)

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

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

    说到测试......

    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

    你会经常听到"only do DOM manipulation in a directive" . This is a necessity. 善意对待它!

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

    一些指令只是装饰视图中已经存在的东西(想想 ngClass ),因此有时会直接进行DOM操作,然后基本完成 . 但是如果一个指令就像一个"widget"并且有一个模板,那么它也应该尊重关注点的分离 . 也就是说,模板也应该在很大程度上独立于链接和控制器功能中的实现 .

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

    我看到许多开发人员对AngularJS很新,使用指令作为抛出一堆jQuery的地方 . 换句话说,他们认为"since I can't do DOM manipulation in the controller, I'll take that code put it in a directive" . 虽然这当然要好得多,但它通常仍然是错误的 .

    认为我们在第3节中编写的 Logger . 即使我们把它放在一个指令中,我们仍然希望这样做"Angular Way" . 它仍然没有你想象的那么罕见!在应用程序中的任何位置进行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);
                });
            }
        };
    });
    

    这有一些问题:

    • 首先,jQuery从来都不是必需的 . 我们在这里做的一切都不需要jQuery!

    • 其次,即使我们的页面上已经有jQuery,也没有理由在这里使用它;我们可以简单地使用 angular.element ,我们的组件在放入没有jQuery的项目时仍然可以工作 .

    • 第三,即使假设此指令需要jQuery才能工作,jqLite( angular.element )将始终使用jQuery(如果已加载)!所以我们不需要使用 $ - 我们可以使用 angular.element .

    • 第四,与第三个密切相关的是,jqLite元素不需要包含在 $ 中 - 传递给 link 函数的 element 已经是jQuery元素!

    • 第五,我们在之前的章节中已经提到过,为什么我们将模板内容混合到我们的逻辑中?

    这个指令可以重写(即使对于非常复杂的情况!)更简单如下:

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

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

    还有所有其他好处,比如测试 - 这很容易!无论模板中有什么内容,指令的内部API都不会被触及,因此重构很容易 . 您可以根据需要更改模板,而无需触及指令 . 无论你改变什么,你的测试仍然通过 .

    w00t!

    因此,如果指令不仅仅是类jQuery函数的集合,它们是什么?指令实际上是 extensions of HTML . 如果HTML不需要它做某事,你可以编写一个指令来为你做,然后就像使用它一样使用它 .

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

    摘要

    唐't even use jQuery. Don'甚至包括它 . 它会阻止你 . 当你遇到一个问题,你认为你已经知道如何在jQuery中解决,在你到达 $ 之前,试着考虑如何在AngularJS范围内做到这一点 . 如果您不需要jQuery并尝试使用jQuery解决它,那么更多的工作将为您服务 .

  • 408

    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作为一流语言学习!”我用艰难的方式了解了上述事实 .

    祝好运 .

  • 184

    jQuery

    jQuery制作了一些可笑的长命令,如 getElementByHerpDerp 更短和跨浏览器 .

    AngularJS

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

    编辑:

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

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

    AngularJS扩展了HTML,因此您不必将 <div> 放在任何地方只是为了创建一个应用程序 . 它使HTML实际上适用于应用程序而不是它的设计目标,即静态的教育网页 . 它使用JavaScript以迂回的方式实现这一点,但从根本上说它是HTML的扩展,而不是JavaScript .

  • 152

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

    Imperative vs Declarative

    使用 jQuery ,您可以一步一步地告诉DOM需要发生什么 . 使用 AngularJS ,您可以描述您想要的结果,但不能说明如何操作 . 更多关于这个here . 另外,请查看Mark Rajcok的答案 .

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

    AngularJS是一个使用MVC模式的整个客户端框架(请查看他们的graphical representation) . 它非常注重关注点的分离 .

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

    jQuery 是一个图书馆

    AngularJS 是一个漂亮的客户端框架,高度可测试,它结合了许多很酷的东西,如MVC,dependency injection,数据绑定等等 .

    它侧重于separation of concerns和测试(unit testing和端到端测试),这有助于测试驱动开发 .

    最好的开始方式是their awesome tutorial . 你可以在几个小时内完成这些步骤;但是,如果你想掌握幕后的概念,它们包含了无数的参考资料以供进一步阅读 .

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

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

    这样做将允许您利用他们的resource factory,它创建服务器端RESTful API的抽象,并使服务器端调用(获取,保存,删除等)非常容易 .

  • 7185

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

    AngularJS改变了你找到元素的方式

    jQuery 中,您通常使用 selectors 来查找元素,然后将它们连接起来:
    $('#id .class').click(doStuff);

    AngularJS 中,您使用 directives 直接标记元素,把它们连接起来:
    <a ng-click="doStuff()">

    AngularJS没有 jqLite 与完全成熟的 jQueryjqLite does not support selectors .

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

  • 23

    作为一个JavaScript MV *初学者,纯粹关注应用程序架构(而不是服务器/客户端问题),我肯定会推荐以下资源(我很惊讶还没有提到):JavaScript Design Patterns,作者Addy Osmani,as介绍不同的 JavaScript Design Patterns . 本答案中使用的术语来自上面的链接文档 . 我不打算在接受的答案中重复措辞 . 相反,这个答案链接回 theoretical backgrounds ,它为AngularJS(和其他库)提供动力 .

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

    我发现在进入一个全局框架之前,为这些模式中的每一个测试 (1) 原生JavaScript代码和 (2) 个较小的库也更容易 . 这使我能够更好地理解框架所针对的哪些关键问题(因为您个人面临问题) .

    例如:

    • JavaScript Object-oriented Programming(这是Google搜索链接) . 它不是一个库,但肯定是任何应用程序编程的先决条件 . 它告诉我 prototype, constructor, singleton & decorator patterns 的原生实现
      facade pattern
    • jQuery / Underscore(就像WYSIWYG用于操纵DOM一样)
      169 Prototype.js代表 prototype/ constructor/ mixin pattern
      169 RequireJS / Curl.js for module pattern/ AMD
      169 KnockoutJSobservable, publish/subscribe pattern

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

  • 84

    我觉得这个问题很有意思,因为我第一次认真接触JavaScript编程是Node.js和AngularJS . 我从来没有学过jQuery,我想's a good thing, because I don' t必须忘掉任何东西 . 事实上,我主动避免jQuery解决方案来解决我的问题,而只是寻找"AngularJS way"来解决它们 . 所以,我想我对这个问题的回答基本上归结为,"think like someone who never learned jQuery"并避免任何直接合并jQuery的诱惑(显然AngularJS在某种程度上在幕后使用它) .

  • 61

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

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

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

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

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

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

  • 46

    jQuery:你想了很多关于'查询DOM'的DOM元素并做了些什么 .

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

    例如,当您从服务器获取要在DOM中以某种格式显示的数据时,在jQuery中,您需要_St4886_在DOM中您想要放置此数据的位置,'2. UPDATE/APPEND'它通过创建新节点或只需设置innerHTML . 然后,当您想要更新此视图时,您将'3. FIND'位置和'4. UPDATE' . 在AngularJS中,在从服务器获取和格式化数据的相同上下文中完成所有查找和更新循环 .

    使用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成为框架而不是库的因素之一 .

  • 45

    收听播客JavaScript Jabber: Episode #32,其中包含AngularJS的创作者:Misko Hevery和Igor Minar . 他们谈论了从其他JavaScript背景到AngularJS的内容,特别是jQuery .

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

    MISKO:[...]我们在Angular中很难想到的事情之一是,我们如何提供大量的逃生舱,这样你就可以走出去,基本上找到了解决这个问题的方法 . 所以对我们来说,答案就是这个叫做“指令”的东西 . 使用指令,你基本上成为一个常规的小jQuery JavaScript,你可以做任何你想做的事情 . IGOR:所以将指令视为编译器的指令,告诉它每当你遇到模板中的这个特定元素或这个CSS时,你就会保留这种代码,并且代码负责元素以及该元素下面的所有内容在DOM树中 .

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

    所以,直接回答你的问题:AngularJS是非常自以为是的,是一个真正的MV *框架 . 但是,你仍然可以在指令中使用jQuery来完成你所熟悉和喜爱的所有非常酷的东西 . 这不是“我如何做我在jQuery中常用的东西?”的问题 . 就像“我如何用jQuery中的所有东西来补充AngularJS一样”这个问题一样多 . “

    这真的是两种截然不同的心态 .

  • 20

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

    总结一下我的经历:

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

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

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

    • 如果需要HTML小部件,请创建指令 .

    • 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.

  • 12

    势在必行→陈述性

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

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

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

    关注点分离

    jQuery使用unobtrusive JavaScript - 行为(JavaScript)与结构(HTML)分离 .

    AngularJS使用 controllers 和指令(每个指令都有自己的控制器和/或编译和链接函数)来从视图/结构(HTML)中删除行为 . Angular还有 servicesfilters 来帮助分离/组织您的应用程序 .

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

    应用程序设计

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

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

    • 想想你想要如何展示你的模特 - 你的观点 . 为每个视图创建HTML模板,使用必要的指令来获得动态数据绑定 .

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

    原型继承

    你可以在不知道JavaScript原型继承如何工作的情况下使用jQuery做很多事情 . 在开发AngularJS应用程序时,如果您对JavaScript继承有很好的理解,就可以避免一些常见的陷阱 . 推荐阅读:What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

  • 69

    AngularJS与jQuery

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

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

    差异很大(TLDR)

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

    AngularJS反而给你一个 compiler .

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

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

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

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

    如果这听起来像是过度规范和限制,那么事实就没有什么可以了 . 因为AngularJS将您的HTML视为代码,所以得到 HTML level granularity in your web application . 一切皆有可能,一旦你做出一些概念上的飞跃,大多数事情都会非常容易 .

    让我们深入了解细节 .

    首先,Angular不会取代jQuery

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

    Misko喜欢jQuery并且不反对你使用它 . 但是,随着您的进步,您会发现使用范围,模板和指令的组合可以完成所有工作,并且您应该尽可能地选择此工作流程,因为您的代码将更加离散,更易于配置,以及更多角 .

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

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

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

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

    您将注意到的关于AngularJS的第一件事就是 custom attributes are everywhere . 您的HTML将充满ng属性,这些属性基本上是类固醇上的onClick属性 . 这些是指令(编译器指令),并且是模板挂钩到模型的主要方式之一 .

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

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

    你的模板应该是声明性的;通过阅读它的含义应该很清楚 . 我们使用有意义名称的自定义属性 . 我们再次使用有意义的名称组成新的HTML元素 . 一位设计师最小的HTML知识和没有编码技能可以读取您的AngularJS模板并了解它在做什么 . 他或她可以进行修改 . 这是Angular的方式 .

    模板位于驾驶席位 .

    在启动AngularJS并运行教程时,我问自己的第一个问题之一是 "Where is my code?" . 我只需编写一个模板就可以了,让AngularJS将它编译成一个应用程序 .

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

    例如,它与XSLT更相似,而不是Ruby on Rails .

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

    Stop trying to drive your application from your JavaScript. Let the template drive the application, and let AngularJS take care of wiring the components together. This also is the Angular way.

    语义HTML与语义模型

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

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

    Your HTML source is no longer semantic, instead, your API and compiled DOM are semantic.

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

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

    关注点分离(SOC)与MVC

    Separation of concerns(SOC)是一种由于各种原因(包括SEO,可访问性和浏览器不兼容性)而在多年的Web开发中成长的模式 . 它看起来像这样:

    • HTML - 语义 . HTML应该是独立的 .

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

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

    同样,AngularJS不遵守他们的规则 . 在一个笔划中, AngularJS does away with a decade of received wisdom 而是实现了一个MVC模式,其中模板不再是语义,甚至不是一点点 .

    它看起来像这样:

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

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

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

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

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

    插件与指令

    Plugins extend jQuery. AngularJS Directives extend the capabilities of your browser.

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

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

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

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

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

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

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

    这是AngularJS中的一个错误 .

    以下拉列表为例 . 在编写下拉插件时,您可能很想在单击处理程序中编写代码,也许是一个要添加的函数chevron,无论是向上还是向下,也许改变展开元素的类,显示隐藏菜单,所有有用的东西 .

    直到你想做一个小改动 .

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

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

    现在 in our template 我们可以连线:

    <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级别的粒度 . 如果我们想要逐案例外,模板可以轻松实现 .

    关闭与$范围

    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" />
    

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

    同样:

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

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

    Ajax一直以来

    在jQuery中进行Ajax调用相当简单,但它仍然可以考虑三次 . 这需要考虑增加的复杂性,以及需要维护的大量脚本 .

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

    服务对象与助手功能

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

    AngularJS为我们提供服务对象 .

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

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

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

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

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

    在你开始使用它之前,很难解释这是多么大的时间 . 在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组件 . When we include a module, all the components in that module become available to us as a simple list identified by their unique strings . 然后我们可以使用AngularJS的依赖注入机制将这些组件相互注入 .

    总结一下

    AngularJS和jQuery不是敌人 . 它很好地使用AngularJS(模板,数据绑定,$范围,指令等)你会发现你需要一个比你原本需要的更少的jQuery .

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

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

    我的小书

    我对AngularJS感到非常兴奋,我写了一本关于它的短篇小说,非常欢迎您在线阅读http://nicholasjohnson.com/angular-book/ . 我希望它有用 .

  • 34

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

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

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

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

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

相关问题