Angular JS best coding practice – Every coder should follow
From: http://www.codingeek.com/angularjs/angular-js-best-coding-practice-every-coder-should-follow/
Listening for the $destroy event is an opportunity to halt the timer. One approach is to cancel the promise returned by $timeout.
1) Dependency Injection:
- 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.
- 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
- 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.
- 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
- 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>
- We can use angular classes to change visibility and status of validations of controls.123456
.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.
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; }); |
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
- 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.
- 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. - 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.
- 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.
123456<strong> </strong>
var
myEventHandler = $rootScope.$on(
'MyEvent'
, ‘My Data’);
$scope.$on(
'$destroy'
,
function
() {
myEventHandler();
});
- 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
- Controllers should not reference DOM but just contain behavior, Directives should have DOM manipulation.
- Services should have logic independent of view.
- Don’t fight with HTML just expand it through Directives.
- It is better to have modular folder structure, so that we can create reusable/ distributable components.
7) General Rules
- Use
ng-src
in place ofsrc
for images. - Use promise for handling call-backs. AngularJS has exposed “$q” service for it. A number of AngularJS services return promises: $http, $interval, $timeout.
- 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.
- Use
$templateCache
to cache html templates, if template caching is required. - Always wrap 3rd party API call-backs in to $apply to notify AngularJS regarding out of environment changes.
- If we don’t want user to show our HTML until AngularJS has loaded, use
ng-cloak
directive.12345<div
class
=
"session ng-cloak"
>..............content............</div>
.ng-cloak {
/* this will change to block when scope and angular is ready */
display:none;
}
- Don’t use “ng” prefix for our directives to avoid any collisions. Create your custom one.Better to use <my–component> because <my:component> sometimes breaks on IE.12
<my-component>
<my:component>
- 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.
- Don’t use self-closing tag because some browsers don’t like them. Use “<product-title></product-title >” rather than “<product-title/>”.
评论
发表评论