Guide to angular programming style (II)

Time:2021-8-16

A good programming style is conducive to the collaborative development of the team, so we also have some agreements when developing angular. This article is mainly aimed at the teams using angular and coffee script( This is a rough translation. The link of the original text is under the article. Interested students can see it.)

Angular Programming Guide

service

Single case

Service is throughnewKeyword is used for instantiationthisTo define and invoke common methods and variables, which is very similar to factory services. For unification, factory services can be used

[note]: all angular services are in singleton mode, which means that there is only one instance for each service injection

// service
angular
    .module('app')
    .service('logger', logger);

function logger() {
  this.logError = function(msg) {
    /* */
  };
}

// factory
angular
    .module('app')
    .factory('logger', logger);

function logger() {
    return {
        logError: function(msg) {
          /* */
        }
   };
}

Factory Services

Single responsibility

Factory services should also beSingle responsibility, when a service wants to achieve more than one purpose, it is necessary to redefine a factory service

Single case

Factory service is a singleton service, and the returned object includes the member object of the service

[note] all angular services are single instances

Callable member first

Promote the callable members (exposed interfaces) of the server to the front of the server (derived from learning JavaScript Design Patterns)

  • Putting callable variable members at the front of the service can provide you with code readability and let you see at a glance which member variables of the service are callable and testable

  • This is necessary when the file becomes longer. You don’t have to scroll to the bottom of the file to see what interfaces are exposed by the service

  • When your function exceeds one line of code, it will reduce the readability of your code and cause redundant scrolling operations when reading. Therefore, you should promote the definition of the callable interface and the return of the service to the top definition of the file and put the implementation details under the file to increase the readability of the code

###Not recommended###
    (->
      dataService = ()->
    
        someValue = ''
    
        save = ()->
          # ... #
    
        validate = ()->
          # ... #
    
        return
          save: save,
          someValue: someValue,
          validate: validate
    
      angular
        .module('app')
        .service('dataService', dataService)
    )()
    
    ###Recommendation method###
    (->
      dataService = ()->
    
        someValue = ''
    
        ##########
    
        return
          save: ()->
           # . #
    
          validate: ()->
           # . #
      angular
        .module('app')
        .service('dataService', dataService)
    )()

The data bound by this method is the mapping of the host object, and the single original data exposed through the module pattern cannot be updated alone

###Not recommended###
    angular
      .module('app.widgets')
    
      # order directive that is specific to the order module
      .directive('orderCalendarRange', orderCalendarRange)
    
      # sales directive that can be used anywhere across the sales app
      .directive('salesCustomerInfo', salesCustomerInfo)
    
      # spinner directive that can be used anywhere across apps
      .directive('sharedSpinner', sharedSpinner)
    
      ### implementation details ###
      
      
      
    ###Recommendation method###
    
     ###
     # @desc order directive that is specific to the order module at a company named Acme
     # @file calendarRange.directive.js
     # @example <div acme-order-calendar-range></div>
     ###
    angular
      .module('sales.order')
      .directive('acmeOrderCalendarRange', orderCalendarRange)
    
     ###
     # @desc spinner directive that can be used anywhere across the sales app at a company named Acme
     # @file customerInfo.directive.js
     # @example <div acme-sales-customer-info></div>
     ###
    angular
      .module('sales.widgets')
      .directive('acmeSalesCustomerInfo', salesCustomerInfo)
    
     ###
     # @desc spinner directive that can be used anywhere across apps at a company named Acme
     # @file spinner.directive.js
     # @example <div acme-shared-spinner></div>
     ###
    angular
      .module('shared.widgets')
      .directive('acmeSharedSpinner', sharedSpinner)
    
      ### implementation details ###

instructions

One instruction is one file. It’s easy to mix all the instructions into one file, but it’s not so easy to separate these instructions from this file later. Therefore, those instructions that need to be shared in the app and modules must be separated into a file, which is also conducive to code maintenance

###Not recommended###
    angular
      .module('app.widgets')
    
      # order directive that is specific to the order module
      .directive('orderCalendarRange', orderCalendarRange)
    
      # sales directive that can be used anywhere across the sales app
      .directive('salesCustomerInfo', salesCustomerInfo)
    
      # spinner directive that can be used anywhere across apps
      .directive('sharedSpinner', sharedSpinner)
    
      ### implementation details ###
      
      
      
    ###Recommendation method###
    
     ###
     # @desc order directive that is specific to the order module at a company named Acme
     # @file calendarRange.directive.js
     # @example <div acme-order-calendar-range></div>
     ###
    angular
      .module('sales.order')
      .directive('acmeOrderCalendarRange', orderCalendarRange)
    
     ###
     # @desc spinner directive that can be used anywhere across the sales app at a company named Acme
     # @file customerInfo.directive.js
     # @example <div acme-sales-customer-info></div>
     ###
    angular
      .module('sales.widgets')
      .directive('acmeSalesCustomerInfo', salesCustomerInfo)
    
     ###
     # @desc spinner directive that can be used anywhere across apps at a company named Acme
     # @file spinner.directive.js
     # @example <div acme-shared-spinner></div>
     ###
    angular
      .module('shared.widgets')
      .directive('acmeSharedSpinner', sharedSpinner)
    
      ### implementation details ###

Restrict DOM operations

Restrict the operation of DOM and use instructions to directly operate dom. If there are alternative ways, such as using CSS to set styles, using animation services, angular templates, ngshow or nghide, use these instead of instructions. For example, if the instruction is to define a simple display and hiding, nghide and ngshow are used to replace it for a long time. However, if the instruction needs to deal with more complex things besides display and hiding, the display and hiding and other operations that need to be implemented are encapsulated in this instruction, which can reduce the monitoring of angular and improve the performance of the application.

  • It is not easy to test and debug the DOM operation. We have a better method, provided that the DOM operation is relatively simple (CSS, animations, templating)

Restrict elements and attributes

Restrict elements and attributes: when creating an instruction, if the instruction behaves like an element, then restrict can be set to e or A. if the instruction can have its own controller, it is ideal to set restrict to E. however, generally, some bootstrappers set restrict to ea, However, when instructions are encapsulated in a separate scope, they tend to represent element instructions

, when enhancing existing DOM elements, it tends to attribute representation

  • It makes sense

  • If the instructions tend to behave like elements or attributes, this allows the instructions we define to use the class attribute

    <!-- Not recommended -- >
       <div class="my-calendar-range"></div>
       ### avoid ###
       (->
         myCalendarRange = ()->
             link = (scope, element, attrs)->
               # ... #
       
             directive =
               link: link,
               templateUrl: '/template/is/located/here.html',
               restrict: 'C'
       
             return directive
       
         angular
             .module('app.widgets')
             .directive('myCalendarRange', myCalendarRange)
       )()
       <!-- recommended -->
       <my-calendar-range></my-calendar-range>
       <div my-calendar-range></div>
       
       
       ###Recommendation method###
       (->
       
         myCalendarRange = ()->
       
             link = (scope, element, attrs)->
               # ... #
       
             directive =
                 link: link,
                 templateUrl: '/template/is/located/here.html',
                 restrict: 'EA'
       
             return directive
       
         angular
             .module('app.widgets')
             .directive('myCalendarRange', myCalendarRange)
       )()