天天看點

dojo事件機制詳解(二)示例源碼解析dojo.connectPublisher函數

示例

上一篇講解了dojo connect事件機制,這一篇講解dojo訂閱釋出模式,主要使用的方法為dojo.subscribe、dojo.unsubscribe、dojo.publish三個函數,如果了解了上一篇, 訂閱釋出模式了解起來就很簡單。不多說了,先來個示例:

var topic = "alarm";
function Foo() {
	this.alarm = function() {
		console.info("do something in Foo's alarm function");
		//釋出主題
		dojo.publish(topic);
	};
}

function Bar() {
	this.getup = function() {
		console.info("alarming now, need to getup");
	}
}

function Baz() {
	this.name = "Baz";
	this.work = function() {
		console.info("alarming now, need to start working");
	}
}

var foo = new Foo();
var bar = new Bar();
var baz = new Baz();

// 訂閱主題
dojo.subscribe(topic, bar, "getup");
dojo.subscribe(topic, baz, "work");

// 該函數調用中釋出主題,然後會觸發訂閱的監聽器
foo.alarm();
           

源碼解析

//所有的主題都在存儲在該對象中
dojo._topics = {};

// 訂閱某主題
dojo.subscribe = function(/*String*/ topic, /*Object|null*/ context, /*String|Function*/ method){
	// 是不是很簡單,主要就調用了一個函數:dojo._listener.add
	// 該函數已經在上一篇詳細講解過了,add函數執行過後,會在dojo._topics對象中存儲一個分發器函數(代理函數),key就為topic
	// 這個分發器函數的_listeners數組屬性存儲了所有監聽器
	// dojo.hitch傳回設定了this變量後的監聽器函數
	return [topic, dojo._listener.add(dojo._topics, topic, dojo.hitch(context, method))]; /*Handle*/
};

// 釋出主題,并且可以傳遞參數
dojo.publish = function(/*String*/ topic, /*Array*/ args){
	// 是不是就更簡單了,從dojo._topics對象中取出分發器函數
	var f = dojo._topics[topic];
	// 判斷分發器函數是否存在
	if(f){
		// 調用分發器函數,該函數中先調用原目标函數,随即調用_listeners數組中存儲的各個監聽器函數
		// 監聽器參數清單就為publish函數的args數組
		f.apply(this, args||[]);
	}
};

// 取消訂閱
dojo.unsubscribe = function(/*Handle*/ handle){
	// handle為subscribe函數的傳回值
	if(handle){
		// 調用dojo._listener.remove函數,從dojo._topics對象中key為topic的分發器函數監聽器清單中移除指定位置的監聽器
		dojo._listener.remove(dojo._topics, handle[0], handle[1]);
	}
};
           

dojo.connectPublisher函數

還有一個dojo.connectPublisher函數需要說一下,通過該函數可以将dojo.publish從函數中脫離出來,更加友善:

dojo.connectPublisher = function(	/*String*/ topic,
									/*Object|null*/ obj,
									/*String*/ event){
	
	//該代理函數的參數清單與目标對象obj的函數參數一緻
	var pf = function(){ dojo.publish(topic, arguments); }
	return event ? dojo.connect(obj, event, pf) : dojo.connect(obj, pf); //Handle
};
           

PS:dojo版本為dojo-release-1.6.3

繼續閱讀