Buổi 9: JSON & LocalStorage
Loại buổi: Lý thuyết
Thời lượng: 120 phút
Dự án: To-Do App (đã có CRUD cơ bản từ buổi 8)
🎯 Mục tiêu học tập
Sau buổi học này, bạn sẽ có thể:
- ✅ Hiểu JSON là gì và cách sử dụng
- ✅ Chuyển đổi giữa JSON và JavaScript object
- ✅ Sử dụng LocalStorage để lưu trữ dữ liệu
- ✅ Sử dụng SessionStorage để lưu trữ tạm thời
- ✅ Xử lý lỗi khi làm việc với Storage
- ✅ Áp dụng vào việc lưu dữ liệu ứng dụng
🧠 Nội dung chính
1. JSON là gì?
JSON (JavaScript Object Notation) là định dạng dữ liệu dạng text, dùng để lưu trữ và truyền dữ liệu.
Đặc điểm:
- Dễ đọc, dễ viết
- Nhẹ, nhanh
- Dùng để trao đổi dữ liệu giữa client và server
- Hỗ trợ bởi hầu hết ngôn ngữ lập trình
Cấu trúc JSON:
{
"hoTen": "Nguyễn Văn A",
"tuoi": 20,
"laSinhVien": true,
"danhSach": [1, 2, 3],
"diaChi": {
"soNha": "123",
"duong": "Đường ABC"
}
}Quy tắc JSON:
- Key phải là chuỗi (có dấu nháy kép)
- Giá trị có thể là: string, number, boolean, null, array, object
- Không có functions, undefined
- Không có comments
- Dấu phẩy cuối cùng không được phép
2. JSON.stringify() - Chuyển Object → JSON
Chuyển đổi JavaScript object/array thành chuỗi JSON:
let sinhVien = {
hoTen: 'Nguyễn Văn A',
tuoi: 20,
laSinhVien: true
};
let jsonString = JSON.stringify(sinhVien);
console.log(jsonString);
// '{"hoTen":"Nguyễn Văn A","tuoi":20,"laSinhVien":true}'
console.log(typeof jsonString); // "string"Ví dụ với mảng:
let danhSach = [
{ id: 1, ten: 'Công việc A' },
{ id: 2, ten: 'Công việc B' }
];
let jsonString = JSON.stringify(danhSach);
console.log(jsonString);
// '[{"id":1,"ten":"Công việc A"},{"id":2,"ten":"Công việc B"}]'Tham số thứ 2: Replacer (lọc thuộc tính)
let sinhVien = {
hoTen: 'Nguyễn Văn A',
tuoi: 20,
password: 'secret123'
};
// Chỉ lấy hoTen và tuoi
let jsonString = JSON.stringify(sinhVien, ['hoTen', 'tuoi']);
console.log(jsonString);
// '{"hoTen":"Nguyễn Văn A","tuoi":20}'Tham số thứ 3: Space (định dạng đẹp)
let sinhVien = {
hoTen: 'Nguyễn Văn A',
tuoi: 20
};
let jsonString = JSON.stringify(sinhVien, null, 2);
console.log(jsonString);
// {
// "hoTen": "Nguyễn Văn A",
// "tuoi": 20
// }3. JSON.parse() - Chuyển JSON → Object
Chuyển đổi chuỗi JSON thành JavaScript object/array:
let jsonString = '{"hoTen":"Nguyễn Văn A","tuoi":20,"laSinhVien":true}';
let sinhVien = JSON.parse(jsonString);
console.log(sinhVien);
// { hoTen: 'Nguyễn Văn A', tuoi: 20, laSinhVien: true }
console.log(sinhVien.hoTen); // "Nguyễn Văn A"Ví dụ với mảng:
let jsonString = '[{"id":1,"ten":"Công việc A"},{"id":2,"ten":"Công việc B"}]';
let danhSach = JSON.parse(jsonString);
console.log(danhSach);
// [{ id: 1, ten: 'Công việc A' }, { id: 2, ten: 'Công việc B' }]Xử lý lỗi:
let jsonString = '{invalid json}';
try {
let data = JSON.parse(jsonString);
} catch (error) {
console.error('Lỗi parse JSON:', error.message);
// Xử lý lỗi...
}4. LocalStorage - Lưu trữ vĩnh viễn
LocalStorage lưu trữ dữ liệu trên trình duyệt, tồn tại vĩnh viễn cho đến khi:
- Người dùng xóa
- Code xóa
- Dữ liệu hết hạn (theo trình duyệt)
Đặc điểm:
- Lưu trữ theo domain (mỗi website có localStorage riêng)
- Dung lượng: ~5-10MB
- Chỉ lưu được string
- Dữ liệu không tự động hết hạn
4.1. setItem() - Lưu dữ liệu
// Lưu string
localStorage.setItem('ten', 'Nguyễn Văn A');
localStorage.setItem('tuoi', '20');
// Lưu object/array (phải stringify trước)
let sinhVien = {
hoTen: 'Nguyễn Văn A',
tuoi: 20
};
localStorage.setItem('sinhVien', JSON.stringify(sinhVien));
let danhSach = [1, 2, 3];
localStorage.setItem('danhSach', JSON.stringify(danhSach));4.2. getItem() - Lấy dữ liệu
// Lấy string
let ten = localStorage.getItem('ten');
console.log(ten); // "Nguyễn Văn A"
// Lấy object/array (phải parse)
let sinhVienString = localStorage.getItem('sinhVien');
let sinhVien = JSON.parse(sinhVienString);
console.log(sinhVien); // { hoTen: 'Nguyễn Văn A', tuoi: 20 }
// Kiểm tra null trước khi parse
let danhSachString = localStorage.getItem('danhSach');
let danhSach = danhSachString ? JSON.parse(danhSachString) : [];4.3. removeItem() - Xóa một key
localStorage.removeItem('ten');4.4. clear() - Xóa tất cả
localStorage.clear(); // Xóa tất cả dữ liệu của domain4.5. key() - Lấy key theo index
// Lấy key đầu tiên
let firstKey = localStorage.key(0);
console.log(firstKey);
// Duyệt tất cả keys
for (let i = 0; i < localStorage.length; i++) {
let key = localStorage.key(i);
let value = localStorage.getItem(key);
console.log(`${key}: ${value}`);
}4.6. length - Số lượng items
console.log(localStorage.length); // Số lượng items5. SessionStorage - Lưu trữ tạm thời
SessionStorage tương tự LocalStorage nhưng:
- Dữ liệu tự động xóa khi đóng tab/window
- Dữ liệu chỉ tồn tại trong session hiện tại
Cách sử dụng giống LocalStorage:
// Lưu
sessionStorage.setItem('ten', 'Nguyễn Văn A');
// Lấy
let ten = sessionStorage.getItem('ten');
// Xóa
sessionStorage.removeItem('ten');
// Xóa tất cả
sessionStorage.clear();Khi nào dùng SessionStorage vs LocalStorage:
- LocalStorage: Dữ liệu cần lưu lâu dài (cài đặt, giỏ hàng, danh sách công việc...)
- SessionStorage: Dữ liệu tạm thời (form đang điền, thông tin session...)
6. Xử lý lỗi và best practices
6.1. Xử lý lỗi khi parse JSON
function layDuLieuTuStorage(key) {
try {
let dataString = localStorage.getItem(key);
if (!dataString) {
return null; // Hoặc giá trị mặc định
}
return JSON.parse(dataString);
} catch (error) {
console.error(`Lỗi parse JSON cho key "${key}":`, error);
// Xóa dữ liệu lỗi
localStorage.removeItem(key);
return null; // Hoặc giá trị mặc định
}
}6.2. Kiểm tra hỗ trợ Storage
function kiemTraStorage() {
try {
localStorage.setItem('test', 'test');
localStorage.removeItem('test');
return true;
} catch (error) {
return false;
}
}
if (!kiemTraStorage()) {
console.warn('Trình duyệt không hỗ trợ LocalStorage');
}6.3. Xử lý quá dung lượng
function luuDuLieu(key, data) {
try {
localStorage.setItem(key, JSON.stringify(data));
return true;
} catch (error) {
if (error.name === 'QuotaExceededError') {
console.error('LocalStorage đã đầy!');
// Xóa dữ liệu cũ hoặc thông báo người dùng
return false;
}
throw error;
}
}6.4. Helper functions
// Lưu object/array
function luuStorage(key, data) {
try {
localStorage.setItem(key, JSON.stringify(data));
return true;
} catch (error) {
console.error('Lỗi lưu Storage:', error);
return false;
}
}
// Lấy object/array
function layStorage(key, defaultValue = null) {
try {
let dataString = localStorage.getItem(key);
if (!dataString) {
return defaultValue;
}
return JSON.parse(dataString);
} catch (error) {
console.error('Lỗi đọc Storage:', error);
return defaultValue;
}
}
// Xóa
function xoaStorage(key) {
localStorage.removeItem(key);
}
// Sử dụng
luuStorage('danhSachCongViec', [{ id: 1, ten: 'CV 1' }]);
let danhSach = layStorage('danhSachCongViec', []);💻 Ví dụ minh họa
Ví dụ 1: Lưu và tải danh sách công việc
// Dữ liệu mẫu
let danhSachCongViec = [
{ id: 1, ten: 'Học JavaScript', trangThai: 'chua lam' },
{ id: 2, ten: 'Làm bài tập', trangThai: 'dang lam' }
];
// Lưu vào LocalStorage
function luuDanhSach() {
localStorage.setItem('danhSachCongViec', JSON.stringify(danhSachCongViec));
}
// Tải từ LocalStorage
function taiDanhSach() {
let dataString = localStorage.getItem('danhSachCongViec');
if (dataString) {
danhSachCongViec = JSON.parse(dataString);
} else {
danhSachCongViec = []; // Khởi tạo mảng rỗng
}
}
// Tự động tải khi trang load
taiDanhSach();
// Tự động lưu khi thay đổi
function themCongViec(ten) {
let congViecMoi = {
id: Date.now(),
ten: ten,
trangThai: 'chua lam'
};
danhSachCongViec.push(congViecMoi);
luuDanhSach(); // Tự động lưu
}Ví dụ 2: Xử lý lỗi đầy đủ
const Storage = {
// Lưu dữ liệu
luu: function(key, data) {
try {
if (!this.kiemTra()) {
throw new Error('LocalStorage không được hỗ trợ');
}
localStorage.setItem(key, JSON.stringify(data));
return true;
} catch (error) {
if (error.name === 'QuotaExceededError') {
console.error('LocalStorage đã đầy!');
alert('Không thể lưu dữ liệu. Vui lòng xóa dữ liệu cũ.');
} else {
console.error('Lỗi lưu Storage:', error);
}
return false;
}
},
// Lấy dữ liệu
lay: function(key, defaultValue = null) {
try {
if (!this.kiemTra()) {
return defaultValue;
}
let dataString = localStorage.getItem(key);
if (!dataString) {
return defaultValue;
}
return JSON.parse(dataString);
} catch (error) {
console.error('Lỗi đọc Storage:', error);
// Xóa dữ liệu lỗi
localStorage.removeItem(key);
return defaultValue;
}
},
// Xóa
xoa: function(key) {
if (this.kiemTra()) {
localStorage.removeItem(key);
}
},
// Xóa tất cả
xoaTatCa: function() {
if (this.kiemTra()) {
localStorage.clear();
}
},
// Kiểm tra hỗ trợ
kiemTra: function() {
try {
localStorage.setItem('test', 'test');
localStorage.removeItem('test');
return true;
} catch (error) {
return false;
}
}
};
// Sử dụng
Storage.luu('danhSachCongViec', [{ id: 1, ten: 'CV 1' }]);
let danhSach = Storage.lay('danhSachCongViec', []);Ví dụ 3: Lưu cài đặt người dùng
// Cài đặt mặc định
let caiDat = {
theme: 'light',
ngonNgu: 'vi',
thongBao: true
};
// Tải cài đặt
function taiCaiDat() {
let saved = localStorage.getItem('caiDat');
if (saved) {
caiDat = { ...caiDat, ...JSON.parse(saved) };
}
}
// Lưu cài đặt
function luuCaiDat() {
localStorage.setItem('caiDat', JSON.stringify(caiDat));
}
// Cập nhật cài đặt
function capNhatCaiDat(key, value) {
caiDat[key] = value;
luuCaiDat();
}
// Sử dụng
taiCaiDat();
capNhatCaiDat('theme', 'dark');🧪 Quiz cuối buổi (7 câu)
Câu 1: JSON có thể chứa function không?
A. Có
B. Không
C. Tùy trường hợp
D. Chỉ arrow function
Đáp án: B
Câu 2: LocalStorage lưu được những kiểu dữ liệu nào?
A. Chỉ string
B. String, number, boolean
C. Tất cả kiểu dữ liệu
D. Chỉ object
Đáp án: A (chỉ string, phải stringify object/array)
Câu 3: Khi nào SessionStorage tự động xóa?
A. Khi đóng tab
B. Khi đóng trình duyệt
C. Sau 24 giờ
D. Không bao giờ
Đáp án: A
Câu 4: JSON.parse('[1, 2, 3]') trả về gì?
A. String
B. Array
C. Object
D. Lỗi
Đáp án: B
Câu 5: Cách nào lưu object vào LocalStorage?
A. localStorage.setItem('key', obj)
B. localStorage.setItem('key', JSON.stringify(obj))
C. localStorage.save('key', obj)
D. Cả A và B
Đáp án: B
Câu 6: Dung lượng tối đa của LocalStorage?
A. 1MB
B. 5-10MB
C. Không giới hạn
D. 100MB
Đáp án: B
Câu 7: localStorage.getItem('key') trả về gì nếu key không tồn tại?
A. undefined
B. null
C. '' (chuỗi rỗng)
D. Lỗi
Đáp án: B
📝 Bài tập về nhà (chuẩn bị cho buổi 10)
- Tạo helper functions cho LocalStorage (luu, lay, xoa)
- Lưu danh sách công việc vào LocalStorage khi thêm/sửa/xóa
- Tự động tải danh sách từ LocalStorage khi trang load
- Xử lý trường hợp dữ liệu rỗng hoặc lỗi
- Thêm nút "Xóa tất cả dữ liệu" để clear LocalStorage
🔗 Tài liệu tham khảo
Chúc bạn học tập tốt! 🚀