在此步骤中,您将学习以下内容:
- 如何通过 XHR 和 Object网址s 从应用外部加载资源,并将资源添加到 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网址s
在 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
,并将具有此 ObjectURL
的 <img>
元素添加到 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#.jpg 或 http://goo.gl/HPBGR#.png。
更多信息
如需详细了解此步骤中引入的一些 API,请参阅:
准备好继续下一步了吗?转到第 6 步 - 将待办事项导出到文件系统 »