If I have a jquery background, how do I switch to Angularjs's thinking mode?

Source: Internet
Author: User

Introduction

One of the people on StackOverflow asked a question: If I have a jquery background, how do I switch to Angularjs's thinking mode?

There was a very classic reply, which won more than 2000 votes.

In order to let the domestic developers can also appreciate the core ideas, now the question and the answer to the translation for your reference.

Question

Assuming I'm already familiar with using jquery to develop client applications, I'm now going to use ANGULARJS. Can you describe what is needed to change the mindset of those thinking patterns? Here are some specific questions to help you answer my question:

    1. How do I architect and design a client Web application in a different way? What is the biggest difference?
    2. What should I stop using, and what should I start to use instead?
    3. Is there anything in the server that needs to be considered or constrained?

PS: I don't want to compare the different points between jquery and Angularjs in detail.

Answer

1. Do not pre-design the page, and then use the DOM action to modify it

In jquery, you will first design the good one page and then make it dynamic. This is because jquery itself is designed using a mix of ideas. Based on this simple premise, jquery has become bloated at the moment.

But in a world of ANGULARJS, you must first have an overall architecture and then build your app from scratch. Instead of thinking at the beginning: "I've got this piece of DOM structure, I want it to be xxx", you have to think about what you want to do first, then start again, then design your app, and finally design your view.

2. Do not mix jquery with Angularjs

Similarly, don't start off with the idea that jquery can achieve x, y, and z, so I just need to overlay a layer of angularjs on it and add the model and controller. This is tempting when you start using Angularjs, which is why I always advise angularjs beginners to completely abandon jquery until they get used to doing things in "angular style".

Here, and in the mailing list, I've seen a lot of this well-designed solution that contains 150 or 200 lines of jquery plug-ins, and then they use a bunch of callbacks and $apply to glue these plugins to the ANGULARJS, It was a complex and confusing practice, but they finally managed to get the goods running! The problem here is that, in most cases, the jquery plugin can be rewritten with very little Angularjs code, and everything will suddenly become concise.

The bottom line is : In the process of solving the problem, first "Think in AngularJS" (think of the problem in the Anguarjs way); If you can't imagine a solution, turn to the community; If you can't find a simple solution after trying all of these methods, And then resort to jquery. But don't let jquery become a stumbling block, or you can never really master angularjs.

3. Maintain a structured approach to thinking

First, make it clear that a single page application is an application that is not a Web page. So, we need to think like a server developer, not as a client-side developer. We have to think about how we can cut our applications into separate, extensible, testable components.

So, how can you do that? How should you think about the problem in a angularjs way? Here are some basic principles to compare with jquery.

Suppose there is a view called "Official record" (official record)

In jquery, we'll modify the view programmatically, and we'll use the UL tag to define a drop-down list as follows:

<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, our application logic will create this drop-down list like this line of code:

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

If we just look at the view code, we can't immediately find out what it's capable of. This is possible for small applications. But for large applications, it can quickly become chaotic and difficult to maintain.

However, in Angularjs, a view is a feature that is based on the "official record" of the view. Our UL statement looks like this:

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

The two implementations are exactly the same, but in the Angularjs version, everyone who sees the template knows what it is doing. Whenever a new development team comes in, she sees the code and immediately understands that there is a directive called Dropdownmenu, which controls the view. She knows the answer intuitively, and there's no need to look at any code. The view itself has told us what will happen here. This makes it even clearer.

Angularjs Beginners often ask the question: How can I find all the hyperlinks of a certain type and add instructions to them? We will answer him this way: you should not do so. Then he was always a startled look. The reason you shouldn't do this is that this is a half-angularjs way of thinking, which is not scientific. Thinking about problems in this way can never get a good result. What you see is "Official Records". In addition to the instructions (including not just the following code), you should never, ever, ever modify the DOM. At the same time, instructions are used in the view , so the idea is clear.

Remember: Don't design first, then write a label. You have to structure and then design.

