Local Storage

С возвращением.
В предыдущем уроке ты познакомился с формами и валидацией.
Формы собирают данные пользователя.
Валидация проверяет, имеют ли эти данные смысл.
Очень полезно.
Очень ответственно.
Очень в стиле: “пожалуйста, не вводи banana как email.”
Сегодня мы научим JavaScript очень интересной вещи.
Памяти.
Не настоящей человеческой памяти.
JavaScript не запомнит твой день рождения и не принесёт торт.
Но он может запоминать маленькие кусочки данных в браузере.
Это называется local storage.
Local storage позволяет JavaScript сохранять данные даже после обновления страницы.
Это значит, что страница может помнить такие вещи:
- имя пользователя;
- выбор темы;
- список задач;
- простую настройку;
- маленькие фрагменты данных из формы.
До local storage JavaScript забывал всё после перезагрузки страницы.
После local storage JavaScript становится немного менее забывчивым.
Всё ещё хаотичным.
Но прогресс есть.
Что Ты Изучишь
В этом уроке ты изучишь:
- что такое local storage;
- как сохранять данные через
localStorage.setItem; - как читать данные через
localStorage.getItem; - как удалять данные через
localStorage.removeItem; - как очистить весь local storage;
- почему local storage сохраняет строки;
- как сохранять объекты и массивы через
JSON.stringify; - как читать объекты и массивы через
JSON.parse; - как создать маленькое сохранение имени;
- как создать простой список задач, который переживёт refresh.
В конце этого урока твоя JavaScript-страница сможет помнить простые данные.
Не всё.
Не секреты.
Не пароли.
Но достаточно, чтобы быть полезной.
Как маленький блокнот внутри браузера.
Что Такое Local Storage?
Local storage — это возможность браузера, которая позволяет сайтам сохранять небольшие объёмы данных.
Данные остаются в браузере даже после:
- обновления страницы;
- закрытия вкладки;
- повторного открытия браузера.
Пример:
localStorage.setItem("name", "Viktor");
Это сохраняет значение "Viktor" под ключом "name".
Позже мы можем его прочитать:
const name = localStorage.getItem("name");
console.log(name);
Результат:
Viktor
Браузер запомнил значение.
Очень приятно.
Очень удобно.
Немного магически.
Но это всё ещё просто JavaScript.
Важное Предупреждение
Не сохраняй чувствительные данные в local storage.
Не сохраняй:
- пароли;
- токены, которые ты не понимаешь;
- приватные документы;
- банковскую информацию;
- секретные API keys;
- что-либо, от чего ты начал бы потеть, если бы это кто-то увидел.
Local storage — это не безопасное хранилище.
Он полезен для простых данных.
Выбор темы?
Хорошо.
Список задач?
Нормально.
Пароль?
Нет.
Абсолютно нет.
Безопасность — это не декоративное растение.
Она имеет значение.
Создай Проект
Создай папку для этого урока:
mkdir javascript-lesson10
cd javascript-lesson10
touch index.html
touch script.js
Твой проект должен выглядеть так:
javascript-lesson10/
index.html
script.js
Открой папку в редакторе.
Сегодня мы будем сохранять данные в браузере.
Браузер сейчас станет маленьким блокнотом.
Надеюсь, не слишком беспорядочным.
Напиши HTML
Открой index.html и добавь:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Local Storage</title>
</head>
<body>
<h1>Local Storage</h1>
<button id="saveButton">Сохранить Имя</button>
<button id="loadButton">Загрузить Имя</button>
<p id="message">Пока ничего не загружено.</p>
<script src="script.js"></script>
</body>
</html>
Это даёт нам:
- кнопку сохранения;
- кнопку загрузки;
- место для сообщения.
Просто.
Маленько.
Готово что-то запомнить.
Что уже больше, чем можно сказать о некоторых браузерах после 38 открытых вкладок.
Сохранение Данных через setItem
Открой script.js и добавь:
const saveButton = document.getElementById("saveButton");
const loadButton = document.getElementById("loadButton");
const messageElement = document.getElementById("message");
function saveName() {
localStorage.setItem("name", "Viktor");
messageElement.textContent = "Имя сохранено.";
}
saveButton.addEventListener("click", saveName);
Обнови браузер.
Нажми Сохранить Имя.
Сообщение должно показать:
Имя сохранено.
Эта строка важна:
localStorage.setItem("name", "Viktor");
Она означает:
Сохрани значение "Viktor" под ключом "name".
Local storage работает с парами ключ-значение.
Ключ — это как этикетка.
Значение — это данные.
Как этикетка на ящике и вещь внутри ящика.
Очень организованно.
Подозрительно организованно.
Чтение Данных через getItem
Теперь добавь эту функцию:
function loadName() {
const savedName = localStorage.getItem("name");
messageElement.textContent = `Сохранённое имя: ${savedName}`;
}
loadButton.addEventListener("click", loadName);
Теперь полный script.js выглядит так:
const saveButton = document.getElementById("saveButton");
const loadButton = document.getElementById("loadButton");
const messageElement = document.getElementById("message");
function saveName() {
localStorage.setItem("name", "Viktor");
messageElement.textContent = "Имя сохранено.";
}
function loadName() {
const savedName = localStorage.getItem("name");
messageElement.textContent = `Сохранённое имя: ${savedName}`;
}
saveButton.addEventListener("click", saveName);
loadButton.addEventListener("click", loadName);
Нажми Сохранить Имя.
Обнови страницу.
Нажми Загрузить Имя.
Имя всё ещё там.
JavaScript его запомнил.
Страница обновилась.
Данные выжили.
Маленькое чудо.
Без backend.
Без базы данных.
Просто браузер делает браузерные вещи.
Что Если Данных Нет?
Если ты пытаешься прочитать ключ, которого не существует, получишь null.
Пример:
const savedAge = localStorage.getItem("age");
console.log(savedAge);
Результат:
null
null означает:
Здесь ничего нет.
Поэтому лучше проверять данные перед тем, как показывать их пользователю.
Пример:
function loadName() {
const savedName = localStorage.getItem("name");
if (savedName === null) {
messageElement.textContent = "Имя ещё не сохранено.";
return;
}
messageElement.textContent = `Сохранённое имя: ${savedName}`;
}
Теперь страница ведёт себя лучше.
Если имени нет, она об этом говорит.
Очень вежливо.
Очень цивилизованно.
В отличие от случайных JavaScript-ошибок в полночь.
Сохранение Input-а Пользователя
Записать "Viktor" прямо в коде хорошо для обучения.
Но обычно мы хотим сохранить то, что вводит пользователь.
Обнови index.html:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Local Storage</title>
</head>
<body>
<h1>Local Storage</h1>
<label for="nameInput">Твоё имя:</label>
<input id="nameInput" type="text" placeholder="Введи своё имя">
<button id="saveButton">Сохранить Имя</button>
<button id="loadButton">Загрузить Имя</button>
<button id="removeButton">Удалить Имя</button>
<p id="message">Пока ничего не загружено.</p>
<script src="script.js"></script>
</body>
</html>
Теперь обнови script.js:
const nameInput = document.getElementById("nameInput");
const saveButton = document.getElementById("saveButton");
const loadButton = document.getElementById("loadButton");
const removeButton = document.getElementById("removeButton");
const messageElement = document.getElementById("message");
function saveName() {
const name = nameInput.value.trim();
if (name === "") {
messageElement.textContent = "Сначала введи имя.";
return;
}
localStorage.setItem("name", name);
messageElement.textContent = "Имя сохранено.";
nameInput.value = "";
}
function loadName() {
const savedName = localStorage.getItem("name");
if (savedName === null) {
messageElement.textContent = "Имя ещё не сохранено.";
return;
}
messageElement.textContent = `Сохранённое имя: ${savedName}`;
}
function removeName() {
localStorage.removeItem("name");
messageElement.textContent = "Имя удалено.";
}
saveButton.addEventListener("click", saveName);
loadButton.addEventListener("click", loadName);
removeButton.addEventListener("click", removeName);
Теперь пользователь может ввести имя.
Сохранить его.
Обновить страницу.
Загрузить снова.
Удалить.
Это настоящее использование local storage.
Маленькое.
Практичное.
Полезное.
Как карманный блокнот, но с большим количеством фигурных скобок.
Удаление Данных через removeItem
Эта строка удаляет один сохранённый элемент:
localStorage.removeItem("name");
Она удаляет значение, сохранённое под ключом "name".
Только этот элемент.
Не всё.
Это полезно, когда пользователь хочет сбросить одну настройку.
Пример:
localStorage.removeItem("theme");
localStorage.removeItem("username");
localStorage.removeItem("draft");
Конкретно.
Контролируемо.
Без лишнего разрушения.
Очень зрело.
Как для JavaScript.
Очистка Всего Local Storage
Есть также:
localStorage.clear();
Это удаляет всё, что сохранено в local storage для этого сайта.
Всё.
Все ключи.
Все значения.
Исчезли.
Используй осторожно.
Пример:
function clearStorage() {
localStorage.clear();
}
Это полезно для кнопок reset.
Но не используй это случайно.
Это цифровой эквивалент уборки стола огнемётом.
Эффективно.
Но агрессивно.
Local Storage Сохраняет Строки
Важная деталь.
Local storage сохраняет значения как строки.
Пример:
localStorage.setItem("age", 33);
const age = localStorage.getItem("age");
console.log(age);
console.log(typeof age);
Результат:
33
string
Даже если мы сохранили число, local storage возвращает строку.
Это важно.
Если тебе нужно число, преобразуй его:
const age = Number(localStorage.getItem("age"));
JavaScript любит сюрпризы с типами.
Держи глаза открытыми.
И, возможно, одну бровь поднятой.
Сохранение Объектов
Local storage не может напрямую сохранять объекты.
Это не работает так, как ты хочешь:
const user = {
name: "Viktor",
role: "Student"
};
localStorage.setItem("user", user);
Результат станет примерно таким:
[object Object]
Очень бесполезно.
Очень JavaScript.
Чтобы сохранить объект, преобразуй его в строку через JSON.stringify.
Пример:
const user = {
name: "Viktor",
role: "Student"
};
localStorage.setItem("user", JSON.stringify(user));
Теперь объект сохранён как JSON-строка.
JSON — это текстовый формат для данных.
Он похож на JavaScript-объекты.
Но это текст.
Маленькая разница.
Большое значение.
Чтение Объектов
Чтобы прочитать объект обратно, используй JSON.parse.
Пример:
const savedUser = localStorage.getItem("user");
const user = JSON.parse(savedUser);
console.log(user.name);
console.log(user.role);
Результат:
Viktor
Student
Полный пример:
const user = {
name: "Viktor",
role: "Student"
};
localStorage.setItem("user", JSON.stringify(user));
const savedUser = localStorage.getItem("user");
const parsedUser = JSON.parse(savedUser);
console.log(parsedUser);
Шаблон такой:
JSON.stringify(data)
когда сохраняем.
JSON.parse(data)
когда читаем.
Stringify, чтобы сохранить.
Parse, чтобы использовать.
Просто.
Мощно.
Немного церемониально.
Сохранение Массивов
Массивы также требуют JSON.stringify.
Пример:
const tasks = ["Учить JavaScript", "Практиковать DOM", "Выпить кофе"];
localStorage.setItem("tasks", JSON.stringify(tasks));
Чтобы их прочитать:
const savedTasks = localStorage.getItem("tasks");
const tasks = JSON.parse(savedTasks);
console.log(tasks);
Результат:
["Учить JavaScript", "Практиковать DOM", "Выпить кофе"]
Это очень полезно.
Потому что многие приложения сохраняют списки.
Задачи.
Товары.
Избранное.
Настройки.
Маленькие списки вещей, которые важны пользователю.
Иногда списки вещей, которые пользователь всё равно забудет.
Но браузер помнит.
Создай Список Задач, Который Сохраняется
Теперь создадим маленький список задач, который переживёт refresh.
Обнови index.html:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Local Storage</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 700px;
margin: 60px auto;
padding: 0 24px;
background-color: #f3f4f6;
color: #111827;
}
.card {
background-color: white;
padding: 24px;
border: 2px solid #e5e7eb;
border-radius: 18px;
}
h1 {
font-size: 42px;
}
input {
width: 100%;
margin-top: 8px;
padding: 12px;
border: 2px solid #d1d5db;
border-radius: 12px;
font-size: 18px;
box-sizing: border-box;
}
button {
margin-top: 14px;
background-color: #2563eb;
color: white;
border: none;
padding: 12px 18px;
border-radius: 999px;
font-weight: 700;
cursor: pointer;
}
button:hover {
background-color: #1d4ed8;
}
ul {
padding-left: 24px;
margin-top: 20px;
}
li {
font-size: 20px;
margin-bottom: 10px;
}
.message {
margin-top: 16px;
font-size: 18px;
font-weight: 700;
}
</style>
</head>
<body>
<h1>Local Storage</h1>
<div class="card">
<label for="taskInput">Новая задача</label>
<input id="taskInput" type="text" placeholder="Введи задачу">
<button id="addTaskButton">Добавить Задачу</button>
<button id="clearTasksButton">Очистить Задачи</button>
<p id="message" class="message">Задачи появятся ниже.</p>
<ul id="taskList"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
Теперь обнови script.js:
const taskInput = document.getElementById("taskInput");
const addTaskButton = document.getElementById("addTaskButton");
const clearTasksButton = document.getElementById("clearTasksButton");
const taskListElement = document.getElementById("taskList");
const messageElement = document.getElementById("message");
let tasks = [];
function saveTasks() {
localStorage.setItem("tasks", JSON.stringify(tasks));
}
function loadTasks() {
const savedTasks = localStorage.getItem("tasks");
if (savedTasks !== null) {
tasks = JSON.parse(savedTasks);
}
}
function showTasks() {
taskListElement.innerHTML = "";
for (const task of tasks) {
const listItem = document.createElement("li");
listItem.textContent = task;
taskListElement.appendChild(listItem);
}
if (tasks.length === 0) {
messageElement.textContent = "Задач пока нет.";
} else {
messageElement.textContent = `У тебя ${tasks.length} задача/задач.`;
}
}
function addTask() {
const task = taskInput.value.trim();
if (task === "") {
messageElement.textContent = "Сначала введи задачу.";
return;
}
tasks.push(task);
saveTasks();
showTasks();
taskInput.value = "";
}
function clearTasks() {
tasks = [];
saveTasks();
showTasks();
}
addTaskButton.addEventListener("click", addTask);
clearTasksButton.addEventListener("click", clearTasks);
loadTasks();
showTasks();
Теперь протестируй.
Добавь задачу.
Обнови страницу.
Задача останется.
Добавь ещё одну задачу.
Обнови снова.
Она всё ещё там.
Поздравляю.
Ты создал маленькое приложение с памятью.
Без backend.
Без базы данных.
Только local storage.
Маленькая frontend-магия.
Очень приятно.
Как Работает Этот Код
Этот массив хранит задачи в JavaScript:
let tasks = [];
Эта функция сохраняет задачи в local storage:
function saveTasks() {
localStorage.setItem("tasks", JSON.stringify(tasks));
}
Эта функция загружает задачи из local storage:
function loadTasks() {
const savedTasks = localStorage.getItem("tasks");
if (savedTasks !== null) {
tasks = JSON.parse(savedTasks);
}
}
Эта функция показывает задачи на странице:
function showTasks() {
taskListElement.innerHTML = "";
for (const task of tasks) {
const listItem = document.createElement("li");
listItem.textContent = task;
taskListElement.appendChild(listItem);
}
}
Это добавляет задачу:
tasks.push(task);
saveTasks();
showTasks();
Важный шаблон:
Обнови данные.
Сохрани данные.
Покажи данные.
Этот шаблон есть везде.
Даже в больших приложениях.
Только с большим количеством файлов.
Большим количеством фреймворков.
И большими эмоциональными повреждениями.
Типичные Ошибки
Забыть JSON.stringify
Неправильно:
localStorage.setItem("tasks", tasks);
Правильно:
localStorage.setItem("tasks", JSON.stringify(tasks));
Массивы и объекты нужно преобразовывать в строки перед сохранением.
Иначе JavaScript становится странным.
Ещё более странным, чем обычно.
Забыть JSON.parse
Неправильно:
const tasks = localStorage.getItem("tasks");
Правильно:
const tasks = JSON.parse(localStorage.getItem("tasks"));
Если ты сохранил JSON, сделай parse при чтении.
Stringify при сохранении.
Parse при загрузке.
Как упаковывать и распаковывать чемодан.
Пытаться Сохранить Чувствительные Данные
Плохая идея:
localStorage.setItem("password", password);
Не делай этого.
Пароли не принадлежат local storage.
Local storage — это не сейф.
Это скорее ящик в твоей комнате.
Полезно.
Но не место для золотых слитков.
Забыть Обновить Страницу После Сохранения
Если ты только сохранишь задачу:
tasks.push(task);
saveTasks();
но не вызовешь:
showTasks();
данные сохранены, но страница не обновляется.
Браузер не читает мысли.
Скажи ему, что показать.
Практика
Создай маленькую страницу, которая сохраняет любимый цвет.
Страница должна иметь:
- input;
- кнопку сохранения;
- кнопку загрузки;
- место для сообщения.
Когда пользователь сохраняет цвет, запиши его в local storage.
Когда пользователь загружает цвет, покажи:
Твой любимый цвет — blue.
Бонус:
Измени фон страницы на этот цвет.
Осторожно с цветами.
Если пользователь введёт “pizza”, браузер может не понять.
Хотя духовно pizza всегда правильный выбор.
Мини-Челлендж
Создай приложение для заметок.
Страница должна иметь:
- textarea;
- кнопку сохранения;
- кнопку загрузки;
- кнопку очистки.
Правила:
- сохрани заметку в local storage;
- загрузи заметку после refresh;
- очисти заметку, когда пользователь нажмёт clear;
- показывай сообщение после каждого действия.
Это очень практичный челлендж.
Многие реальные приложения начинаются с этой идеи:
Пользователь что-то пишет.
Приложение это сохраняет.
Пользователь возвращается позже.
Данные всё ещё там.
Просто.
Полезно.
Мощно.
Итог
Сегодня ты изучил:
- local storage сохраняет данные в браузере;
- данные переживают refresh;
localStorage.setItemсохраняет данные;localStorage.getItemчитает данные;localStorage.removeItemудаляет один элемент;localStorage.clearудаляет всё;- local storage сохраняет строки;
- числа могут требовать преобразования;
- объекты и массивы требуют
JSON.stringify; - сохранённый JSON требует
JSON.parse; - local storage полезен для простых данных;
- local storage не для паролей или секретов.
Это огромный шаг.
Твои страницы теперь могут помнить вещи.
Маленькие вещи.
Полезные вещи.
Браузерные вещи.
JavaScript получил маленькую память.
Очень полезную.
Очень опасную, если использовать неправильно.
Как дать блокнот еноту.
Следующий Урок
В следующем уроке мы изучим Fetch API.
Fetch позволяет JavaScript получать данные из других мест.
API.
Серверов.
JSON-файлов.
Реальных данных из внешнего мира.
До этого большинство данных жило внутри нашего кода.
Скоро JavaScript начнёт говорить с интернетом.
Осторожно.
Надеюсь.