使用 Closure 库构建应用

本教程将引导您构建一款简单的应用,让您可以亲身使用 Closure 库。要完成本教程,您应该具备一些 JavaScript 使用经验,并且应该已经完成了 Closure 库使用入门中的练习。

使用以下链接下载本教程中使用的两个源文件:

将这些文件保存到包含 closure-library 目录的同一目录中。

本教程逐步介绍了这些源文件的不同部分。请注意,提供的 notepad.html 文件必须下载并关联到 Closure 库的副本,然后才能使用,如下所述。

Notes 应用

本教程说明构建一个简单的应用以显示笔记的过程。示例:

  • 为应用创建命名空间,
  • 使用 Closure 库的 goog.dom.createDom() 函数为列表创建文档对象模型 (DOM) 结构,以及
  • 使用记事列表中的 Closure Library 类,允许用户打开和关闭列表中的项。

使用 goog.offer() 创建命名空间

当您使用来自不同来源的 JavaScript 库时,某些 JavaScript 文件可能会重新定义您在代码中使用的全局变量或函数名称。为了最大限度地降低此类名称冲突的风险,请使用 Closure 库的 goog.provide() 函数为代码创建命名空间。

例如,备注应用使用由 Note() 构造函数函数创建的 Note 对象。如果任何其他 JavaScript 文件定义了一个全局 Note 函数或变量,则可能会覆盖此构造函数。因此,该示例会通过对 goog.provide 进行以下调用,为此构造函数创建一个命名空间:

goog.provide('tutorial.notepad.Note');

goog.provide() 函数可确保其参数指示的 JavaScript 对象结构存在。它会检查路径表达式中的每个对象属性是否存在,如果不存在,则对其进行初始化。上面的函数调用等同于:

tutorial = tutorial || {};
tutorial.notepad = tutorial.notepad || {};
tutorial.notepad.Note = tutorial.notepad.Note || {};

因为 goog.provide() 只会初始化不存在的属性,所以绝不会覆盖属性。

请注意,goog.provide() 语句具有依赖项解析脚本 calcdeps.py 可使用它们的优势。请参阅使用依赖项计算脚本,了解如何使用 calcdeps.py

存在 tutorial.notepad.Note 对象结构后,此示例会将构造函数函数分配给 Note 属性。

tutorial.notepad.Note = function(title, content, noteContainer) {
  this.title = title;
  this.content = content;
  this.parent = noteContainer;
};

Note 构造函数现在位于使用 goog.provide() 创建的 tutorial.notepad 命名空间中。

使用 goog.dom.createDom() 创建 DOM 结构

为了在 HTML 文档中显示 Note,该示例为 Note 类提供了以下方法:

tutorial.notepad.Note.prototype.makeNoteDom = function() {
  // Create DOM structure to represent the note.
  this.headerElement = goog.dom.createDom(goog.dom.TagName.DIV,
      {'style': 'background-color:#EEE'}, this.title);
  this.contentElement = goog.dom.createDom(goog.dom.TagName.DIV, null, this.content);
  var newNote = goog.dom.createDom(goog.dom.TagName.DIV, null,
      this.headerElement, this.contentElement);

  // Add the note's DOM structure to the document.
  goog.dom.appendChild(this.parent, newNote);
};

此方法使用 Closure 库函数 goog.dom.createDom()。以下 goog.require() 语句包含此函数的代码:

goog.require('goog.dom');

如需添加并非构造函数的类似 goog.dom.createDom() 的函数,请将包含该函数的命名空间传递给 goog.require(在本例中为 goog.dom)。除非您需要类,否则无需在 goog.require() 语句中包含函数的名称。对于这种情况,使用 Closure 库类说明了 goog.require() 语句。

函数 goog.dom.createDom() 会创建一个新的 DOM 元素。例如,以下 makeNoteDom() 语句会创建一个新的 div 元素。

  this.headerElement = goog.dom.createDom(goog.dom.TagName.DIV,
      {'style': 'background-color:#EEE'}, this.title);

createDom() 调用中的第二个参数指定要添加到元素的属性,第三个参数指定要添加到元素的子元素(在本例中为字符串)。第二个参数和第三个参数都是可选的。

makeNoteDom() 方法只需创建一个 Note 参数。为了创建一个备注列表,该示例包含一个 makeNotes() 函数,该函数接受一组备注数据并为每个项实例化一个 Note 对象,从而调用 NotemakeNoteDom() 方法。

