What about Arcgis Javascript (12) -- AMD in dojo uses class

Keywords: JQuery REST Programming Attribute

This blog is reprinted from Click Open Link

1. introduction

When it comes to object-oriented, we have to mention classes. In native js, we can't create classes without the keyword class, but in dojo, Dojo customizes a module called dojo/_base/declare, with which we can create our own classes and implement object-oriented programming. In this blog, we'll learn how to use dojo/_base/declare to create classes in our applications.

2. Classes in Dojo

First, let's look at the dojo/_base/declare declaration:

declare(classname,[],{})
  • 1
  • 1
  • The first parameter of declare is optional, representing the name of the class.
  • The second parameter of declare represents the inheritance relationship of a class, such as which parent class to inherit. You can see that the second parameter is an array, so dojo can inherit more.
  • The third parameter is an object, representing the subject of the class.

2.1 Create a simple class

After class inheritance, we create a very simple class:

var Person=declare("namespace.Person", null, {
    name:null,
    age:null,
    constructor: function(name,age){
            this.name=name;
            this.age=age;
        }

});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • The above code establishes a Person class, without a parent class, and the constructor is constructor.
  • How do we create an instance of the Person class? Code: var p=new Person("wpx",20)

The above method is a very simple class, but there is a problem. If there are many attributes of the class, there will be many parameters in our constructor. Is there a solution? The answer is yes. Now look at the modified code.

var Person=declare("namespace.Person", null, {
    name:null,
    age:null,
    constructor: function(args){
            declare.safeMixin(this,args);
        }

});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

So what should we do when we create instances of classes? Code:

var p=new Person({
    name:"wpx",
    age:20
})
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

At this point, a friend may ask, what is the role of class names? Class names can be used as global references to classes, such as the Person class above, which can also define instances as follows:

