關於chrome擴展開發的栗子已經有很多了,問問度娘基本能滿足你的欲望, 我想說的是擴展和頁面間的數據傳遞問題。
我們知道寫擴展有個必須的文件就是“manifest.json”, 這個里面定義了一個和頁面打交道的文件“content.js”, 該js可以訪問頁面中的任何元素;但不幸的是頁面卻無法訪問content.js中的任何方法(寫擴展頁面的除外啊,我說的頁面是瀏覽器中的普通頁面)。那么問題就來了:怎么才能觸發content.js中的事件呢?
官方當然給出解決方案:content.js中寫按鈕的監聽事件,比如一般button的click事件
1 //bt1 是頁面按鈕id 2 document.getElementById('bt1')..addEventListener(“click”,function(){ 3 //做一些自己的事情,和background.js打交道等等 4 },false);
這么做當然沒有問題。
但是……
如果頁面中沒有bt1按鈕呢 ?
如果我不知道是哪個按鈕調用的呢 ?
或者說,content.js中有一個方法,需要頁面上隨時可以調用 。。。。
解決辦法就是,頁面添加一個固定的按鈕就叫bt1,其他的都不能叫這個名字,content.js這樣就可以綁定事件了, 誰用誰調用一下bt1的click事件。
其實還有個解決辦法:自定義事件 , 看代碼
1 //頁面中定義一個事件 2 //name 事件名稱,msg傳遞的消息值 3 createCustomEvent:function(name,msg){ 4 var evt = document.createEvent("CustomEvent"); 5 evt.initCustomEvent(name, true, false, msg); 6 document.dispatchEvent(evt); 7 },
content.js寫一個事件監聽
1 //content.js中的監聽方法 2 //name要和頁面name相同 3 //evt 就是得到的結果 4 document.addEventListener(name, function(evt) { 5 var data =evt.detail; //data就是上面的msg值 6 7 //todo 8 9 }
這樣整個流程就通了,頁面隨時可以創建一個事件來調用擴展方法。
不過明白人已經看出來了,返回值呢? 是的,該方法只能傳遞值卻不能得到結果,並且msg只能傳遞字符串,也沒法定義回調。如果想得到返回值只能再content.js中也定義一個自定義事件,頁面做監聽,反過來使用上面的代碼。(感覺很矬……)
這還沒有完, 該方案不支持並發。當有兩個地方同時調用該方法時,頁面監聽事件無法區分那個的返回值,得到的結果根本無法使用。
怎么辦呢? 我又想到一個更矬的辦法來,調用的時候傳遞一個回調,然后保存起來。
說不明白,看代碼吧。頁面代碼
1 var sendMessage=function(msg,callback){ 2 //獲取一個自增序列當key,頁面唯一 3 var key=getIndex(); 4 //保存到hashtable里面,evtMap是個自定義hashtable 5 evtMap.add(key,callback); 6 //'調用自定義事件,把key帶上 7 createCustomEvent(eventName,{"evtId":key,"msg":msg}); 8 9 }
content.js可以得到這個key,回調的時候再把這個可以傳過來,看看content.js
1 document.addEventListener(listenerName, function(evt) { 2 3 var data =evt.detail; 4 //todo 得到msg 5 6 var res={"evtId":data.evtId,"msg":msg }; //把頁面傳遞的key再傳回去 7 8 var evt = document.createEvent("CustomEvent"); 9 evt.initCustomEvent(backEventName, true, false, res); 10 document.dispatchEvent(evt); 11 12 }, false);
再回到頁面js代碼
1 document.addListener(listenerName,function(response){ 2 //通過key從hasttable中再次獲取callback函數 3 var evtId=response.evtId; 4 var callback=evtMap.getValue(evtId); 5 if (callback) { 6 callback(response.msg); 7 }; 8 });
上面就是一種比較矬的解決擴展和頁面數據交互的一種方案,如果哪位高手有更好的方案不舍賜教~!! 感謝
下面把JS的Hashtable貼一下,其實度娘懷里就有
var HashTable=function(){ var size = 0; var entry = new Object(); this.add = function (key,value){ if(!this.containsKey(key)){ size ++ ; } entry[key] = value; } this.getValue = function (key) { return this.containsKey(key) ? entry[key] : null; } this.remove = function(key){ if( this.containsKey(key) && ( delete entry[key] ) ) { size --; } } this.containsKey = function(key){ return (key in entry); } this.containsValue = function(value){ for(var prop in entry) { if(entry[prop] == value){ return true; } } return false; } this.getValues = function () { var values = new Array(); for(var prop in entry) { values.push(entry[prop]); } return values; } this.getKeys = function () { var keys = new Array(); for(var prop in entry) { keys.push(prop); } return keys; } this.getSize = function () { return size; } this.clear = function () { size = 0; entry = new Object(); } }
