关于chrome扩展开发的栗子已经有很多了,问问度娘基本能满足你的欲望, 我想说的是扩展和页面间的数据传递问题。
我们知道写扩展有个必须的文件就是“manifest.json”, 这个里面定义了一个和页面打交道的文件“content.js”, 该js可以访问页面中的任何元素;但不幸的是页面却无法访问content.js中的任何方法(写扩展页面的除外啊,我说的页面是浏览器中的普通页面)。那么问题就来了:怎么才能触发content.js中的事件呢?
官方当然给出解决方案:content.js中写按钮的监听事件,比如一般button的click事件
//bt1 是页面按钮id
document.getElementById('bt1')..addEventListener(“click”,function(){
//做一些自己的事情,和background.js打交道等等
},false);
这么做当然没有问题。
但是……
如果页面中没有bt1按钮呢 ?
如果我不知道是哪个按钮调用的呢 ?
或者说,content.js中有一个方法,需要页面上随时可以调用 。。。。
解决办法就是,页面添加一个固定的按钮就叫bt1,其他的都不能叫这个名字,content.js这样就可以绑定事件了, 谁用谁调用一下bt1的click事件。
其实还有个解决办法:自定义事件 , 看代码
//页面中定义一个事件
//name 事件名称,msg传递的消息值
createCustomEvent:function(name,msg){
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent(name, true, false, msg);
document.dispatchEvent(evt);
},
content.js写一个事件监听
//content.js中的监听方法
//name要和页面name相同
//evt 就是得到的结果
document.addEventListener(name, function(evt) {
var data =evt.detail; //data就是上面的msg值 //todo }
这样整个流程就通了,页面随时可以创建一个事件来调用扩展方法。
不过明白人已经看出来了,返回值呢? 是的,该方法只能传递值却不能得到结果,并且msg只能传递字符串,也没法定义回调。如果想得到返回值只能再content.js中也定义一个自定义事件,页面做监听,反过来使用上面的代码。(感觉很矬……)
这还没有完, 该方案不支持并发。当有两个地方同时调用该方法时,页面监听事件无法区分那个的返回值,得到的结果根本无法使用。
怎么办呢? 我又想到一个更矬的办法来,调用的时候传递一个回调,然后保存起来。
说不明白,看代码吧。页面代码
var sendMessage=function(msg,callback){
//获取一个自增序列当key,页面唯一
var key=getIndex();
//保存到hashtable里面,evtMap是个自定义hashtable
evtMap.add(key,callback);
//'调用自定义事件,把key带上
createCustomEvent(eventName,{"evtId":key,"msg":msg}); }
content.js可以得到这个key,回调的时候再把这个可以传过来,看看content.js
document.addEventListener(listenerName, function(evt) { var data =evt.detail;
//todo 得到msg var res={"evtId":data.evtId,"msg":msg }; //把页面传递的key再传回去 var evt = document.createEvent("CustomEvent");
evt.initCustomEvent(backEventName, true, false, res);
document.dispatchEvent(evt); }, false);
再回到页面js代码
document.addListener(listenerName,function(response){
//通过key从hasttable中再次获取callback函数
var evtId=response.evtId;
var callback=evtMap.getValue(evtId);
if (callback) {
callback(response.msg);
};
});
上面就是一种比较矬的解决扩展和页面数据交互的一种方案,如果哪位高手有更好的方案不舍赐教~!! 感谢
下面把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();
}
}