HTML5: Web Storage (DOM Storage)
HTML5 bổ sung rất nhiều API mới mà lập trình viên có thể sử dụng để hỗ trợ cho các ứng dụng game của mình. Ví dụ như lưu lại dữ liệu với Web Storage, Web Sql, Indexed DB, thực hiện công việc song song với Web Worker, giao tiếp với server thông qua Web Socket. Do thời lượng có lượng, tôi chỉ trình bày một phần nhỏ trong số này.
HTML5 cung cấp một tính năng lưu trữ dữ liệu tại client với dung lượng giới hạn lớn hơn nhiều so với cookie. Tính năng này được gọi là Web Storage và được chia thành hai đối tượng là localStorage và sessionStorage. Bài viết này sẽ giúp bạn nắm được các kiến thức đầy đủ về sử dụng hai đối tượng này trong việc lập trình web.
Giới thiệu
Hiện nay, mỗi cookie chỉ cho phép lưu trữ tối đa 4KB và vài chục cookie cho một domain. Vì thế cookie chỉ được dùng để lưu trữ những thông tin đơn giản và ngắn gọn như email, username, ... giúp người dùng đăng nhập tự động vào trang web. Điều này khiến cho những trang web muốn nâng cao hiệu suất làm việc bằng cách cache dữ liệu tại client hầu như không thể thực hiện được.
Sự xuất hiện của Web Storage là một điểm nhấn cho việc ra đời các ứng dụng web có khả năng tương tác và nạp dữ liệu tức thì trên trình duyệt. Một hiệu quả nữa là dung lương truyền tải qua mạng có thể được giảm thiểu đáng kể. Ví dụ một ứng dụng tra cứu sách trực tuyến, các sách đã được tra sẽ được lưu lại trên máy của người dùng. Khi cần tra lại, máy người dùng sẽ không cần kết nối đến server để tải lại những dữ liệu cũ.
Với những ứng dụng web có cơ sở dữ liệu nhỏ gọn, lập trình viên có thể thực hiện việc cache “âm thầm” cơ sở dữ liệu xuống client và sau đó người dùng có thể thoải mái tra cứu mà không cần request đến server.
Interface Storage
interface Storage {
readonly attribute unsigned long length;
DOMString? key(unsigned long index);
getter DOMString getItem(DOMString key);
setter creator void setItem(DOMString key, DOMString value);
deleter void removeItem(DOMString key);
void clear();
};
Như bạn thấy, các dữ liệu lưu trữ trong Storage chỉ là kiểu chuỗi, với các loại dữ liệu khác số nguyên, số thực, bool, ... bạn cần phải thực hiện chuyển đối kiểu. Mỗi đối tượng Storage là một danh sách các cặp key/value, đối tượng này bao gồm các thuộc tính và phương thức:
- length: số lượng cặp key/value có trong đối tượng.
- key(n): trả về tên của key thứ n trong danh sách.
- getItem(key): trả về value được gắn với key.
- setItem(key,value): thêm hoặc gán một cặp key/value vào danh sách.
- removeItem(key): xóa cặp key/value khỏi danh sách.
- clear: xóa toàn bộ dữ liệu trong danh sách.
Bên cạnh đó, đối tượng Storage còn có thể được truy xuất qua các thuộc tính là các key trong danh sách.
Ví dụ:
localStorage.abc="123";
// equivalent to:
// localStorage.setItem("abc","123");
Local Storage và Session Storage
Hai đối tượng này là được tạo ra từ interface Storage, bạn sử dụng hai đối tượng này trong javascript qua hai biến được tạo sẵn là window.localStorage và window.sessionStorage. Hai lợi ích mà chúng mang lại là:
- Dễ sử dụng: bạn có thể truy xuất dữ liệu của hai đối tượng này thông qua các thuộc tính hoặc các phương thức. Dữ liệu được lưu trữ theo từng cặp key/value và không cần bất kì công việc khởi tạo hay chuẩn bị nào.
- Dung lượng lưu trữ lớn: Tùy theo trình duyệt, bạn có thể lưu trữ từ 5MB đến 10MB cho mỗi domain. Theo Wikipedia thì con số này là: 5MB trong Mozilla Firefox, Google Chrome,và Opera, 10MB trong Internet Explorer.
Phạm vi:
- sessionStorage: giới hạn trong một cửa sổ hoăc thẻ của trình duyệt. Một trang web được mở trong hai thẻ của cùng một trình duyệt cũng không thể truy xuất dữ liệu lẫn nhau. Như vậy, khi bạn đóng trang web thì dữ liệu lưu trong sessionStorage hiện tại cũng bị xóa.
- localStorage: có thể truy xuất lẫn nhau giữa các cửa sổ trình duyệt. Dữ liệu sẽ được lưu trữ không giới hạn thời gian.
Đối với localStorage:
Bạn có thể đọc và dịch nguyên văn tiếng Anh dưới đây:
“Each domain and subdomain has its own separate local storage area. Domains can access the storage areas of subdomains, and subdomains can access the storage areas of parent domains. For example, localStorage['example.com'] is accessible to example.com and any of its subdomains. The subdomainlocalStorage['www.example.com'] is accessible to example.com, but not to other subdomains, such as mail.example.com.”
Bạn có thể xem thêm về localStorage tại: http://v1study.com/html5-web-storage-a423.html#localstorage
Sử dụng
Bạn có thể tạo một tập tin HTML với nội dung phía dưới để chạy trên trình duyệt. Ở đây ta sử dụng Chrome vì nó cung cấp sẵn cửa sổ xem phần Resources trong Google Chrome Developer Tools (Ctrl + Shift + I). Nội dung của tập tin HTML như sau:
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
sessionStorage.myVariable="Hello. ";
localStorage.myVariable="Nice to meet you!";
document.write(sessionStorage.myVariable);
document.write(localStorage.myVariable);
</script>
</body>
</html>
Kết quả hiển thị:
Trong giao diện xem Resources, bạn có thể mở phần Console để gõ các lệnh javascript tương tác với trang web hiện tại. Ví dụ ở đây ta thêm các giá trị mới vào trong localStorage và dùng alert() để hiển thị chúng lên:
Storage event
Đối tượng Window trong javascript cung cấp một event với tên “storage”. Event này được kích hoạt mỗi khi storageArea bị thay đổi.
interface StorageEvent : Event {
readonly attribute DOMString key;
readonly attribute DOMString? oldValue;
readonly attribute DOMString? newValue;
readonly attribute DOMString url;
readonly attribute Storage? storageArea;
};
Event này có thể không hoạt động khi bạn xem tập tin HTML ở máy cục bộ và chỉ được kích hoạt ở những cửa sổ/thẻ khác. Tức là khi bạn mở nhiều cửa sổ trình duyệt truy xuất đến cùng domain, nếu bạn thay đổi một đối tượng Storage bên cửa sổ này thì các cửa sổ còn lại sẽ được kích hoạt event “storage”, còn cửa sổ hiện tại sẽ không xảy ra gì cả.
<!DOCTYPE html>
<html>
<body>
<button onclick="changeValue();">Change Value</button>
<script type="text/javascript">
localStorage.clear();
console.log(localStorage);
if (window.addEventListener)
window.addEventListener('storage', storage_event, false);
else if (window.attachEvent) // IE
window.attachEvent('onstorage', storage_event, false);
function storage_event(event){
console.log(event);
}
function changeValue(){
localStorage.myValue=Math.random();
}
</script>
</body>
</html>
Thêm các phương thức vào Storage
Các phương thức của Storage có thể không đủ đáp ứng yêu cầu của bạn, vì vậy bạn có thể thêm một vài phương thức mới vào để sử dụng khi cần thiết. Ví dụ ta sẽ thêm phương thức search() để lọc ra các giá trị chứa từ khóa cần tìm kiếm.
Storage.prototype.search = function(keyword) {
var array=new Array();
var re = new RegExp(keyword,"gi");
for (var i = 0; i < this.length; i++) {
var value=this.getItem(this.key(i));
if(value.search(re)>-1)
array.push(value);
}
return array;
}
Phương thức trên sử dụng biểu thức chính quy để tìm kiếm theo hai tùy chọn “g” (tìm kiếm toàn bộ chuỗi) và “i” (không phân biệt hoa thường). Phương thức string.search() trả về vị trí của kí tự đầu tiên khớp với từ khóa tìm kiếm, ngược lại là -1 nếu không tìm thấy.