Angular JS best coding practice – Every coder should follow

From: http://www.codingeek.com/angularjs/angular-js-best-coding-practice-every-coder-should-follow/

1) Dependency Injection:

  1. Dependency injection is one of the best attribute of AngularJS framework and we should always use it. It will really help when we need to cover test cases of our application.
  2. Provide alias to dependency so that they will not rename during minification process, because in AngularJS dependencies are resolved by name.
1
2
3
4
5
6
angular.module(‘myApp’).controller('MyController', ['$scope''MyService',function($scope, MyService) {
    // controller logic
    }
   ]);

2) $Scope

  1. Treat scope as read only in templates i.e. even if AngularJS allows us to write code that modifies the scope in the templates, it is something that we must be very cautious about and probably shouldn’t do.
  2.  Treat scope as write only in controllers i.e. a controller is in charge of using another component, like a service, to get the data that the template will show and write this data in an object of the scope.
  • As a THUMB RULE, we must always have “.”  in the binding i.e. we should bind to an object in scope rather than a property directly, otherwise it can lead to unexpected behaviour in child $scope because $scope works on Java-script Prototypal inheritance.
    In below code we can see that superhero is an object on scope returned by Superhero service and same object used for binding in view.
1
2
3
4
5
<div class="form-group">
    <label class="control-label" for="name">Super Power</label>
       <div class="controls">
      <input type="text" data-ng-model="superhero.superPower">
</div>

1
2
3
$scope. superhero = Superheros.get({
    superheroId: $stateParams.superheroId
)};
  • The purpose of scope is to refer to model and not to be a model.
  • Model is our JavaScript object.

3) Validations

  1. Use attribute “novalidate” in form tag while using AngularJS validations to turn off HTML5 validations.
    1
    <form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewCtrl.addReview(product)" novalidate>
  2. We can use angular classes to change visibility and status of validations of controls.
    1
    2
    3
    4
    5
    6
    .ng-valid.ng-dirty{
        border-color: #FA787E;
    }
    .ng-invalid.ng-dirty{
        border-color: #FA787E;
    }

4) Memory – Task Management

  •  AngularJS broadcasts a $destroy event just before tearing down a scope and removing the scope from its parent. Listening for this event is crucial for cleaning up tasks and resources that otherwise might continue to chew up memory or CPU. Always register ‘destroy’ event to remove any memory leak prone code.
As an example, the following controller continuously updates a model value in one second intervals, and these updates will continue forever, even after the controller’s view is gone and the scope is removed from the parent. Even if the user will be navigating back and forth to a view that loads this controller, each navigation will add another timer that runs forever.
1
2
3
4
5
6
7
8
9
module.controller("MyController", function($scope, $timeout) {
    var onMyTimeout = function() {
        $scope.value += 1;
        $timeout(onMyTimeout, 100);
    };
    $timeout(onMyTimeout, 100);
    $scope.value = 0;
});
Listening for the $destroy event is an opportunity to halt the timer. One approach is to cancel the promise returned by $timeout.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.controller("TestController", function($scope, $timeout) {var onTimeout = function() {
    $scope.value += 1;
    timer = $timeout(onTimeout, 100);
};
    var timer = $timeout(onTimeout, 100);
    $scope.value = 0;
    $scope.$on("$destroy", function() {
        if (timer) {
            $timeout.cancel(timer);
        }
    });
});

5) Events@ $rootScope

  1. We should only use scope events to communicate across the controllers in the current screen of our Single Page Application. If we need to only share data, then we should look at using Services instead.
  2. When firing events, unless we need every single scope in our whole application to be notified about an event, we don’t need to fire an event on $rootScope. If we only need it for the children scopes, $broadcast the event on our own scope. Parent scopes $emit it on our scope. This will also short circuit the event propagation, instead of going through the entire top-to-bottom flow.
  3. Services have no other alternative but to listen for events on $rootScope to get notifications. This is because services are initialized once across our application, and don’t get their own scope and this will be fine.
  4.  Generally we should not register event listeners on the $rootScope other than a service. This is a general cause of bugs in the AngularJS applications. This is because when we add an event listener on the $scope of a controller and the controller is destroyed (we navigate away from the page, or close a section), the listeners also get destroyed. When we add it to the $rootScope and navigate away from a controller, the listener remains and keeps alive and triggering. So we have to manually deregister it from $rootScope, or be safe and just not add it on $rootScope. But if we have to add an event to rootScope, do not forget to clean it in controller’s scope.
    1
    2
    3
    4
    5
    6
    <strong> </strong>
    var myEventHandler = $rootScope.$on('MyEvent', ‘My Data’);
          $scope.$on('$destroy', function() {
          myEventHandler();
    });
  5. If we know that there is only one listener, and you have already encountered it, we can stop further propagation of the event by calling event.stopPropagation() on the event object passed to the event listener function.

6) Structuring Business Logic

  1. Controllers should not reference DOM but just contain behavior, Directives should have DOM manipulation.
  2. Services should have logic independent of view.
  3. Don’t fight with HTML just expand it through Directives.
  4. It is better to have modular folder structure, so that we can create reusable/ distributable components.

7) General Rules

  1. Use ng-src in place of src for images.
  2. Use promise for handling call-backs. AngularJS has exposed “$q” service for it. A number of AngularJS services return promises: $http, $interval, $timeout.
  3. Do not minify angular.min.js because as per AngularJS team they has minified angular files with predefined settings, which may break if we minify again. So just concatenate it.
  4. Use $templateCache to cache html templates, if template caching is required.
  5. Always wrap 3rd party API call-backs in to $apply to notify AngularJS regarding out of environment changes.
  6. If we don’t want user to show our HTML until AngularJS has loaded, use ng-cloak directive.
    1
    2
    3
    4
    5
    <div class="session ng-cloak">..............content............</div>
    .ng-cloak {
    /* this will change to block when scope and angular is ready */
    display:none;
    }
  7. Don’t use “ng” prefix for our directives to avoid any collisions. Create your custom one.Better to use <mycomponent> because <my:component> sometimes breaks on IE.
    1
    2
    <my-component>
    <my:component>
  8. Use $broadcast() , $emit() and $on() for events of  global relevance across the app (such as a user authenticating or the app closing). If we need events specific to modules, services or widgets we should opt for Services, Directive Controllers etc.
  9. Don’t use self-closing tag because some browsers don’t like them. Use “<product-title></product-title >” rather than “<product-title/>”.
Ref:http://blog.jobbole.com/80634/

评论

此博客中的热门博文

XML, XSL, HTML

Input in element.eleme.io

Data URI是由RFC 2397 ACE