第 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 步 - 将待办事项导出到文件系统 »