本文介绍了《用 AngularJS 思考》如果我有 jQuery 背景?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  • 如何以不同的方式构建和设计客户端 Web 应用程序?最大的区别是什么?
  • 我应该停止做什么/使用什么;我应该开始做什么/使用什么?
  • 是否有任何服务器端注意事项/限制?

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

解决方案

1.不要设计您的页面,然后使用 DOM 操作

更改它

在 jQuery 中,您设计一个页面,然后使其动态化.这是因为 jQuery 是为增强而设计的,并且在这个简单的前提下取得了令人难以置信的发展.

但是在 AngularJS 中,您必须从头开始考虑您的架构.与其从思考我有这块 DOM 并且我想让它做 X"开始,你必须从你想要完成的事情开始,然后设计你的应用程序,最后设计你的视图.

2.不要用 AngularJS 扩充 jQuery

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

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

底线是这样的:在解决的时候,首先在AngularJS中思考";如果您想不出解决方案,请询问社区;如果毕竟没有简单的解决方案,然后请随时使用 jQuery.但是不要让 jQuery 成为拐杖,否则你将永远无法掌握 AngularJS.

3.始终从架构的角度思考

首先要知道单页应用程序应用程序.它们不是网页.因此,除了像客户端开发人员那样思考之外,我们还需要像服务器端开发人员那样思考.我们必须考虑如何将我们的应用程序划分为单独的、可扩展的、可测试的组件.

那么你是怎么做到的?你如何在 AngularJS 中思考"?以下是一些与 jQuery 对比的一般原则.

观点是官方记录"

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

  • <a href="#/home">首页</a>
  • <li><a href="#/menu1">菜单 1</a><ul><li><a href="#/sm1">子菜单 1</a></li><li><a href="#/sm2">子菜单 2</a></li><li><a href="#/sm3">子菜单 3</a></li>
<li><a href="#/home">菜单 2</a>

在 jQuery 中,在我们的应用程序逻辑中,我们将使用以下内容激活它:

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

当我们只看视图时,并不会立即发现这里有任何功能.对于小型应用程序,这很好.但对于非平凡的应用程序,事情很快就会变得混乱且难以维护.

不过,在 AngularJS 中,视图是基于视图的功能的官方记录.我们的 ul 声明看起来像这样:

    ...

这两个做同样的事情,但在 AngularJS 版本中,任何查看模板的人都知道应该发生什么.每当开发团队的新成员加入时,她都可以查看此内容,然后知道有一个名为 dropdownMenu 的指令在其上运行;她不需要凭直觉得出正确答案或筛选任何代码.视图告诉我们应该发生什么.干净多了.

刚接触 AngularJS 的开发人员经常会问这样的问题:如何找到特定类型的所有链接并在其中添加指令.当我们回答:你没有时,开发人员总是大吃一惊.但你不这样做的原因是这就像半 jQuery、半 AngularJS,而且不好.这里的问题是开发人员试图在 AngularJS 的上下文中执行 jQuery".这永远不会奏效.视图官方记录.在指令之外(下面将详细介绍),您永远不会,永远,永远 更改 DOM.并且指令被应用在视图中,所以意图很明确.

记住:不要设计,然后标记.您必须先架构,然后再设计.

数据绑定

这是迄今为止 AngularJS 最棒的功能之一,并且省去了我在上一节中提到的各种 DOM 操作的需要.AngularJS 会自动更新你的视图,所以你不必更新!在 jQuery 中,我们响应事件然后更新内容.类似的东西:

$.ajax({url: '/myEndpoint.json',成功:功能(数据,状态){$('ul#log').append('<li>收到数据!</li>');}});

