Click here to Skip to main content
15,891,136 members
Articles / Programming Languages / Javascript

AngularJS use summary

Rate me:
Please Sign up or sign in to vote.
3.60/5 (7 votes)
28 Jan 2016CPOL4 min read 15.4K   7   4
My understanding about AngularJS

Introduction

Introduce some bacis and important knowledge of AngularJs.

Background

I have used AngularJS for a while, I use it because our customer demanded us to use that technology in our project. From totally blank to have some understanding about AngularJs, I think it's necessary to write something about my understanding to AngularJS. 

1.Two-way data binding

There are many different kinds of MV** frameworks that are very popular, and AngularJS is one of them (MVVM). 

The most important thing for MV** framework is that they can separate View layer and Model layer, decouple your code. MVC, MVP, MVVM all have the same objective and the difference between them is how to associate the model layer with the view layer.

How the data flow between model layer and view layer is the key problem. The two-way data binding is that the change on view can reflect on the model layer and vice versa. So how the AngularJS does the two-way binding and how it becomes dirty-check ? let's start from a front-end question:

C++
html:
<input type="button" value="increase 1" id="J-increase" />
<span id="J-count"></span>

js:
<script>
    var bindDate = {
        count: 1,
        appy: function () {
            document.querySelector('#J-count').innerHTML = this.count;
        },
        increase: function () {
            var _this = this;
            document.querySelector('#J-increase').addEventListener('click', function () {
                _this.count++;
                appy();
            }, true);
        },
        initialize: function () {            
            this.appy();            
            this.increase();
        }
    };
    bindDate.initialize();
</script>

As above example, there are two processes:
a. view layer affects model layer: click button on page would increase the count number.
b. model layer reflects view layer: after the 'count' changed, it would represent on view via 'apply' function.

This is the way when we use jQuery or other libraries, there are three obvious defects:
a. It involves too many DOM operations.
b. The process is complicated.
c. Code coupling is too high, not easy to write unit tests.

Let's see how AngularJS deal with data:

Step 1, add Watcher:  when the data changes definition which object needs to be check, need to register first. 

C++
$watch: function(watchExp, listener, objectEquality) {
    var scope = this,
        array = scope.$$watchers,
        watcher = {
            fn: listener,
            last: initWatchVal,
            get: get,
            exp: watchExp,
            eq: !!objectEquality
        };
    if (!array) {
        array = scope.$$watchers = [];
    }
    array.unshift(watcher);
}

Step 2, dirty-check: when the data under a specified scope changed, need to loop the registered $$watchers = [...]

C++
 $digest: function() {
     while (length--) {
         watch = watchers[length];
         watch.fn(value, lastValue, scope);
     }
 }

this implemented the two-way data binding, you can see that similar to a customize event and that used observer design pattern or publisher-subscriber.

2.Dependency Injection

Let's see if we don't use DI (Dependency Injection) how to solve the interdependence between objects.

C++
function Car() {
    ...
}
Car.prototype = {
    run: function () {...}
}
 
function Benz() {
    var cat = new Car();
}
Benz.prototype = {
    ...
}

As above, class Benz dependents on class Car, it solves the dependence relationship by using an internal New. It's obviously not good to do like that, the code coupling is high and not beneficial for maintenance.
We know javascript language doesn't have annotation mechanism, let's see how AngularJS achieve it.

Step 1, Analog comment

C++
function annotate(fn, strictDi, name) {
    var $inject;
    if (!($inject = fn.$inject)) {
        $inject = [];
        $inject.push(name);
    }else if (isArray(fn)) {
        $inject = fn.slice(0, last);
    }
    return $inject;
}
createInjector.$$annotate = annotate;

Step 2, Create injection object

C++
function createInjector(modulesToLoad, strictDi) {
    var providerCache = {
        $provide: {
            provider: supportObject(provider),
            factory: supportObject(factory),
            service: supportObject(service),
            value: supportObject(value),
            constant: supportObject(constant),
            decorator: decorator
          }
      },
    instanceCache = {},
    instanceInjector = (instanceCache.$injector =
        createInternalInjector(instanceCache, function(serviceName, caller) {
            var provider = providerInjector.get(serviceName + providerSuffix, caller);
            return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
        }));
    return instanceInjector;
}

Step 3, Get inject object

C++
function invoke(fn, self, locals, serviceName) {
    var args = [],
        $inject = annotate(fn, strictDi, serviceName);
 
    for (...) {
        key = $inject[i];        
        args.push(
          locals && locals.hasOwnProperty(key)
          ? locals[key]
          : getService(key, serviceName)
        );
    }
    if (isArray(fn)) {
        fn = fn[length];
    }      
    return fn.apply(self, args);
}

so if there is no anotation then simulate one, that why PPK said angular is  "a front-end framework by non-front-enders for non-front-enders".

3.Controller communication

In the real development work, the app system will become very big, one app could not have only one controller, how to deal with the communication between different controllers ? There are two main ways:

1.Event mechanism: register event on $rootScope, in this way it will register too many events on the $rootScope and that will cause a lot of problems.

C++
//controller1
app.controller('controller1', function ($rootScope) {
    $rootScope.$on('eventType', function (arg) {
        ......
    })
})
 
// controller2
app.controller('controller2', function ($rootScope) {
    $rootScope.$emit('eventType',arg);
    or
    $rootScope.$broadcast('eventType',arg);
})

2. Use service: make full use of angular characteristics of DI, use angular service is a singleton feature, it will play a role as a bridge between different controller.

C++
// register service
app.service('Message', function () {
    return {
        count: void(0);
    }
})
 
// controller1
app.controller('controller1', function ($scope, Message) {
    $scope.count = 1;
    Message.count = $scope.count;
});
 
// controller2
app.controller('controller2', function ($scope, Message) {
    $scope.num = Message.count;
});

4.Service features

1. Singleton: In AngularJS only service can do dependency injection, something like controller, directive etc don't have this feature, angular service only provide some basic services, it wouldn't associated with specific business, but controller, directive all closely associated with the specific business, so we need to keep the service unique.

2. Lazy new: angular will generate the provider of service first, but it did not generate the corresponding service instantly, it will be instantiated only when we need to use it. 

3. The category of provider: provider(), factory, service, value, constant. Which provider is the underlying implementation, other ways are base on it. Note that all these services all need to add $get method eventually, because all the specific  service is generated by executing the $get method.

5.The implementation of directive

Directive's compiler has two phases: compile, link. In short, the compiler phase mainly handle template DOM, In this phase it does not involve scope problems, i.e. no data rendering. For example, ng-Repeat directive just using compile to modify template, after executed compile it will return link function override the following link functions; in the other hand, the link is mainly responsible for data rendering, it divides into two steps.  The compile order of these two steps is reversed, post-link will compile the internal then external. This is safe for directie compile, because directive can embed directive, in the meanwhile link will handle the real DOM, that will involve DOM operation performance issue.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionNot clear enough Pin
hamid_m31-Jan-16 18:25
hamid_m31-Jan-16 18:25 
QuestionHave you consider to post this as a tip? Pin
Nelek27-Jan-16 23:12
protectorNelek27-Jan-16 23:12 
QuestionBackground for understading Pin
Member 816573027-Jan-16 5:34
Member 816573027-Jan-16 5:34 
BugImage(s) not displaying Pin
Slacker00727-Jan-16 2:04
professionalSlacker00727-Jan-16 2:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.