介绍
在leaflet中有上百个插件,非常的实用,这是因为leaflet具有很好的可拓展性。
本文就来介绍一下leaflet的拓展基础
官方文档:leaflet
leaflet architecture
在leaflet1.0.0中有超过60多个js类,官方网站使用了一个L.ImageOverlay来提供展示,这里就直接放上该类图的UML的链接吧:LeafletUML
从技术上来讲,共有以下几种方式来拓展leaflet
- 最常用的,使用L.Class.extend()方法创建L.Layer, L.Handler or L.Control的子类
- 在已存在的类中使用L.Class.extend()方法来增加更多的功能。
- 使用L.Class.extend()改变已存在的类中已有的功能
L.Class
JavaScript是一个比较奇怪的语言(leaflet官网原话),他不是真正的面向对象的语言,而更像是面向原型的语言(prototype-oriented language)
leaflet中的所有类都继承自L.Class。
L.Class.extend()
为了提高extend()方法的拓展能力,它只接受一个参数,一个带有键值对的普通对象,就像下面这样:
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 console
console.log( myDemoInstance.myDemoMethod() );
每个键代表了方法或者属性的名字,值代表了具体的方法和属性。
这样就得到了了一个新的对象,并且可以使用拓展的方法和属性。
L.Class.include()
如果类已经被定义了,但是你还想拓展这个类的功能,你就要用到include()方法,它的参数和extend方法一样,都是带有键值对的普通对象,其使用也基本一致
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()
在面向对象的编程中,一般有一个构造方法。而在leaflet中,这一功能由initialize()方法来实现,如果你有要在构造方法中执行的操作,可以修改该方法来实现
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
其中的L.setOption方法可以直接将选项与已有的进行绑定。
和一般的继承一样,leaflet的父类中的属性也可以被子类所继承
var MyCubeClass = MyBoxClass.extend({
options: {
depth: 1
}
});
var instance = new MyCubeClass('Blue');
console.log(instance.options.width); // Outputs "1", parent class default
console.log(instance.options.height); // Outputs "1", parent class default
console.log(instance.options.depth); // Outputs "1"
leaflet还提供了一个初始化方法的钩子方法,可以在initialize方法执行后立即执行,如下
MyBoxClass.addInitHook(function(){
this._area = this.options.width * this.options.length;
});
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.LayerGroup.extend({
addLayer: function (layer) {
…
L.LayerGroup.prototype.addLayer.call(this, layer);
},
removeLayer: function (layer) {
…
L.LayerGroup.prototype.removeLayer.call(this, layer);
},
…
});
大多数 Leaflet 类都有相应的工厂函数。工厂函数与类同名,但采用 lowerCamelCase 而不是 UpperCamelCase
function myBoxClass(name, options) {
return new MyBoxClass(name, options);
}
结语
leaflet的强大在于其良好的可拓展性,这让他有了很多可以使用的插件,我们也可以在原生leaflet的基础上进一步开发自己需要的插件。
这一章算是进阶内容的入门篇,在之后的leaflet进阶中会进一步研究这一内容。