JSDuck and AngularJS integration skills

 

Word count: 1568

Reading time: 10 minutes

 

 

foreword

Earlier, we explained in detail how to use the JSDuck tool in actual development with a practical case. However, not all of the time, the way the code is encapsulated is under our control. For example, if we use the current mainstream frameworks AngularJS, React or Vue, the way the code is encapsulated must be constructed in the way defined by the framework. When there are modules, controllers, services, directives and other components in our code that JSDuck does not know at all, how can we use JSDuck to describe our code correctly?

So, below, I will take AngularJS as an example to talk about my own solution.

 

 

Fusion of ideas

There are two ways to solve this problem. First, you can map parts of code that JSDuck doesn't recognize to tags recognized by the tool to describe them. Second, since there are no ready-made tags to describe these new members, we can customize a set of tags to describe them.

The first method is more convenient and requires no additional coding; the second method is more elegant, but requires a custom set of tags.

Here, because the author's requirements for the document are mainly practical, it does not need to be so perfect, and there is not too much energy to develop a complete set of labels. Therefore, the author chose the first solution.

The core of the first solution is to determine which new members the AngularJS framework brings to our code, and then how to map these new members to the original tags.

AngularJS brings us the following new members: Modules, Services, Directives, Filters and Controllers. Then the mapping relationship is as follows:

new member Mapped JSDuck tags
module Module class (@class)
Serve Service class (@class)
instruction Functions in module classes (@method)
filter Functions in module classes (@method)
controller Controller class (@class)

Among them, a module is a special class, I call it a module class, which is distinguished from other classes by namespace and class name. For example, NgModule.layout is one of my module classes, and the namespace NgModule is a namespace dedicated to storing module classes.

Service is another special class, I call it service class, service class and module class are related by namespace, and the name of service class is special, which starts with "$" symbol. For example, NgModule.layout.$layoutTag is one of my service classes whose namespace is the module class it belongs to.

Directives and filters are relatively simple, they are all functions in the module class to which they belong.

The controller is also a special class, I call it the controller class, and its namespace is the module class to which it belongs. It is distinguished from other classes by the name of the class, which ends with "Ctrl". For example: NgModule.frame3.frameCtrl is one of my controller classes. Here, the parent-child controller is directly represented by the parent class and child class.

The overall idea is like this, then, let's talk directly on the code!

 

 

Example

As shown below, it is part of the code of one of our module classes (for the convenience of viewing, only comments are left, and the specific implementation is deleted):

/**
     * Page general widget module
     * @class NgModule.layout
     * @alias gm.ngCustom.layout
     * @author lsjcoder
     */
    angular.module("gm.ngCustom.layout",[]).provider("$layoutTag",
    /**
     * Service representing the label of the query item
     * @class NgModule.layout.$layoutTag
     * @alias $layoutTag
     * @author lsjcoder
     */
    function() {
        this.$get = [function () {
            function factory() {
                var $ layout = {};
                /**
                 * @member NgModule.layout.$layoutTag
                 * @method getCheckedTags Get checked tags
                 * @param {Array} tags collection of tags
                 * @returns {Array} collection of selected tags
                 */
                $layout.getCheckedTags = function(tags){
                };
                /**
                 * @member NgModule.layout.$layoutTag
                 * @method clearCheck clears the selection
                 * @param {Array} tags collection of tags
                 */
                $layout.clearCheck = function(tags){
                };
                return $layout;
            }
            return factory;
        }];
    }).directive("gmTags",["$layoutTag",
    /**
     * @member NgModule.layout
     * @method gmTags tag directive, EAC mode
     * @param {Number} [max-tag-num] DOM attribute value, the maximum number of tags displayed externally, it will be automatically calculated according to the page width by default
     * @param {Boolean} [multi = true] DOM attribute value, whether to enable multi-selection mode
     * @param {Object} tagdata is used to pass values, command configuration items
     * @param {String} tagdata.checkTag The name of the function to call after the tag is selected
     * @param {Array} tagdata.tags tag data
     */
    function($layoutTag){
        //Query the label instruction in the form
        return {
            restrict: "ECA",
            templateUrl: "tag.tpl.html",
            replace: true,
            scope: {
                tagdata: "="
            },
            link: function (scope, element, attr, transclution) {
            }
        }
    }]).directive("dateChoose",
    /**
     * @member NgModule.layout
     * @method dateChoose date command, EAC mode
     */
    function(){
        return {
            restrict:"EAC",
            link :function(scope,element,attr,transclution){
            }
        }
    }).directive("timeChoose",
    /**
     * @member NgModule.layout
     * @method timeChoose time command, EAC mode
     */
    function(){
        return {
            restrict:"EAC",
            link :function(scope,element,attr,transclution){
              
            }
        }
    });

The code is already very clear, this code contains the module and the annotation method of the services and instructions in the module. The filter is the same as the instruction, so I won't go into details.

 

 

Next, let's take a look at how the controller is annotated:

/**
     * @class NgModule.frame3 frame3模块
     * @alias frame3
     * @author lsjcoder
     */
    var frameApp = angular.module("frameApp",[]);
    /**
     * @class NgModule.frame3.frameCtrl frame controller
     * @extends NgModule.frame.frameCtrl
     * @author lsjcoder
     */
    frameApp.controller("frameCtrl",["$scope",function($scope){
       /**
         * @member NgModule.frame3.frameCtrl
         * @method refreshPage refresh the routing page
         * @param {String} strPath routing address
         * @author lsjcoder
         */
        $scope.refreshPage = function(strPath){
           
        };
    }]);

As shown in the above code, I declare a controller NgModule.frame3.frameCtrl, which belongs to the module NgModule.frame3, the parent controller is NgModule.frame.frameCtrl, and there is a function member refreshPage inside.

 

 

At this point, we can describe all the new parts of the code that use the AngularJS framework in this way. Other frameworks can also be handled in the same way. This processing method is a compromise solution. If you want to be more standardized and elegant, it is recommended to use custom tags to solve it.

 

 

 

Welcome everyone to pay attention to my WeChat public account, and code with the old driver:

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324386715&siteId=291194637