在做了Firefox插件这么长时间,还是被Firefox插件的命名空间问题弄的头晕脑胀,如果我们想要代码重用,例如我写个Google搜索栏,然后再写Baidu搜索栏,以为可以良好的运行,其实并不可以,因为无论是id,还是方法都会冲突,更可怕的是命名空间和js文件的冲突。可以说,冲突的问题真是千奇百怪啊。
因为命名空间出错,大部分是因为我们通常情况下编写JavaScript的时候都是以静态的方法去写的,JavaScript其实是面向对象的编程语言,所以如果你不习惯用面向对象开发,那就要好好学习一下JavaScript的面向对象了,OK,多的不说,我们首先要写一个变量。注意,整个全局中都只能有一个共有变量,否则其他的变量很可能引起冲突。
var FFNamespace = {}; // 命名空间
(function() { var namespaces = []; // 注册命名空间
this.ns = function(fn) {
var ns = {};
namespaces.push(fn, ns);
return ns;
}; // 初始化命名空间
this.initialize = function() {
for (var i=0; i<namespaces.length; i+=2) {
var fn = namespaces[i];
var ns = namespaces[i+1];
fn.apply(ns);
}
}; // 清除命名空间
this.shutdown = function() {
window.removeEventListener("load", FFNamespace.initialize, false);
window.removeEventListener("unload", FFNamespace.shutdown, false);
}; // 初始化生命周期
window.addEventListener("load", FFNamespace.initialize, false);
window.addEventListener("unload", FFNamespace.shutdown, false);
}).apply(FFNamespace);
上面的代码我们保存为一个文件就可以了,例如保存为gj.Namespace,但是光只有这里的代码还不够,我们还需要创建公共的变量和方法以便可以互相访问。
// 创建公共变量
getCurrentURI: function() {
return window.location.href;
},
// 扩展的快捷方式
appname: FFNamespace,
// XPCOM
Cc: Components.classes,
Ci: Components.interfaces
};
上面的代码我们可以保存为gj.Namespace.Lib,看了上面的代码之后,你肯定不太清楚appname是干什么用的,这里appname就相当于是一个快捷方式。因为如果写命名空间的全称,可能比较长,定义了快捷方式之后我们就可以用快捷方式来命名了。
现在我们来创建两个“冲突”的js文件,分别为Test1和Test2。
{
appname.Test1 =
{
onClick:function()
{
alert(‘test 1 on click‘);
}
}
}});
上面是Test1,下面是Test2。
{
appname.Test2 =
{
onClick:function()
{
alert(‘test 2 on click‘);
}
}
}});
上面的代码我们同样保存为Test1.js和Test2.js,保存完之后我们就可以写XUL了。XUL代码如下。
<?xml-stylesheet href="chrome://{appname}/skin/overlay.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://{appname}/locale/overlay.dtd">
<overlay id="{appname}-overlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="chrome://{appname}/content/gj.Namespace.js"
type="application/x-javascript"/>
<script src="chrome://{appname}/content/gjNamespace.Lib.js"
type="application/x-javascript"/>
<script src="chrome://{appname}/content/Test1.js"
<script src="chrome://{appname}/content/Test2.js"
<!– firefox –>
<statusbar id="status-bar">
<statusbarpanel id="bar1" onmousedown="FFNamespace.Test1.onClick();">
<label value="My God!"/>
</statusbarpanel>
</statusbar> </overlay>
上面我们创建了一个状态栏的插件,让他显示My God!,然后我们执行了命名空间的相应的方法,这里我们可以看到两个代码基本上都是差不多的,而且我们就算把这个插件换一个名字,再同样安装,也是没有任何冲突的,怎么样,是不是完美的解决方法?
其实这个原理说简单也简单,说复杂也复杂,主要是把命名空间对象放到数组里面,这样就能够减少冲突了。还可以参考这篇文章。
本来还想问你这个代码引用是怎么弄的
结果发现用的不是一个博客系统……
主题一样而已,汗……
[...] Firefox Add-on – 完美解决命名空间问题 [...]