第 5 步:从网络添加图片

在此步骤中,您将学习以下内容:

  • 如何从应用外部加载资源,并通过 XHR 和 Object网址 将其添加到 DOM。

完成此步骤预计用时:20 分钟。
若要预览您将在此步骤中完成的内容,请跳转到本页底部 ↓

CSP 如何影响外部资源的使用

Chrome 应用平台强制您的应用完全符合内容安全政策 (CSP)。 您无法直接从 Chrome 应用外部加载 DOM 资源(例如图片、字体和 CSS) 软件包。

如果您希望在应用中显示外部图片,则需要通过 XMLHttpRequest 请求, 将其转换为 Blob,然后创建 ObjectURL。您可以将此ObjectURL添加到 DOM,因为它指的是应用上下文中的内存项。

显示待办事项的缩略图

让我们更改应用,以在待办事项中查找图片网址。如果网址看起来像 (例如以 .png、.jpg、.svg 或 .gif 结尾),请按照上述流程展示 图片缩略图。

更新权限

在 Chrome 应用中,您可以对任何网址进行 XMLHttpRequest 调用,只要您在 。由于您不会事先知道用户将输入什么图片网址,因此请求权限以 向 "<all_urls>" 发出请求。

manifest.json 中,请求“”权限

"permissions": ["storage", "alarms", "notifications",
                "webview", "<all_urls>"],

创建和清除 Object网址

controller.js 中,添加 _createObjectURL() 方法以从 Blob 创建 Object网址:

Controller.prototype._createObjectURL = function(blob) {
  var objURL = URL.createObjectURL(blob);
  this.objectURLs = this.objectURLs || [];
  this.objectURLs.push(objURL);
  return objURL;
};

Object网址 会保留内存,因此当不再需要 Object网址 时,应撤销它们。添加此项 _clearObjectURL() 方法添加到 controller.js 以处理上述操作:

Controller.prototype._clearObjectURL = function() {
  if (this.objectURLs) {
    this.objectURLs.forEach(function(objURL) {
      URL.revokeObjectURL(objURL);
    });
    this.objectURLs = null;
  }
};

发出 XHR 请求

添加 _requestRemoteImageAndAppend() 方法以对给定的图片网址执行 XMLHttpRequest:

Controller.prototype._requestRemoteImageAndAppend = function(imageUrl, element) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', imageUrl);
  xhr.responseType = 'blob';
  xhr.onload = function() {
    var img = document.createElement('img');
    img.setAttribute('data-src', imageUrl);
    img.className = 'icon';
    var objURL = this._createObjectURL(xhr.response);
    img.setAttribute('src', objURL);
    element.appendChild(img);
  }.bind(this);
  xhr.send();
};

在 XHR 加载时,此方法会根据 XHR 的响应创建 ObjectURL,并添加 <img> 元素 将此 ObjectURL 添加到 DOM。

解析待办事项中的图片网址

现在添加 _parseForImageURLs() 方法,用于查找所有尚未处理的链接,并检查它们是否存在 图片。对于每个看起来像图片的网址,执行 _requestRemoteImageAndAppend()

Controller.prototype._parseForImageURLs = function () {
  // remove old blobs to avoid memory leak:
  this._clearObjectURL();
  var links = this.$todoList.querySelectorAll('a[data-src]:not(.thumbnail)');
  var re = /\.(png|jpg|jpeg|svg|gif)$/;
  for (var i = 0; i<links.length; i++) {
    var url = links[i].getAttribute('data-src');
    if (re.test(url)) {
      links[i].classList.add('thumbnail');
      this._requestRemoteImageAndAppend(url, links[i]);
    }
  }
};

在待办事项列表中呈现缩略图

现在,从 showAll()showActive()showCompleted() 调用 _parseForImageURLs()

/**
 * An event to fire on load. Will get all items and display them in the
 * todo-list
 */
Controller.prototype.showAll = function () {
  this.model.read(function (data) {
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
    this._parseForImageURLs();
  }.bind(this));
};

/**
 * Renders all active tasks
 */
Controller.prototype.showActive = function () {
  this.model.read({ completed: 0 }, function (data) {
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
    this._parseForImageURLs();
  }.bind(this));
};

/**
 * Renders all completed tasks
 */
Controller.prototype.showCompleted = function () {
  this.model.read({ completed: 1 }, function (data) {
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
    this._parseForImageURLs();
  }.bind(this));
};

editItem() 执行相同的操作:

Controller.prototype.editItem = function (id, label) {
  ...
  var onSaveHandler = function () {
    ...
    if (value.length && !discarding) {
      ...
      label.innerHTML = this._parseForURLs(value);
      this._parseForImageURLs();
    } else if (value.length === 0) {
  ...
}

限制显示的图片尺寸

最后,在 _bowercomponents/todomvc-common/base.css 中添加 CSS 规则,以限制 图片:

.thumbnail img[data-src] {
  max-width: 100px;
  max-height: 28px;
}

启动完成的待办事项应用

您已完成第 5 步!重新加载应用,然后添加待办事项,并提供指向在线托管图片的网址。部分 您可以使用的网址:http://goo.gl/nqHMF#.jpghttp://goo.gl/HPBGR#.png

了解详情

如需详细了解此步骤中引入的一些 API,请参阅:

准备好继续下一步了吗?转到第 6 步 - 将待办事项导出到文件系统 »