扩展Leaflet:类

来源:互联网 发布:国行a1533支持什么网络 编辑:程序博客网 时间:2024/06/07 13:12

        Leaflet拥有数百个自由插件,这些插件扩展了Leaflet的功能:有时采用通用的方式,有时采用特定场景的方式。

        Leaflet拥有如此之多插件的部分原因是Leaflet易于扩展。该教程介绍扩展Leaflet最常用的方式。

        注意:本文假定你熟练掌握了一下知识:

  •         JavaScript
  •         DOM handling 
  •         Object-oriented programming(能够理解诸如类、实例、继承、方法和属性等概念)

Leafet 架构

        

        让我们看一下Leaflet 1.0.0 简化的UML 类图。Leaflet拥有60多个JavaScript类,因此UML图有点大,幸运的是我们可以使用L.ImageOverlay来制作可缩放的图片。


        从技术角度将,Leaflet可以使用如下几种方式来扩展:

  •   最常用的方式:使用L.Class.extend()创建L.Layer,L.Handler或者L.Control

  1.      地图移动、缩放时Layer就会移动
  2.      Handler不可见并且用来处理浏览器事件
  3.      Control是固定的接口元素

  •   使用L.Class.include()在已存在的类中包含新的函数功能

  1.       添加新的方法和选项
  2.       改变某些方法
  3.       使用addInitHook方法来执行额外的构造器代码

  •   使用L.Class.include()来更改已经存在的类中的部分内容(改变类中方法的实现)

        本文包含了仅仅在Leaflet 1.0.0中存在的类和方法,当为旧版本开发插件时应该注意类和方法的可用性。

L.Class


        JavaScript是一种有点奇怪的语言。它并不是一种真正的面向对象语言,而是一种面向原型的语言。这就使得JavaScript使用传统意义上的面向对象编程的继承变得困难,然而Leaflet基于L.Class使得类继承变得简单。尽管现代的JavaScript能够使用ES6中的类,但是Leaflet并不是基于ES6设计的。

L.Class.extend()


        我们可以使用.extend()来创建Leaflet中任意的子类。这个方法使用一个参数:即一个键值对的简单对象,每个键是属性或者方法的名称,每个值是属性的初始值或者方法的实现。
var MyDemoClass = L.Class.extend({    // A property with initial value = 42    myDemoProperty: 42,       // A method     myDemoMethod: function() { return this.myDemoProperty; }    });var myDemoInstance = new MyDemoClass();// This will output "42" to the development consoleconsole.log( myDemoInstance.myDemoMethod() );   

        为类、方法和属性命名时注意遵循以下命名习惯:

  • 函数、方法、属性和工厂方法名称应该使用小驼峰风格
  • 类名称应该使用大驼峰风格
  • 私有属性和方法以下划线(_)开始。这种写法并不是真正将属性和方法私有化,只是提醒开发者不要直接使用它们

L.Class.include()

        如果某个类已经定义了,可以使用.include()重新定义已有的属性、方法或者添加新的属性或者方法。

MyDemoClass.include({    // Adding a new property to the class    _myPrivateProperty: 78,        // Redefining a method    myDemoMethod: function() { return this._myPrivateProperty; }});var mySecondDemoInstance = new MyDemoClass();// This will output "78"console.log( mySecondDemoInstance.myDemoMethod() );// However, properties and methods from before still exist// This will output "42"console.log( mySecondDemoInstance.myDemoProperty );

L.Class.initialize()

        在OOP中,类会拥有一个构造器方法。在Leaflet中的L.Class中,构造器方法被命名为initialize。

        如果你的类拥有一些特定的选项(options),可以在构造器中使用L.setOptions()方法来初始化选项(options)。这个函数可以将提供的选项和类中的默认选项合并。

var MyBoxClass = L.Class.extend({    options: {        width: 1,        height: 1    },    initialize: function(name, options) {        this.name = name;        L.setOptions(this, options);    }    });var instance = new MyBoxClass('Red', {width: 10});console.log(instance.name); // Outputs "Red"console.log(instance.options.width); // Outputs "10"console.log(instance.options.height); // Outputs "1", the default

        Leaflet使用特殊的方式处理选项属性(options):子类会继承父类中的选项属性(options)。

var MyCubeClass = MyBoxClass.extend({    options: {        depth: 1    }});var instance = new MyCubeClass('Blue');console.log(instance.options.width);console.log(instance.options.height);console.log(instance.options.depth);

        子类执行父类构造器和自身的构造器也很常见的行为。在Leafleet中可以使用L.Class.addInitHook()实现。这个方法可以在类的initialize()方法刚刚执行之后“挂住”初始化函数,比如:

MyBoxClass.addInitHook(function(){    this._area = this.options.width * this.options.length;});

        在initialize()执行(调用setOpstions()的方法)之后会执行该函数。这就意味着this.options在hook执行之前已经存在并赋值了。

        addInitHook有一种可选的语法,可以使用方法名称和方法中的参数作为addInitHook的参数。

MyCubeClass.include({    _calculateVolume: function(arg1, arg2) {        this._volume = this.options.width * this.options.length * this.options.depth;    }});MyCubeClass.addInitHook('_calculateVolume', argValue1, argValue2);

父类的方法

        通过访问父类的原型可以调用父类中的方法,使用Function.call(...)可以实现。比如,可以在L.FeatureGroup的代码中看到:

L.FeatureGroup = L.LayerGroup.extend({    addLayer: function (layer) {        …        L.LayerGroup.prototype.addLayer.call(this, layer);    },        removeLayer: function (layer) {        …        L.LayerGroup.prototype.removeLayer.call(this, layer);    },    …});


        调用父类的构造器可以使用相同的方式,使用如下的方式替代:ParrentClass.prototype.initialize.call(this,...)。

工厂方法

        大多数的Leaflet类拥有对应的工厂方法。工厂方法拥有和对应类相同的名字,只不过类使用大驼峰风格而工厂方法使用小驼峰风格。

function myBoxClass(name, options) {    return new MyBoxClass(name, options);}

命名风格

        为Leaflet类插件命名时请遵循一下命名习惯:

  • 永远不要在你的插件中暴露全局变量
  • 如果你拥有一个新类,将它直接放在L命名空间中(L.MyPlugin)
  • 如果你继承一个已有的类,将它作为已有类的子属性

原文地址:http://leafletjs.com/examples/extending/extending-1-classes.html

0 0
原创粉丝点击