步驟 5:從網路新增圖片

在這個步驟中,您將瞭解以下內容:

  • 如何從應用程式外部載入資源,並透過 XHR 和 ObjectURLs 將資源加入 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>"],

建立及清除物件網址

controller.js 中,新增 _createObjectURL() 方法,從 Blob 建立 ObjectURL:

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

ObjectURL 會保留記憶體,因此不再需要 ObjectURL 時,請予以撤銷。新增此項目 使用 _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;
}

啟動已完成的 Todo 應用程式

您已完成步驟 5!請重新載入應用程式,並新增內含線上代管圖片網址的待辦事項項目。只有部分通知 可用的網址:http://goo.gl/nqHMF#.jpghttp://goo.gl/HPBGR#.png

瞭解詳情

如要進一步瞭解這個步驟中導入的部分 API,請參閱:

準備好進行下一個步驟了嗎?前往步驟 6:將待辦事項匯出至檔案系統 »