tutorial.notepad.makeNotes = function(data, noteContainer) {
  var notes = [];
  for (var i = 0; i < data.length; i++) {
    var note =
      new tutorial.notepad.Note(data[i].title, data[i].content, noteContainer);
    notes.push(note);
    note.makeNoteDom();
  }
  return notes;
};

使用 Closure 库类

只需两行代码,该示例就会让每条记事变为 ZippyZippy 是指可以收起或展开即可隐藏或显示内容的元素。

首先,该示例为 doubleclick 类添加了一组 required() 语句:

goog.require('goog.dom.TagName');
goog.require('goog.ui.Zippy');

然后,在 makeNoteDom 方法的末尾添加一行代码:

tutorial.notepad.Note.prototype.makeNoteDom = function() {
  // Create DOM structure to represent the note.
  this.headerElement = goog.dom.createDom(goog.dom.TagName.DIV,
      {'style': 'background-color:#EEE'}, this.title);
  this.contentElement = goog.dom.createDom(goog.dom.TagName.DIV, null, this.content);
  var newNote = goog.dom.createDom(goog.dom.TagName.DIV, null,
      this.headerElement, this.contentElement);

  // Add the note's DOM structure to the document.
  goog.dom.appendChild(this.parent, newNote);

  // NEW LINE:
  return new goog.ui.Zippy(this.headerElement, this.contentElement);
};

构造函数调用 new goog.ui.Zippy(this.headerElement, this.contentElement) 会将一个行为附加到备注元素,该元素会在用户点击 headerElement 时切换 contentElement 的可见性。

在 HTML 文档中使用记事本

以下是该示例应用的完整 JavaScript 代码:

goog.provide('tutorial.notepad');
goog.provide('tutorial.notepad.Note');

goog.require('goog.dom');
goog.require('goog.ui.Zippy');

/**
 * Iterates over a list of note data objects, creates a Note instance
 * for each one, and tells the instance to build its DOM structure.
 */
tutorial.notepad.makeNotes = function(data, noteContainer) {
  var notes = [];
  for (var i = 0; i < data.length; i++) {
    var note =
      new tutorial.notepad.Note(data[i].title, data[i].content, noteContainer);
    notes.push(note);
    note.makeNoteDom();
  }
  return notes;
};

/**
 * Manages the data and interface for a single note.
 */
tutorial.notepad.Note = function(title, content, noteContainer) {
  this.title = title;
  this.content = content;
  this.parent = noteContainer;
};

/**
 * Creates the DOM structure for the note and adds it to the document.
 */
tutorial.notepad.Note.prototype.makeNoteDom = function() {
  // Create DOM structure to represent the note.
  this.headerElement = goog.dom.createDom(goog.dom.TagName.DIV,
      {'style': 'background-color:#EEE'}, this.title);
  this.contentElement = goog.dom.createDom(goog.dom.TagName.DIV, null, this.content);
  var newNote = goog.dom.createDom(goog.dom.TagName.DIV, null,
      this.headerElement, this.contentElement);

  // Add the note's DOM structure to the document.
  goog.dom.appendChild(this.parent, newNote);
  return new goog.ui.Zippy(this.headerElement, this.contentElement);
};

您可以下载 notepad.js 文件来获取此代码(点击即可下载文件)。

以下 HTML 使用此记事本代码在网页上显示记事列表:

<html>
<head>
<title>Notepad</title>
<script src="closure-library/closure/goog/base.js"></script>
<script src="notepad.js"></script>
</head>
<body>

<div id="notes">
</div>

<script>
function main() {
  var noteData = [
    {'title': 'Note 1', 'content': 'Content of Note 1'},
    {'title': 'Note 2', 'content': 'Content of Note 2'}];

  var noteListElement = document.getElementById('notes');
  var notes = tutorial.notepad.makeNotes(noteData, noteListElement);
}
main();
</script>
</body>
</html>

您可以下载文件 notepad.html点击此处下载文件)来获取此页面。

本页面:

  • 包含 Closure 库文件 base.jsscript 标记。此标记的 src 属性是从 HTML 文件到库的 base.js 文件的路径。
  • 为包含记事本代码的文件添加 script 标记。
  • 在页面中包含一个脚本,用于通过调用 makeNotes() 初始化笔记列表。makeNotes() 函数接受两个参数:对象数组(每个数组都包含一条备注的数据),以及用于为备注列表构建 DOM 结构的 DOM 元素。