JS应用在Firebug中的扩展架构模式(2)

http://www.itjxue.com  2015-08-06 23:17  来源:未知  点击次数: 

下面这些代码是browserOverlay.js文件的内容,这个脚本文件会在一个界面文件(browserOverlay.xul)中被引用。

// 扩展对应的唯一全局变量
var myExtension = {};
(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", myExtension.initialize, false);
      window.removeEventListener("unload", myExtension.shutdown, false);
  };

  // 注册两个事件处理程序,维护扩展的生存期
  window.addEventListener("load", myExtension.initialize, false);
  window.addEventListener("unload", myExtension.shutdown, false);
}).apply(myExtension);

正如我前文所述,这里只有一个全局对象myExtension。

总结一下,这个对象要实现下面几个方法:

  • ns - 注册一个新的命名空间。
  • initialize - 初始化所有的命名空间。
  • shutdown - 收尾的清理工作。

当然这段代码也会确保initialize和shutdown方法会在正确的时间被调用,这也是两个事件处理程序的作用。

browserOverlay.xul现在看起来可能会是下面这个样子:

<?xml version="1.0"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/
there.is.only.xul">
  <script src="chrome://namespace/content/browserOverlay.js" type="application/x-javascript"/>
  <script src="chrome://namespace/content/Module1.js" type="application/x-javascript"/>
  <script src="chrome://namespace/content/Module2.js" type="application/x-javascript"/>
</overlay>

在这里,Module1.js和Module2.js两个文件是一模一样的。

myExtension.ns(function() {
  // TODO: 脚本内的全部代码
});

在不同的模块间共享数据

我们已经把所有的脚本置于本地的作用域下,现在让我们来回答上面提到的第二个问题,就是在不同的命名空间下如何共享函数和数据。基本的思路当然是要利用我们唯一的全局对象啦,也就是myExtension。

首先,让我们先来看看下面这段代码(都在lib.js文件中)

myExtension.LIB = {
  // 共享函数接口
  getCurrentURI: function() {
      return window.location.href;
  },

  // 扩展对象的快捷方式
  theApp: myExtension,

  // XPCOM组件的快捷方式
  Cc: Components.classes,
  Ci: Components.interfaces,

  // 等等。。。
};

你可以注意到,这段代码在全局的myExtension对象下建立了一个新的LIB属性,这个属性定义了一个函数库,是要在扩展所有的模块中共享的。你应该在Java的包结构中看到过相同的做法,所有的命名空间呈树状结构分布在一个唯一的对象下面,YUI也是这样子做的。

lib.js文件也在browserOverlay.xul中引入,紧随browserOverlay.js的后面。

<?xml version="1.0"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/
there.is.only.xul">
  <script src="chrome://myextension/content/browserOverlay.js" type="application/x-javascript"/>
  <script src="chrome://myextension/content/lib.js" type="application/x-javascript"/>
  <script src="chrome://myextension/content/Module1.js" type="application/x-javascript"/>
  <script src="chrome://myextension/content/Module2.js" type="application/x-javascript"/>
</overlay>

让我们对模块内的脚本也做一些改进。

myExtension.ns(function() {
  with(myExtension.LIB) {
      // TODO: 脚本内的全部代码
      var moduleVariable = "Accessible only from withing this module";
      dump("myExtension.Module initialization " + getCurrentURI() + "\n");
  }
});

通过利用with语句,我们可以方便的访问所有的库函数,就像访问全局变量一样。

既然我们要访问全局对象,还可以像下面这样利用theApp这个快捷方式(尤其是命名空间名字太长的时候)

myExtension.ns(function() {
  with(myExtension.LIB) {
      // TODO: 脚本内的全部代码
      theApp.sharedValue = "A new shared property";
  }
});

下面这个图是从UML的角度来纵观整个架构。

大家可以在 这里 下载本文提到的演示扩展。

(责任编辑:IT教学网)

更多

推荐Javascript/Ajax文章