对于看起来像这样的视图:

    除了混合关注点之外,我们还存在我之前提到的表示意图的相同问题.但更重要的是,我们必须手动引用和更新 DOM 节点.如果我们想删除一个日志条目,我们也必须针对 DOM 进行编码.除了DOM,我们如何测试逻辑?如果我们想更改演示文稿怎么办?

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

    $http( '/myEndpoint.json' ).then( function ( response ) {$scope.log.push( { msg: '收到数据!' } );});

    我们的视图可以是这样的:

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

    但就此而言,我们的观点可能如下所示:

    <div class="alert" ng-repeat="日志条目">{{ entry.msg }}

    现在我们不再使用无序列表,而是使用 Bootstrap 警告框.而且我们永远不必更改控制器代码!但更重要的是,无论日志在何处如何更新,视图也会发生变化.自动地.整洁!

    虽然我没有在这里展示,但数据绑定是双向的.因此,这些日志消息也可以通过执行以下操作在视图中进行<input ng-model="entry.msg"/>.有很多欢欣鼓舞.

    不同的模型层

    在 jQuery 中,DOM 有点像模型.但是在 AngularJS 中,我们有一个单独的模型层,我们可以以任何我们想要的方式管理它,完全独立于视图.这有助于上述数据绑定,维护关注点分离,并引入了更高的可测试性.其他答案提到了这一点,所以我就留在那里.

    关注点分离

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

    依赖注入

    帮助我们解决关注点分离的是依赖注入 (DI).如果您来自服务器端语言(从 JavaPHP) 你可能已经熟悉这个概念,但如果你是来自 jQuery 的客户端人员,这个概念看起来从愚蠢到多余再到时髦.但事实并非如此.:-)

    从广泛的角度来看,DI 意味着您可以非常自由地声明组件,然后从任何其他组件中,只需请求它的一个实例,它就会被授予.您不必知道加载顺序、文件位置或类似内容.威力可能不会立即显现,但我将仅提供一个(常见)示例:测试.

    假设在我们的应用程序中,我们需要一个通过 REST API 以及本地存储(取决于应用程序状态).在我们的控制器上运行测试时,我们不想与服务器通信 - 毕竟我们正在测试 控制器.我们只需添加一个与原始组件同名的模拟服务,注入器将确保我们的控制器自动获取虚假服务 - 我们的控制器不知道也不需要知道其中的区别.

    说到测试...

    4.测试驱动的开发 - 总是

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

    在您见过、使用或编写过的所有 jQuery 插件中,有多少带有随附的测试套件?不是很多,因为 jQuery 不太适合.但 AngularJS 是.

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

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

    Hello</a>

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

    it('应该在路由改变时添加active"',inject(function() {var elm = $compile( '<a href="/hello" when-active>Hello</a>' )( $scope );$location.path('/不匹配');期望( elm.hasClass('active') ).toBeFalsey();$location.path('/你好');期望( elm.hasClass('active') ).toBeTruthy();}));

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

    .directive( 'whenActive', function ( $location ) {返回 {范围:真实,链接:函数(范围、元素、属性){scope.$on('$routeChangeSuccess', function () {if ( $location.path() == element.attr( 'href' ) ) {element.addClass('活动');}别的 {element.removeClass('活动');}});}};});

    我们的测试现在通过了并且我们的菜单按要求执行.我们的开发是迭代测试驱动的.酷酷的.

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

    您经常会听到仅在指令中执行 DOM 操作".这是必要的.以应有的尊重对待它!

    但让我们深入一点...

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

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

    我看到许多刚接触 AngularJS 的开发人员使用指令作为抛出一堆 jQuery 的地方.换句话说,他们认为由于我无法在控制器中进行 DOM 操作,我会将这些代码放入指令中".虽然这当然要好得多,但通常仍然是错误的.

    想想我们在第 3 节中编写的记录器.即使我们将它放在指令中,我们仍然希望以Angular 方式"来实现.它仍然不需要任何 DOM 操作!有很多时候 DOM 操作是必要的,但它比您想象的很多罕见!在您的应用程序中任何地方进行 DOM 操作之前,先问问自己是否真的需要这样做.可能有更好的方法.

    这是一个简单的例子,展示了我最常看到的模式.我们想要一个可切换的按钮.(注意:这个例子有点做作,而且有点冗长,用来表示以完全相同的方式解决的更复杂的情况.)

    .directive( 'myDirective', function () {返回 {模板:'<a class="btn">切换我!</a>',链接:函数(范围、元素、属性){var on = false;$(element).click(函数(){上 = !上;$(element).toggleClass('active', on);});}};});

    这里有一些问题:

    1. 首先,jQuery 从来都不是必需的.我们在这里所做的一切都不需要 jQuery!
    2. 其次,即使我们的页面上已经有 jQuery,也没有理由在这里使用它;我们可以简单地使用 angular.element 并且我们的组件在放入一个没有 jQuery 的项目时仍然可以工作.
    3. 第三,即使假设该指令需要 jQuery ,jqLit​​e (angular.element) 将总是使用 jQuery,如果它是加载!所以我们不需要使用 $ - 我们可以使用 angular.element.
    4. 第四,与第三密切相关的是,jqLit​​e 元素不需要被包裹在 $ - 传递给 linkelementcode> 函数将已经是一个 jQuery 元素!
    5. 第五,我们在前面的部分中提到过,为什么我们要将模板内容混合到我们的逻辑中?

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

    .directive( 'myDirective', function () {返回 {范围:真实,模板:'<a class="btn" ng-class="{active: on}" ng-click="toggle()">切换我!</a>',链接:函数(范围、元素、属性){scope.on = false;scope.toggle = 函数 () {scope.on = !scope.on;};}};});

    同样,模板内容在模板中,因此您(或您的用户)可以轻松地将其替换为符合任何必要样式的模板,并且无需触及逻辑.可重用性 - 繁荣!

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

    w00t!

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

    换句话说,如果 AngularJS 没有做一些开箱即用的事情,想想团队将如何完成它以适应 ngClickngClass

    总结

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

    Suppose I'm familiar with developing client-side applications in jQuery, but now I'd like to start using AngularJS. Can you describe the paradigm shift that is necessary? Here are a few questions that might help you frame an answer:

    • How do I architect and design client-side web applications differently? What is the biggest difference?
    • What should I stop doing/using; What should I start doing/using instead?
    • Are there any server-side considerations/restrictions?

    I'm not looking for a detailed comparison between jQuery and AngularJS.

    解决方案

    1. Don't design your page, and then change it with DOM manipulations

    In jQuery, you design a page, and then you make it dynamic. This is because jQuery was designed for augmentation and has grown incredibly from that simple premise.

    But in AngularJS, you must start from the ground up with your architecture in mind. Instead of starting by thinking "I have this piece of the DOM and I want to make it do X", you have to start with what you want to accomplish, then go about designing your application, and then finally go about designing your view.

    2. Don't augment jQuery with AngularJS

    Similarly, don't start with the idea that jQuery does X, Y, and Z, so I'll just add AngularJS on top of that for models and controllers. This is really tempting when you're just starting out, which is why I always recommend that new AngularJS developers don't use jQuery at all, at least until they get used to doing things the "Angular Way".

    I've seen many developers here and on the mailing list create these elaborate solutions with jQuery plugins of 150 or 200 lines of code that they then glue into AngularJS with a collection of callbacks and $applys that are confusing and convoluted; but they eventually get it working! The problem is that in most cases that jQuery plugin could be rewritten in AngularJS in a fraction of the code, where suddenly everything becomes comprehensible and straightforward.

    The bottom line is this: when solutioning, first "think in AngularJS"; if you can't think of a solution, ask the community; if after all of that there is no easy solution, then feel free to reach for the jQuery. But don't let jQuery become a crutch or you'll never master AngularJS.

    3. Always think in terms of architecture

    First know that single-page applications are applications. They're not webpages. So we need to think like a server-side developer in addition to thinking like a client-side developer. We have to think about how to divide our application into individual, extensible, testable components.

    So then how do you do that? How do you "think in AngularJS"? Here are some general principles, contrasted with jQuery.

    The view is the "official record"

    In jQuery, we programmatically change the view. We could have a dropdown menu defined as a ul like so:

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

    In jQuery, in our application logic, we would activate it with something like:

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

    When we just look at the view, it's not immediately obvious that there is any functionality here. For small applications, that's fine. But for non-trivial applications, things quickly get confusing and hard to maintain.

    In AngularJS, though, the view is the official record of view-based functionality. Our ul declaration would look like this instead:

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

    These two do the same thing, but in the AngularJS version anyone looking at the template knows what's supposed to happen. Whenever a new member of the development team comes on board, she can look at this and then know that there is a directive called dropdownMenu operating on it; she doesn't need to intuit the right answer or sift through any code. The view told us what was supposed to happen. Much cleaner.

    Developers new to AngularJS often ask a question like: how do I find all links of a specific kind and add a directive onto them. The developer is always flabbergasted when we reply: you don't. But the reason you don't do that is that this is like half-jQuery, half-AngularJS, and no good. The problem here is that the developer is trying to "do jQuery" in the context of AngularJS. That's never going to work well. The view is the official record. Outside of a directive (more on this below), you never, ever, never change the DOM. And directives are applied in the view, so intent is clear.

    Remember: don't design, and then mark up. You must architect, and then design.

    Data binding

    This is by far one of the most awesome features of AngularJS and cuts out a lot of the need to do the kinds of DOM manipulations I mentioned in the previous section. AngularJS will automatically update your view so you don't have to! In jQuery, we respond to events and then update content. Something like:

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

    For a view that looks like this:

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

    Apart from mixing concerns, we also have the same problems of signifying intent that I mentioned before. But more importantly, we had to manually reference and update a DOM node. And if we want to delete a log entry, we have to code against the DOM for that too. How do we test the logic apart from the DOM? And what if we want to change the presentation?

    This a little messy and a trifle frail. But in AngularJS, we can do this:

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

    And our view can look like this:

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

    But for that matter, our view could look like this:

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

    And now instead of using an unordered list, we're using Bootstrap alert boxes. And we never had to change the controller code! But more importantly, no matter where or how the log gets updated, the view will change too. Automatically. Neat!

    Though I didn't show it here, the data binding is two-way. So those log messages could also be editable in the view just by doing this: <input ng-model="entry.msg" />. And there was much rejoicing.

    Distinct model layer

    In jQuery, the DOM is kind of like the model. But in AngularJS, we have a separate model layer that we can manage in any way we want, completely independently from the view. This helps for the above data binding, maintains separation of concerns, and introduces far greater testability. Other answers mentioned this point, so I'll just leave it at that.

    Separation of concerns

    And all of the above tie into this over-arching theme: keep your concerns separate. Your view acts as the official record of what is supposed to happen (for the most part); your model represents your data; you have a service layer to perform reusable tasks; you do DOM manipulation and augment your view with directives; and you glue it all together with controllers. This was also mentioned in other answers, and the only thing I would add pertains to testability, which I discuss in another section below.

    Dependency injection

    To help us out with separation of concerns is dependency injection (DI). If you come from a server-side language (from Java to PHP) you're probably familiar with this concept already, but if you're a client-side guy coming from jQuery, this concept can seem anything from silly to superfluous to hipster. But it's not. :-)

    From a broad perspective, DI means that you can declare components very freely and then from any other component, just ask for an instance of it and it will be granted. You don't have to know about loading order, or file locations, or anything like that. The power may not immediately be visible, but I'll provide just one (common) example: testing.

    Let's say in our application, we require a service that implements server-side storage through a REST API and, depending on application state, local storage as well. When running tests on our controllers, we don't want to have to communicate with the server - we're testing the controller, after all. We can just add a mock service of the same name as our original component, and the injector will ensure that our controller gets the fake one automatically - our controller doesn't and needn't know the difference.

    Speaking of testing...

    4. Test-driven development - always

    This is really part of section 3 on architecture, but it's so important that I'm putting it as its own top-level section.

    Out of all of the many jQuery plugins you've seen, used, or written, how many of them had an accompanying test suite? Not very many because jQuery isn't very amenable to that. But AngularJS is.

    In jQuery, the only way to test is often to create the component independently with a sample/demo page against which our tests can perform DOM manipulation. So then we have to develop a component separately and then integrate it into our application. How inconvenient! So much of the time, when developing with jQuery, we opt for iterative instead of test-driven development. And who could blame us?

    But because we have separation of concerns, we can do test-driven development iteratively in AngularJS! For example, let's say we want a super-simple directive to indicate in our menu what our current route is. We can declare what we want in the view of our application:

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

    Okay, now we can write a test for the non-existent when-active directive:

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

    And when we run our test, we can confirm that it fails. Only now should we create our directive:

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

    Our test now passes and our menu performs as requested. Our development is both iterative and test-driven. Wicked-cool.

    5. Conceptually, directives are not packaged jQuery

    You'll often hear "only do DOM manipulation in a directive". This is a necessity. Treat it with due deference!

    But let's dive a little deeper...

    Some directives just decorate what's already in the view (think ngClass) and therefore sometimes do DOM manipulation straight away and then are basically done. But if a directive is like a "widget" and has a template, it should also respect separation of concerns. That is, the template too should remain largely independent from its implementation in the link and controller functions.

    AngularJS comes with an entire set of tools to make this very easy; with ngClass we can dynamically update the class; ngModel allows two-way data binding; ngShow and ngHide programmatically show or hide an element; and many more - including the ones we write ourselves. In other words, we can do all kinds of awesomeness without DOM manipulation. The less DOM manipulation, the easier directives are to test, the easier they are to style, the easier they are to change in the future, and the more re-usable and distributable they are.

    I see lots of developers new to AngularJS using directives as the place to throw a bunch of jQuery. In other words, they think "since I can't do DOM manipulation in the controller, I'll take that code put it in a directive". While that certainly is much better, it's often still wrong.

    Think of the logger we programmed in section 3. Even if we put that in a directive, we still want to do it the "Angular Way". It still doesn't take any DOM manipulation! There are lots of times when DOM manipulation is necessary, but it's a lot rarer than you think! Before doing DOM manipulation anywhere in your application, ask yourself if you really need to. There might be a better way.

    Here's a quick example that shows the pattern I see most frequently. We want a toggleable button. (Note: this example is a little contrived and a skosh verbose to represent more complicated cases that are solved in exactly the same way.)

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

    There are a few things wrong with this:

    1. First, jQuery was never necessary. There's nothing we did here that needed jQuery at all!
    2. Second, even if we already have jQuery on our page, there's no reason to use it here; we can simply use angular.element and our component will still work when dropped into a project that doesn't have jQuery.
    3. Third, even assuming jQuery was required for this directive to work, jqLite (angular.element) will always use jQuery if it was loaded! So we needn't use the $ - we can just use angular.element.
    4. Fourth, closely related to the third, is that jqLite elements needn't be wrapped in $ - the element that is passed to the link function would already be a jQuery element!
    5. And fifth, which we've mentioned in previous sections, why are we mixing template stuff into our logic?

    This directive can be rewritten (even for very complicated cases!) much more simply like so:

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

    Again, the template stuff is in the template, so you (or your users) can easily swap it out for one that meets any style necessary, and the logic never had to be touched. Reusability - boom!

    And there are still all those other benefits, like testing - it's easy! No matter what's in the template, the directive's internal API is never touched, so refactoring is easy. You can change the template as much as you want without touching the directive. And no matter what you change, your tests still pass.

    w00t!

    So if directives aren't just collections of jQuery-like functions, what are they? Directives are actually extensions of HTML. If HTML doesn't do something you need it to do, you write a directive to do it for you, and then use it just as if it was part of HTML.

    Put another way, if AngularJS doesn't do something out of the box, think how the team would accomplish it to fit right in with ngClick, ngClass, et al.

    Summary

    Don't even use jQuery. Don't even include it. It will hold you back. And when you come to a problem that you think you know how to solve in jQuery already, before you reach for the $, try to think about how to do it within the confines the AngularJS. If you don't know, ask! 19 times out of 20, the best way to do it doesn't need jQuery and to try to solve it with jQuery results in more work for you.

    这篇关于《用 AngularJS 思考》如果我有 jQuery 背景?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-06 14:58