在 Closure 图书馆中找路

Closure 库包含许多不同的工具,从界面微件到通信实用程序,不一而足。 该库的不同部分共享了一组规范,有助于整理代码并使其易于使用。

本文简要介绍了 Closure 库代码库的核心惯例。阅读本文后,您应该对这些惯例足够熟悉“使用入门”练习,并进一步探索该库。

Closure 库命名空间

所有 Closure 库函数和属性的名称都以圆点分隔的路径开头,以防止它们与非 Closure 库代码中定义的名称意外重叠。此路径称为命名空间

例如,以下 Closure 库代码在 goog.math 命名空间内定义了 clamp() 函数:

goog.math.clamp = function(value, min, max) {
  return Math.min(Math.max(value, min), max);
};

您可以按如下方式调用此函数:

  var clampedValue = goog.math.clamp(2, 3, 4);

名称 goog 是 Closure 库命名空间的根。所有 Closure 库名称都以 goog 开头。

依赖项管理:goog.require()goog.provide()

所有 Closure 库 JavaScript 文件都以如下一段代码开头:

goog.provide('goog.math');

goog.require('goog.array');
goog.require('goog.math.Box');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Range');
goog.require('goog.math.Rect');
goog.require('goog.math.Size');

Closure 库文件开头的 goog.provide() 语句声明了该文件提供的公共命名空间和类。goog.require() 语句指示此文件需要的 Closure 库的其他部分。 goog.provide()goog.require() 都是在 Closure 库文件 closure/goog/base.js 中定义的函数。

goog.provide()goog.require() 共同提供 Closure 库的依赖项管理系统。此系统可让您轻松组建您要使用的 Closure 库的各个部分。

在您自己的代码中使用 goog.require() 函数来加载所需的 Closure 库部分。请参阅 Closure 库使用入门,了解如何使用 goog.require() 加载 Closure 库软件包。

继承

Closure 库使用 goog.inherits() 函数向 JavaScript 添加继承机制。Closure 库使用此函数将其代码库整理到类和子类中。

例如,以下代码定义了继承自 Button 类的 MenuButton Closure 库类的构造函数:

goog.ui.MenuButton = function(content, opt_menu, opt_renderer, opt_domHelper) {
  goog.ui.Button.call(this, content, opt_renderer ||
      goog.ui.MenuButtonRenderer.getInstance(), opt_domHelper);

  // Menu buttons support the OPENED state.
  this.setSupportedState(goog.ui.Component.State.OPENED, true);

  if (opt_menu) {
    this.setMenu(opt_menu);
  }
  this.timer_ = new goog.Timer(500);  // 0.5 sec
};
goog.inherits(goog.ui.MenuButton, goog.ui.Button);

上述代码中最后一个语句 goog.inherits(goog.ui.MenuButton, goog.ui.Button)MenuButton 确立为 Button 的子类(您可以在 closure/goog/base.js 中看到 goog.inherits() 的实现)。由于这是对 goog.inherits() 的调用,因此即使没有 goog.ui.MenuButton.prototype.getValue() 方法,您也可以对 MenuButton 实例调用 getValue() 方法,如下所示:

  var btn = new goog.ui.MenuButton('hi');
  var value = btn.getValue();

MenuButtonButton 继承 getValue() 方法。

请注意,MenuButton 构造函数的第一行会调用 Button 构造函数,如下所示:

goog.ui.MenuButton = function(content, opt_menu, opt_renderer, opt_domHelper) {
  goog.ui.Button.call(this, content, opt_renderer ||
      goog.ui.MenuButtonRenderer.getInstance(), opt_domHelper);
  ...
};
goog.inherits(goog.ui.MenuButton, goog.ui.Button);

必须要调用此类父类构造函数才能正确建立继承。您可以使用 goog.inherits() 在您自己的代码中创建继承,但请务必始终使用 call() 调用父类构造函数。

每个类的 API 文档都会显示该类的继承层次结构,以及该类从父类继承的所有方法。

Closure 库活动

现代浏览器使用事件来触发 JavaScript 函数来响应用户操作。遗憾的是,不同的浏览器具有不同的事件系统。

Closure 库定义了自己的事件框架,其框架在所有浏览器中以相同方式运行。此外,此框架还允许程序员定义和分派自己的事件类型。Closure 库在整个代码库中使用其事件框架,让您可以像监听 DOM 元素一样监听事件的 Closure 库对象。

例如,对于库的可折叠元素 widget (goog.ui.Zippy) 的代码而言,下面这行代码使用事件框架来在用户点击监听器时附加监听器:

goog.events.listen(this.elHeader_, goog.events.EventType.CLICK,
    this.onHeaderClick_, false, this);

此代码会将事件监听器附加到 DOM 元素 elHeader_。由于对 goog.events.listen() 进行此调用,用户点击 elHeader_ 会触发处理程序函数 onHeaderClick_。如需详细了解此调用中的其他参数,请参阅事件教程

通过使用 goog.events.listen() 在您自己的代码中处理浏览器事件,您就无需为不同浏览器的事件系统编写特殊情况。

您还可以使用 goog.events.listen() 监听 Closure 库类的实例。例如,打开 doubleclick 时,Closure 库类 goog.ui.Zippy 会分派下方显示的自定义事件:

  this.dispatchEvent(new goog.ui.ZippyEvent(goog.ui.Zippy.Events.TOGGLE,
      this, this.expanded_));

通过监听此事件,您的代码可以对其进行响应,例如向用户发送提醒,如下所示:

  var zippyHeader = document.getElementById('header');
  var zippyContent = document.getElementById('content');
  var zippy = new goog.ui.Zippy(zippyHeader, zippyContent);

  function react(e) {
    alert('The Zippy opened!');
  }
  goog.events.listen(zippy, goog.ui.Zippy.Events.TOGGLE, react);

如需详细了解 Closure 库事件,请参阅事件教程