Подписывайтесь на мой твиттер, там всегда что-нибудь интересное!

Как работать с localStorage в JavaScript

В этой статье вы узнаете о том, что такое localStorage и на рабочем примере узнаем то, как с ним работать в JavaScript.

Перевод статьи How to Use Local Storage with JavaScript

Мне нравится делать обучающие материалы о том, как создавать небольшие приложения буквально с нуля, используя чистый JavaScript. Создание to-do списка это распространенная идея для создания приложения, а без базы данных, в которую можно положить задачи, она становится особенной полезной, но добавляет некоторые сложности для начинающих.

Однако, даже без базы данных, мы можем использовать встроенное в браузер веб-хранилище, чтобы сохранять туда задачи из to-do списка.Такое приложение было бы особенно полезным для создания быстрых заметок. Вы бы просто установили ярлык на приложение при запуске новой вкладки и задачи to-do будут находиться на вашем компьютере пока вы не очистите кэш.

Вот то, что мы сегодня будем делать:

Демка

Исходник

Для того, чтобы понимать статью, вам нужно знать основы HTML и CSS, понимать типы данных и синтаксис JavaScript, вместе с DOM манипуляциями.

Целью этой статьи является создание быстрого приложения, которое будет хранить to-do элементы в веб-хранилище браузера на вашем компьютере и показывать их на фронте. Посмотрите пример.

Что такое веб-хранилище

В веб-хранилище хранятся данные пользователя браузера. Есть два типа веб-хранилищ:

localStorage — это данные, которые хранятся бессрочно и будут доступны даже после перезагрузки браузера.

sessionStorage — это данные, которые стираются после того, как окно браузера закрывается.

Веб-хранилище довольно удобно для сохранения данных, таких как предпочтения пользователей (светлая или темная цветовая схема на сайте и тп), сохранение товаров, положенных в корзину или запоминание того, что пользователь залогинен на сайте.

До этого, для запоминания такого рода локальных, временных данных, использовались только кукисы. В локальном веб-хранилище вы можете хранить значительно больше данных (5MB vs 4KB) и не обращаться к ним, при каждом HTTP вызове, таким образом, это может быть лучшим вариантом для хранилища данных на стороне клиента.

Вот обзор методов localStorage

setItem() — добавляет пару ключ-значение в локальное веб-хранилище

getItem() — получает значение по ключу

removeItem() — удаляет элемент по ключу

clear() — очищает хранилище

Вы можете посмотреть то, что находится в локальном хранилище, зайдя в консоль и введя в неё localStorage.

Storage {length: 0}

Добавление данных в localStorage очень простой процесс, вы можете использовать setItem() метод. Я буду использовать общепринятые имена для пары ключ-значение, но они могут быть любой производной строкой.

localStorage.setItem('key', 'value')

Теперь, если вы проверите localStorage в консоле, то вы там увидите новый ключ и значение.

Storage {key: "value", length: 1}

Если вы хотите получить значение конкретного ключа, то вам надо будет использовать метод getItem().

localStorage.getItem('key')
value

И наконец, вы можете удалить данные с помощью removeItem().

localStorage.removeItem('key')

А используя clear(), вы очистите всё веб-хранилище.

localStorage.clear()

Теперь мы можем приступить к созданию приложения.

Подготавливаем фронт

Сначала мы создадим простенькую HTML разметку в index.html. Я работаю в Primitive(мой минималистический HTML Фреймворк) для стилей, потому что это то, что я всегда использую, если мне нужен быстрый фронт.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Tab App</title>
<link rel="stylesheet" href="https://unpkg.com/primitive-ui/dist/css/main.css" />
  </head>
<body>
    <div class="small-container">
      <h1>New Tab App</h1>
<!-- more will go here -->
    </div>
  
    <script src="js/scripts.js"></script>
  </body>
</html>

Тут нам надо уделить внимание настройке трёх вещей:

Текстовой input— для добавления новых элементов.

Список — то место, куда будут добавляться новые элементы на фронте.

Кнопка — для сброса всех элементов.

Добавьте этот код туда, где стоит комментарий <! — more will go here — >

<form>
  <input id="item" type="text" placeholder="New" required />
</form>
<h2>Items</h2>
<ul></ul>
<button>Clear All</button>

И вот, как всё это будет выглядеть.

Далее мы сосредоточимся на написании функционала в JavaScript.

Пишем функционал на JavaScript

Перед тем, как интегрировать всё это с локальным веб-хранилищем, давайте подцепим на JS форму и список, через которые мы хотим добавлять данные в input и выводить их в ul.

Для начала, я собираюсь объявить несколько переменных для элементов на странице.

const form = document.querySelector('form')
const ul = document.querySelector('ul')
const button = document.querySelector('button')
const input = document.getElementById('item')

Далее, я напишу функцию, которая создаст элемент li, так как этот функционал нам потребуется очень часто. Я назову функцию liMaker(). Она просто будет создавать элемент li, выставлять ему текст, который будет как параметр и добавлять созданный li в ul.

const liMaker = text => {
  const li = document.createElement('li')
  li.textContent = text
  ul.appendChild(li)
}

Далее, я собираюсь добавить прослушиватель события на форму, которая связана с submit — событие, которое будет происходить всякий раз, как мы нажмем на enter в форме.e.preventDefault() предотвратит отправку формы при сабмите, это нам не нужно, так как мы не собираемся отправлять никаких данных на сервер.