Data binding

So far, this is Angularjs's best feature, and using this feature eliminates the large number of DOM manipulation codes I mentioned in the previous section. Angularjs will automatically refresh the view for you, so you don't need to do it yourself! In jquery, we respond to events and then refresh the page content. Examples are as follows:

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

The corresponding view code is as follows:

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

In addition to mixing the points of attention in this way, there is the problem of thinking patterns that I mentioned earlier. But, more importantly, we have to manually reference and update the DOM node. Also, if we want to delete a log object, we must re-encode it for the DOM. So how do we get out of the DOM and test the logic? At the same time, what should we do if we want to modify the display effect?

This is a bit messy, the code is both trivial and fragile. But in Angularjs, we can do this:

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

Then our view code is this:

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

For the problem of deleting the log object mentioned above, we can write the view like this:

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

Here we replace the unordered list with the bootstrap alert block. And we never need to modify the controller code! And more importantly, the view automatically refreshes whenever or wherever the log object is updated . Noble Elegance!

Although I did not show here, in fact, the data binding operation is bidirectional. Therefore, you can also edit the log information in the view, as long as you do so: <input ng-model= "Entry.log"/>. There are also many more surprises.

Differentiate the data Model layer

In jquery, the DOM has the same meaning as the data model. But in Angularjs, we have a separate data model layer, and we can manage it according to our own ideas, which is completely independent of the view layer. This is useful for data-binding operations in the previous example, and maintains the principle of separation of considerations while also introducing stronger testing capabilities. This is mentioned in a lot of other answers, so I'm not going to go into it here.

Attention Point Separation

All of this is to achieve such a lofty goal: keep your points of attention separate. The role of your view is to show all the actions that "Official Records" can Do (most); Your data model is used to represent your data; you also have a service layer to perform reusable tasks; You perform DOM operations and mix instructions into the view; and finally you use the controller to put all Things to stick together. This is mentioned in many other responses, and the only thing I want to add is about the testing aspect, which I'll discuss in the next section.

Dependency Injection

The feature used to help us realize the separation of points of attention is dependency injection. If you're coming from a service-side language (for example, from Java or PHP), you're probably already familiar with the concept, but if you're a front-end guy, you might think that this concept is stupid, redundant, and very pushy if you turn around from jquery. But that is not the case.

At a large level, di means that you are free to declare a component, and then in other components you can request an instance of the declared component, and then you can get it. You don't need to know the loading order, the file path, and all that sort of stuff. The powerful energy of this concept may not be so obvious, here I only cite a (common) example: testing.

For example, in our application, depending on the state of the application, we need to request a server-side storage implementation through a REST API, as well as a local storage implementation. When we test our controller, we do not want to communicate with the server, after all we are testing the controller and not other things. We can just add a dummy service as the custom component mentioned earlier, and then the syringe will ensure that the controller can automatically get the virtual services, and our controller will not know what is the difference between them, and there is no need to know.

A little more about testing ...

4. Test-driven development---always

The content here is about architecture, which should actually belong to the third section, but this piece of content is extremely important, so I've made it a separate subsection.

How many of the jquery plugins you've seen, used, or written have a complete test case? Not many, because jquery is not a principle of too much bird. But Angularjs very much value this point.

In jquery, the only way to test is usually to create a separate component on a Sample/demo page where we can perform DOM operations related tests. So, we have to develop a component independently and then integrate it into our application. Good trouble! When you use jquery for development, it takes too much time, because we choose the way we iterate, not the way we choose test-driven development. So, who can blame us?

However, in Angularjs, because we have separated the points of attention, we can use iterative approach to test-driven development! For example, let's say we need a super-simple instruction to show what the current route is in the menu. We can declare what we need in a view like this:

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

OK, now let's write a unit test:

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

We run this unit test to verify that it will fail. Then we'll write the instructions:

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