var p=new namespace.Person({
    name:"wpx",
    age:20
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

2.2 Class and Module Combination

Most people who have learnt backstage languages are used to: one class, one file. That's good for us about our js code, so how do we implement it in dojo? The code is as follows:

  • person.js
define(["dojo/_base/declare"],function(declare){
    return declare("namespace.Person",null,{
        name:null,
        age:null,
        constructor: function(args){
            declare.safeMixin(this,args);
        },
        toString:function(){
            return this.name+":"+this.age
        }
    })
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • Call our custom class
require(["js/person"], function(Person) {
            var p=new Person({
                name:"wpx",
                age:20
            });
            alert(p.toString())
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Assuming our class name is namespace.Person, we can also refer to it in this way (note the difference from above), that is, the global reference:

require(["js/person"], function() {
            var p=new namespace.Person({
                name:"wpx",
                age:20
            });
            alert(p.toString())
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • Operation result

2.3 On Class Inheritance

How to use inheritance of classes is not much discussed here. If you want to know more about advanced use of classes, please check the official website:
dojo Creates Classes

3. demand

The above is just a brief introduction to how to use classes when creating classes. Now let's talk about the use of classes from the aspect of requirements.

3.1 demand 1

Suppose we have a new project, and then the project manager says, "Xiao Wang, now I want to implement a function, provide a coordinate of a point, and add an icon to the map. You just need to give me an interface. I don't care how to implement it. So how do we achieve it now?  
Idea: Create a module, and then there is a class in the module. The class has a method. The method can add dot graphics to the map. Yes, but some of the students said, so how do map objects come? The answer is: Can we pass in through constructors?

  • code implementation
define(["esri/graphic","esri/symbols/SimpleMarkerSymbol",
    "esri/symbols/SimpleLineSymbol","dojo/colors",
    "esri/layers/GraphicsLayer",
    "dojo/_base/declare"],
    function (Graphic,SimpleMarkerSymbol,SimpleLineSymbol,Color,GraphicsLayer,declare){
    return declare(null,{
        map:null,//Define map objects, passed in from outside
        constructor: function(args){
            declare.safeMixin(this,args);
        },
        //Provide methods for adding points
        addPoint:function(point){
            var lineSymbol=new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,new Color([255, 0, 0]), 2)
            var pSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CROSS, 100,lineSymbol, new Color([0, 255, 0, 0.25]));
            var g=new Graphic(point,pSymbol);
            var layer=new GraphicsLayer();
            layer.add(g)
            this.map.addLayer(layer);

        }
    })
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • Main page:
require(["esri/map","esri/layers/ArcGISDynamicMapServiceLayer","esri/geometry/Point","js/MyUtil","dojo/domReady!"],
                function(Map,ArcGISDynamicMapServiceLayer,Point,MyUtil) {
                    var map=new Map("mapDiv")
                    var p=new Point(
                            {
                                x:"-107.13700471124938",
                                y:"41.54667348528646",
                                spatialReference:{
                                    wkid:"4326"
                                }
                            })
                    var layer=new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer");
                    map.addLayer(layer);
                    var util=new MyUtil({
                        map:map
                    });
                    util.addPoint(p);

        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

3.2 Demand 2 (Important)

We have achieved the first requirement, but suddenly one day the project manager asked you to say: Xiaowang, our requirement has changed, the last function may have to be changed, I do not provide a point, I want to interactive graphics. But, instead of adding my drawing to the map, I want to return it to me.

3.2.1 Code Implementation

At this point, you'll think, it's not easy. We directly draw the image, and then get the geometric shape of the drawing. Just return it directly. Our thinking is as follows:
* Create a module
* There is a getPoint method in the module, which calls the getPoint method to get the coordinates of the points.

But the problem arises. Let's look at our code first.

        getPoint:function()
        {
            on(this.toobar,"draw-complete",this.showResult);
        },
        showResult:function(result){
            var geometry=result.geometry;
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Looking at the code, we found the problem: we called the getPoint method, but the geometry was obtained in the showResult method, and we could not return at all, so we were wrong at first.

If there is a problem, then we should solve it. How should we return our data? The answer is to use the callback method. We provide an interface to the outside world in the class, which is a function through which our data can be returned. So that's how we did it.

define(["dojo/on","dojo/_base/declare","esri/toolbars/draw"],function(on,declare,Draw){
    return declare("mydraw",[],{
        map:null,//Current Map Object
        toobar:null,
        callback:null,//Used for callback and data transfer
        constructor:function(args)
        {
            declare.safeMixin(this,args);
        },
        init:function()
        {
            this.toobar = new Draw(this.map, { showTooltips: true });
            this.toobar.activate(Draw.POINT);
        },
        getPoint:function(callback)
        {
            this.init();
            this.callback=callback;
            on(this.toobar,"draw-complete",this.showResult);
        },
        showResult:function(result){
            this.callback(result.geometry);
        }

    })
});

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • We call
require(["esri/map","dojo/dom","esri/layers/ArcGISDynamicMapServiceLayer","js/mydraw","dojo/domReady!"],
                function(Map,dom,ArcGISDynamicMapServiceLayer,MyDraw) {
                    var map=new Map("mapDiv")
                    var layer=new ArcGISDynamicMapServiceLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer");
                    map.addLayer(layer);

                    dom.byId("btn").onclick=function(){
                        var my=new MyDraw({
                            map:map
                        });
                        my.getPoint(function(g)
                        {
                            alert(g)
                        })
                    }

        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.2.2 Program Error

Here comes the problem again. Our ideas are all right, but when it runs, the program is wrong.

Carefully troubleshooting, we found that this has no callback attribute

Then we wondered, what went wrong? We clearly defined callback, and went on to find something more interesting.

        getPoint:function(callback)
        {
            this.init();
            this.callback=callback;
            //Here this is our mydraw class
            on(this.toobar,"draw-complete",this.showResult);
        },
        showResult:function(result){
            //Here the direction of this has changed, so you can debug it.
            this.callback(result.geometry);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

I don't know if you remember that this keyword is very flexible in js. We know that the use of this in classes is inevitable and the frequency of use will be very high. We also said that we can control the direction of this when calling functions. In dojo, we provide a module called dojo/_base/lang. With this module, we can control the direction of this. How should I use it? To correct this error, you only need to modify one place.

         getPoint:function(callback)
        {
            this.init();
            this.callback=callback;
            //Here this is our mydraw class
            on(this.toobar,"draw-complete",lang.hitch(this,this.showResult));
        },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Note: When I use on binding events, I control the direction of this. This is our mydraw class in the getPoint function, so when I call the showResult function, I can control this as mydraw.

3.2.3 Program Running

At last, we succeeded in running the program.

3.3 Demand 3

Needs 3 is very simple. Some students may use dojo when they use it. jQuery Middle class libraries (actually unnecessary, dojo is already powerful), so what should we do? How do we use jquery in our own modules? The code is as follows

define(["dojo/_base/declare"],function(declare){
    return declare(null,{
        $:null,
        constructor: function(args){
            declare.safeMixin(this,args);
        }
    })
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

When using our class (assuming our Person):

var p=new Person({
$:$
});
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

The idea is to pass our global $to our custom module.

4. Introduce require loading module again

First, let's look at the order in which we load:

  • First: If we have custom modules, configure the path of our custom modules through dojoConfig
  • Second: Load init's js file (be careful to load it in dojoConfig)
  • Third: require is loaded in sequence. For example, if my require first loads dijit/registry, then a variable is written in the following function to represent the dijit/registry module. At this time, the name of the variable does not matter, but only represents the module. But note: the first place in the graph represents a js file, and the second place in the graph represents a custom variable (used to represent the module). )
  • Fourth: You notice that the first parameter in my require has six modules, but there are only four variables in function. Note here: If we don't use this module in funtcion function (note that it's not used in function, not elsewhere), then we try to put it back.
  • Fifth: Here we declare that: (1) in the figure represents a js file, and (2) in the figure is a custom variable. Since it is a custom variable, it means that we can write it freely (to represent the previous js file). Some people may ask, there are many classes under a folder, can't we just write them randomly? This situation does not exist. In this declaration: 1 in the figure represents a js path, and it is impossible to have a file with the same name under the same folder.

4. summary

In this blog, I mainly talked about

  • How to create classes, how to use classes, where we can use the define method to make our class a file, easy to manage.
  • How to use callback functions to return data in classes
  • How to use extraclass variables in classes (which can be passed in through constructors)
  • Use dojo/_base/lang module correctly in class to control our this keyword
  • The loading process of require is re-introduced.
  • Note that we define many classes and modules, but there is only one entry for our program.

4.1 Download address of this blog code: dojo_class

Posted by heminfotech on Fri, 21 Dec 2018 17:27:05 -0800