Bước 5: Thêm hình ảnh từ web

Trong bước này, bạn sẽ tìm hiểu:

  • Cách tải tài nguyên từ bên ngoài ứng dụng và thêm tài nguyên vào DOM thông qua XHR và ObjectURLs.

Thời gian ước tính để hoàn tất bước này: 20 phút.
Để xem trước những việc bạn sẽ hoàn thành trong bước này, hãy chuyển xuống cuối trang này ↓.

Cách CSP ảnh hưởng đến việc sử dụng tài nguyên bên ngoài

Nền tảng Ứng dụng Chrome buộc ứng dụng của bạn phải hoàn toàn tuân thủ Chính sách bảo mật nội dung (CSP). Bạn không thể tải trực tiếp các tài nguyên DOM như hình ảnh, phông chữ và CSS từ bên ngoài Ứng dụng Chrome của mình .

Nếu muốn hiển thị hình ảnh từ bên ngoài trong ứng dụng, bạn cần yêu cầu hình ảnh đó qua XMLHttpRequest, biến đổi nó thành Blob rồi tạo ObjectURL. Bạn có thể thêm ObjectURL này vào DOM vì thành phần này đề cập đến một mục trong bộ nhớ trong bối cảnh của ứng dụng.

Hiển thị hình thu nhỏ cho các mục việc cần làm

Hãy thay đổi ứng dụng để tìm URL hình ảnh trong một mục việc cần làm. Nếu URL trông giống như một hình ảnh (ví dụ: ví dụ: kết thúc bằng .png, .jpg, .svg hoặc .gif), hãy áp dụng quy trình nêu trên để hiển thị hình thu nhỏ bên cạnh URL.

Cập nhật quyền

Trong một ứng dụng Chrome, bạn có thể thực hiện các lệnh gọi XMLHttpRequest đến bất kỳ URL nào, miễn là bạn chỉ định miền của URL đó trong tệp kê khai. Vì bạn sẽ không biết trước người dùng sẽ nhập URL hình ảnh nào, hãy xin phép gửi yêu cầu đến "<all_urls>".

Trong tệp manifest.json, hãy yêu cầu mã "" quyền:

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

Tạo và xoá ObjectURLs

Trong controller.js, hãy thêm phương thức _createObjectURL() để tạo ObjectURLs từ một Blob:

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

Các ObjectURL giữ bộ nhớ, vì vậy, khi không cần ObjectURL nữa, bạn nên thu hồi chúng. Thêm nội dung này _clearObjectURL() đến controller.js để xử lý việc đó:

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

Tạo yêu cầu XHR

Thêm phương thức _requestRemoteImageAndAppend() để thực thi XMLHttpRequest trên một URL hình ảnh nhất định:

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();
};

Khi tải XHR, phương thức này sẽ tạo một ObjectURL từ phản hồi của XHR và thêm một phần tử <img> bằng ObjectURL này vào DOM.

Phân tích cú pháp URL hình ảnh trong các mục việc cần làm

Bây giờ, hãy thêm một phương thức _parseForImageURLs() tìm tất cả các đường liên kết chưa được xử lý rồi kiểm tra những đường liên kết đó hình ảnh. Đối với mỗi URL trông giống như một hình ảnh, hãy thực thi _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]);
    }
  }
};

Hiển thị hình thu nhỏ trong danh sách việc cần làm

Bây giờ, hãy gọi _parseForImageURLs() từ showAll(), showActive()showCompleted():

/**
 * 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));
};

Làm tương tự với 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) {
  ...
}

Cố định kích thước hình ảnh hiển thị

Cuối cùng, trong _bowercomponents/todomvc-common/base.css, hãy thêm một quy tắc CSS để giới hạn kích thước của hình ảnh:

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

Chạy ứng dụng Việc cần làm đã hoàn thành

Bạn đã hoàn tất Bước 5! Tải lại ứng dụng rồi thêm một mục việc cần làm có URL đến một hình ảnh được lưu trữ trực tuyến. Hơi nhiều URL mà bạn có thể sử dụng: http://goo.gl/nqHMF#.jpg hoặc http://goo.gl/HPBGR#.png.

Thông tin khác

Để biết thêm thông tin chi tiết về một số API được giới thiệu trong bước này, hãy tham khảo:

Bạn đã sẵn sàng chuyển sang bước tiếp theo? Chuyển tới Bước 6 - Xuất việc cần làm sang hệ thống tệp »