Now our test runs through and the menu behaves as expected. In this way, our development is both iterative and test-driven . The bunker.

5. Conceptually, directives are not packaged jquery

You will often hear words like "manipulate the DOM only in instructions". This is a must . Please treat this principle with caution.

Let's go a little bit further ...

There are some instructions just to decorate the contents of the view that already exist (think of Ngclass), and sometimes do some DOM operations directly, then there is no then. However, a directive with a template, such as a widget, is also subject to the principle of separation of attention points. In other words, the template itself also needs to maintain a strong independence, independent of the link and controller functions of the specific implementation.

Angularjs has built-in complete tools to make this very easy, and we can use the Ngclass directive to dynamically update CSS style classes; Ngbind can be used to do two-way data binding; Ngshow and nghide can display or hide elements programmatically , and so much more. We can also import the instructions we have written ourselves. In other words, we can achieve a variety of brilliant effects without the need for DOM manipulation. The fewer DOM operations you perform, the easier it is to test the instructions, the easier it is to set the style, the easier it will be to modify in the future, and the better the reusability and distribution.

I've seen a lot of angularjs beginners take instructions as a place to accommodate a variety of jquery code. In other words, the idea is, "since I can't do DOM operations in the controller, I'll put the DOM operation-related code inside the instructions." This is a better practice, but it's usually wrong .

Think about the logger application we wrote in the third section. Even if we put the relevant operation into the instruction, we have implemented it in a "Angularjs way". It still does not do any DOM operation! Dom operations are necessary in many cases, but this is much less than you might think! Ask yourself if you really have to do this before you do DOM operations anywhere inside the app. There is a good chance that there is a better way to implement.

Here is a small example of a pattern that I often see. We need a switch-type button. (Note: The code for this example is a bit cumbersome, and a bit verbose, just to represent a more complex example, these examples are usually solved in 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 () {                if ( on ) {                    $(element).removeClass( ‘active‘ );                }                else {                    $(element).addClass( ‘active‘ );                }                on = !on;            });        }    };});

There are a lot of mistakes in this piece of code.

First, jquery is never a must. What we're going to do here actually doesn't need jquery! at all.

Second, even if we have introduced jquery on the page, there is no need to use it here, and for projects that do not use jquery, we can simply use angular.element, so that our components can also run well.

Thirdly, assuming that we have to use jquery in order to run, Jqlite (angular.element) will always use jquery automatically, if jquery has already loaded the words! So we don't need to use $, we just have to use angular.element.

IV, like the 3rd, the Jqlite element is not necessary to use $ for packaging, the element passed to the link function is already a jquery element!

and 5th, which we didn't mention in the previous section, is why we're mixing template-related content into our code logic?

The above instructions can be rewritten as follows (even for very complex situations!) ), after rewriting the code is extremely simple:

.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, template-related content is in templates, so you (or your users) can simply switch it to meet any necessary styling requirements and never need to modify the code logic . reusability---BAM!

This will bring other benefits, such as testing---this is necessary! No matter what is inside the template, the API inside the directive never needs to be modified, so refactoring is easy. You can modify the contents of the template at will without the need to ignore the instructions. And no matter what you modify, your test will still run through.

w00t!

Well, if the instructions are not a collection of jquery functions, what are they? The instruction is actually an HTML extension . If HTML can't do something you want to do, write a directive yourself and then use that instruction as if it were part of the HTML.

In other words, if Angularjs doesn't have built-in support for something, think about how your team should implement it, referring to instructions such as Ngclick,ngclass.

Summary

Do not use jquery. It is best not to introduce it. It will only drag your hind legs. When you encounter a problem that you know how to use jquery to solve, before you use $, think about how to solve it in a angularjs way. If you don't know, ask someone! The best way to solve this is not to use jquery, and if you work with jquery, you'll end up with more work.

Original link: http://damoqiongqiu.iteye.com/blog/1926475

If I have a jquery background, how do I switch to Angularjs's thinking mode?

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.