天天看點

百度地圖API詳解之事件機制,function“閉包”解決for循環和監聽器沖突的問題:

百度地圖API詳解之事件機制

2011年07月26日 星期二 下午 04:06

和DOM程式設計裡的事件模型一樣,百度地圖API也提供了類似的事件機制。本文介紹了事件監聽的添加和移除方法,this指針和事件參數的使用以及綁定事件監聽函數中涉及的閉包問題,最後分享了一個用來增強地圖API事件機制的開源項目。

事件添加和移除

我們最簡單的事件開始,下面的代碼示例給map對象添加了click事件的監聽函數,當使用者點選地圖時該監聽函數就會被觸發:

var map

=new BMap.Map('map');

map.centerAndZoom(new BMap.Point(116.404,

39.915),

11);

map.addEventListener('click',

function(){

alert('您點選了地圖');

});

在初始化地圖完成後,我們通過map對象的addEventListener方法添加click事件的監聽。凡是在類參考文檔中說明某個類具備某些事件時,我們都可以調用該對象的addEventListener方法添加響應的事件監聽函數。

上面我們通過傳入一個匿名函數添加了事件監聽,如果我們需要移除事件監聽,則需要将監聽函數用具名函數表示:

var clickHandler

=function(){

}

map.addEventListener('click', clickHandler);

// 後續進行移除

map.removeEventListener('click', clickHandler);

事件參數

和DOM事件類似,在百度地圖API的事件機制中也提供了事件參數,參數通過監聽函數的參數進行傳遞,比如我們修改最開始的代碼:

function(e){

alert('點選坐标:

'+ e.point.lng

+',

'+ e.point.lat);

通過API的類參考文檔得知,click事件的參數包含type、target、point和pixel四個屬性,上面的示例就是擷取了point屬性,它表示目前點選的地理位置。

this

在事件監聽中還可以通過this引用觸發事件的對象,就像标準的DOM事件一樣。

map.addEventListener('dragend',

alert(this.getCenter());

// 這裡的this就是map執行個體

事件閉包

閉包是Javascript腳本語言的特性之一,不熟悉它的開發者很可能犯下面這種錯誤:頁面有十個标注(Marker執行個體),我希望點選不同的标注開啟内容不同的資訊視窗,每個資訊視窗顯示該标注的索引(1到10)。首先我們初始化标注執行個體并存放于數組中:

var markers

= [];

for (var i

=0; i

<10; i

++) {

var mkr

=new BMap.Marker(new BMap.Point(116.2+

i /20,

39.855), {title: i

+1});

markers.push(mkr);

map.addOverlay(mkr);

我們給每個标注添加自己的title屬性以示區分,你将看到如下效果:

百度地圖API詳解之事件機制,function“閉包”解決for循環和監聽器沖突的問題:

下面,我們添加标注的點選事件,用來開啟内容不同的資訊視窗:

for (i

markers[i].addEventListener('click',

this.openInfoWindow(new BMap.InfoWindow('我是第'+

(i +1)

+'個标注'));

代碼看起來沒有任何問題,循環周遊markers數組,為每個标注執行個體綁定click事件,事件處理函數中開啟資訊視窗并顯示是第幾個标注。但是通過浏覽器看效果的時候卻發現問題了:

百度地圖API詳解之事件機制,function“閉包”解決for循環和監聽器沖突的問題:

明明是第三個标注,點選之後的資訊視窗中卻顯示“11”。實際上,當click的監聽函數被執行的時候才會去看變量i的值是什麼,此時for循環早已經執行完,那麼當for循環執行完i的值正好是11。為了達到我們想要的效果,需要增加一層“閉包”:

(function(){

var index

= i;

(index +1)

})();

上面的代碼你可以了解為新增加的函數内部儲存了每次循環變量i的值,那麼當監聽函數執行時将會擷取閉包内儲存的index變量的值,而不是之前的變量i的值。再看一下,效果OK了:

百度地圖API詳解之事件機制,function“閉包”解決for循環和監聽器沖突的問題:

對地圖API事件增強

我們通過幾個例子來看一下它的使用方法,首先需要引用這個js腳本,這裡就直接使用github提供的原始資料的位址:

https://raw.github.com/jiazheng/EventWrapper/master/release/eventwrapper.min.js

下面我們添加兩個事件監聽:

var clickListener

= EventWrapper.addListener(map,

'click',

alert(e.point.lng +',

var dragListener

'dragend',

移除的方式如下:

EventWrapper.removeListener(dragListener);

我們将之前addListener方法傳回的對象傳遞給removeListener即可,這和google的使用方式一緻。此外我們還可以清除某個對象所有通過此方式綁定的事件:

EventWrapper.clearInstanceListeners(map);

// 清除map執行個體所有的事件監聽函數

目前此項目基本完成,但是還沒有經過大規模的測試和驗證,可能存在不完善的地方,也歡迎廣大開發者發現問題并進行回報。

from:http://www.cnblogs.com/jz1108/archive/2011/07/16/2107199.html

繼續閱讀