Вместо этого, форма отправит значение input. Мы вызовем функцию liMaker(), которая создаст элемент с текстом, который будет значением input и далее, мы добавим это в DOM. И под конец, мы выставим значение input на пустую строку, таким образом вам не придётся вручную стирать то, что вы только написали.

form.addEventListener('submit', function(e) {
  e.preventDefault()
liMaker(input.value)
  input.value = ''
})

Теперь, с буквально пустяковым количеством кода на борту, мы имеем небольшое приложение, которое добавляет to-do элементы в список задач.

Но, так как мы нигде не сохраняем наши данные, то при закрытии или обновлении браузера, введенные нами элементы исчезнут. Последним шагом будет интеграция нашего приложения с локальным хранилищем, для того, чтобы данные оставались в нём и после перезагрузки страницы, и после перезагрузки браузера.

Интегрируем локальное хранилище

Сейчас мы добавим немного функционала в наше приложение. Во первых, каждый раз, когда форму будут сабмитить, значение из input будет добавлено в localStorage вместе с мгновенным отображением в списке задач. Также, нам нужно будет пробежаться циклом по всему локальному хранилищу и показать элементы этого хранилища сверху списка существующих задач. Ну и под конец, мы добавим кнопку “Clear All”, которая удалит все элементы не только из локального хранилища, но и из списка ul.

Давайте сначала создадим пустой массив и создадим в localStorage ключ под названием itemslocalStorage в виде значений ключей принимает только строки, к тому же, нам надо хранить задачи в массиве.

Мы можем обойти это ограничение с помощью JSON.stringify(), чтобы конвертировать массив в строку. А уже потом мы применим JSON.parse() для конвертирования содержимого localStorage в какой-нибудь рабочий формат, который мы положим в переменную data. Вставьте этот код под всем, что мы написали выше.

let itemsArray = []

localStorage.setItem('items', JSON.stringify(itemsArray))
const data = JSON.parse(localStorage.getItem('items'))

В слушателе событий мы будем отправлять каждое новое значение input в массив, а затем добавлять в localStorage новое значение с уже обновленным массивом.

e.preventDefault()
itemsArray.push(input.value)
localStorage.setItem('items', JSON.stringify(itemsArray))

Далее, мы собираемся пробежаться по всему содержимому переменной data, которая содержит всё из нашего localStorage в таком виде, в котором мы можем работать с этими данным в JavaScript. Затем мы заново запустим liMaker(). Это покажет нам всю нужную информацию в списке при каждом открытии приложения.

data.forEach(item => {
  liMaker(item)
})

И под конец мы добавим событие по клику на кнопку, которая очистит все данные из localStorage и удалит все потомков у ul.

button.addEventListener('click', function() {
  localStorage.clear()
  while (ul.firstChild) {
    ul.removeChild(ul.firstChild)
  }
})

Если всё пройдет хорошо, то данные запишутся в хранилище и покажутся в списке задач, а само хранилище вы сможете проверить введя localStorage в консоли.

Storage {items:
"["Welcome","to","the","Thunderdome"]",
  length: 1}

Но у нас осталась последняя проблема. После закрытия браузера или перезагрузки страницы, вся существующая информация в localStorage пропадает и ничего не остается на нашем фронте. Почему?

Потому, что наш itemsArray сбрасывается каждый раз при запуске скрипта. Мы можем пофиксить эту проблемку, создав условие, которое проверит наличие доступного localStorage:

let items
if (localStorage.getItem('items')) {
  items = JSON.parse(localStorage.getItem('items'))
} else {
  items = []
}

Практичнее было бы использовать тернарный оператор.

let itemsArray = localStorage.getItem('items') ? JSON.parse(localStorage.getItem('items')) : []

Теперь наше приложение завершено. И когда вы вводите какую-либо информацию, а затем обновляете или закрываете окно браузера, данные будут на месте, пока вы самостоятельно не очистите их в настройках браузера или запустив команду localStorage.clear(). Ну а вот и полный код JavaScript.

const form = document.querySelector('form')
const ul = document.querySelector('ul')
const button = document.querySelector('button')
const input = document.getElementById('item')
let itemsArray = localStorage.getItem('items') ? JSON.parse(localStorage.getItem('items')) : []
localStorage.setItem('items', JSON.stringify(itemsArray))
const data = JSON.parse(localStorage.getItem('items'))
const liMaker = text => {
  const li = document.createElement('li')
  li.textContent = text
  ul.appendChild(li)
}
form.addEventListener('submit', function(e) {
  e.preventDefault()
itemsArray.push(input.value)
  localStorage.setItem('items', JSON.stringify(itemsArray))
  liMaker(input.value)
  input.value = ''
})
data.forEach(item => {
  liMaker(item)
})
button.addEventListener('click', function() {
  localStorage.clear()
  while (ul.firstChild) {
    ul.removeChild(ul.firstChild)
  }
})

Заключение

В этом руководстве мы узнали о том, как сделать простое to-do приложение, которое можно использовать для быстрого напоминания о текущих задачах, просто вызвав новую вкладку, используя HTML5 веб-хранилище. Я надеюсь, что теперь у вас появилось лучшее понимание локального хранилища и того, как интегрировать его в простое приложение.

Почитайте про применение localStorage в следующей статье — Используем localStorage в React