Хранение данных на стороне клиента
Содержание:
- HTML Tutorial
- Событие storage
- Транзакции
- cookie.isSupported
- Слежение за областью HTML5-хранилища
- Курсоры
- Описание интерфейса
- Веб-хранилище. Назначение localStorage и sessionStorage
- What is the Web Storage API?
- Используем localStorage в React
- Веб хранилище
- Наш компонент для рабочего примера
- Автоматическая фиксация транзакций
- Full Example
- Поиск по индексированному полю
- Builds
- Setting up JavaScript functionality
HTML Tutorial
HTML HOMEHTML IntroductionHTML EditorsHTML BasicHTML ElementsHTML AttributesHTML HeadingsHTML ParagraphsHTML StylesHTML FormattingHTML QuotationsHTML CommentsHTML Colors
Colors
RGB
HEX
HSL
HTML CSSHTML Links
Links
Link Colors
Link Bookmarks
HTML Images
Images
Image Map
Background Images
The Picture Element
HTML TablesHTML Lists
Lists
Unordered Lists
Ordered Lists
Other Lists
HTML Block & InlineHTML ClassesHTML IdHTML IframesHTML JavaScriptHTML File PathsHTML HeadHTML LayoutHTML ResponsiveHTML ComputercodeHTML SemanticsHTML Style GuideHTML EntitiesHTML SymbolsHTML EmojisHTML CharsetHTML URL EncodeHTML vs. XHTML
Событие storage
Когда обновляются данные в или , генерируется событие со следующими свойствами:
- – ключ, который обновился (, если вызван ).
- – старое значение (, если ключ добавлен впервые).
- – новое значение (, если ключ был удалён).
- – url документа, где произошло обновление.
- – объект или , где произошло обновление.
Важно: событие срабатывает на всех остальных объектах , где доступно хранилище, кроме того окна, которое его вызвало. Давайте уточним
Давайте уточним.
Представьте, что у вас есть два окна с одним и тем же сайтом. Хранилище разделяется между ними.
Вы можете открыть эту страницу в двух окнах браузера, чтобы проверить приведённый ниже код.
Теперь, если оба окна слушают , то каждое из них будет реагировать на обновления, произошедшие в другом окне.
Обратите внимание, что событие также содержит: – url-адрес документа, в котором данные обновились. Также содержит объект хранилища – событие одно и то же для и , поэтому ссылается на то хранилище, которое было изменено
Мы можем захотеть что-то записать в ответ на изменения
Также содержит объект хранилища – событие одно и то же для и , поэтому ссылается на то хранилище, которое было изменено. Мы можем захотеть что-то записать в ответ на изменения.
Это позволяет разным окнам одного источника обмениваться сообщениями.
Современные браузеры также поддерживают Broadcast channel API специальный API для связи между окнами одного источника, он более полнофункциональный, но менее поддерживаемый. Существуют библиотеки (полифилы), которые эмулируют это API на основе и делают его доступным везде.
Транзакции
Термин «транзакция» является общеизвестным, транзакции используются во многих видах баз данных.
Транзакция – это группа операций, которые должны быть или все выполнены, или все не выполнены (всё или ничего).
Например, когда пользователь что-то покупает, нам нужно:
- Вычесть деньги с его счёта.
- Отправить ему покупку.
Будет очень плохо, если мы успеем завершить первую операцию, а затем что-то пойдёт не так, например отключат электричество, и мы не сможем завершить вторую операцию. Обе операции должны быть успешно завершены (покупка сделана, отлично!) или необходимо отменить обе операции (в этом случае пользователь сохранит свои деньги и может попытаться купить ещё раз).
Транзакции гарантируют это.
Все операции с данными в IndexedDB могут быть сделаны только внутри транзакций.
Для начала транзакции:
- – это название хранилища, к которому транзакция получит доступ, например, . Может быть массивом названий, если нам нужно предоставить доступ к нескольким хранилищам.
-
– тип транзакции, один из:
- – только чтение, по умолчанию.
- – только чтение и запись данных, создание/удаление самих хранилищ объектов недоступно.
Есть ещё один тип транзакций: . Такие транзакции могут делать любые операции, но мы не можем создать их вручную. IndexedDB автоматически создаёт транзакцию типа , когда открывает базу данных, для обработчика . Вот почему это единственное место, где мы можем обновлять структуру базы данных, создавать/удалять хранилища объектов.
Почему существует несколько типов транзакций?
Производительность является причиной, почему транзакции необходимо помечать как или .
Несколько readonly транзакций могут одновременно работать с одним и тем же хранилищем объектов, а readwrite транзакций – не могут. Транзакции типа readwrite «блокируют» хранилище для записи. Следующая такая транзакция должна дождаться выполнения предыдущей, перед тем как получит доступ к тому же самому хранилищу.
После того, как транзакция будет создана, мы можем добавить элемент в хранилище, вот так:
Мы сделали четыре шага:
- Создать транзакцию и указать все хранилища, к которым необходим доступ, строка .
- Получить хранилище объектов, используя , строка .
- Выполнить запрос на добавление элемента в хранилище объектов , строка .
- …Обработать результат запроса , затем мы можем выполнить другие запросы и так далее.
Хранилища объектов поддерживают два метода для добавления значений:
-
put(value, )
Добавляет значение в хранилище. Ключ необходимо указать, если при создании хранилища объектов не было указано свойство или . Если уже есть значение с таким же ключом, то оно будет заменено. -
add(value, )
То же, что , но если уже существует значение с таким ключом, то запрос не выполнится, будет сгенерирована ошибка с названием .
Аналогично открытию базы, мы отправляем запрос: и после ожидаем события .
- для является ключом нового объекта.
- Ошибка находится в (если есть).
Checks if cookies are enabled in the browser.
Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... if(localStorageService.cookie.isSupported) { //... } //... });
Directly adds a value to cookies.Note: Typically used as a fallback if local storage is not supported.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... function submit(key, val) { return localStorageService.cookie.set(key, val); } //... });
Cookie Expiry Pass a third argument to specify number of days to expiry
localStorageService.cookie.set(key,val,10)
localStorageService.cookie.set(key,val,null,false)
sets a cookie that is secure.
Directly get a value from a cookie.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... function getItem(key) { return localStorageService.cookie.get(key); } //... });
Remove directly value from a cookie.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... function removeItem(key) { return localStorageService.cookie.remove(key); } //... });
Remove all data for this app from cookie.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... function clearAll() { return localStorageService.cookie.clearAll(); } });
Слежение за областью HTML5-хранилища
Если вы хотите программно отслеживать изменения хранилища, то должны отлавливать событие storage. Это событие возникает в объекте window, когда setItem(), removeItem() или clear() вызываются и что-то изменяют. Например, если вы установили существующее значение или вызвали clear() когда нет ключей, то событие не сработает, потому что область хранения на самом деле не изменилась.
Событие storage поддерживается везде, где работает объект localStorage, включая Internet Explorer 8. IE 8 не поддерживает стандарт W3C addEventListener (хотя он, наконец-то, будет добавлен в IE 9), поэтому, чтобы отловить событие storage нужно проверить, какой механизм событий поддерживает браузер (если вы уже проделывали это раньше с другими событиями, то можете пропустить этот раздел до конца). Перехват события storage работает так же, как и перехват других событий. Если вы предпочитаете использовать jQuery или какую-либо другую библиотеку JavaScript для регистрации обработчиков событий, то можете проделать это и со storage тоже.
if (window.addEventListener) {
window.addEventListener(«storage», handle_storage, false);
} else {
window.attachEvent(«onstorage», handle_storage);
};
Функция обратного вызова handle_storage будет вызвана с объектом StorageEvent, за исключением Internet Explorer, где события хранятся в window.event.
function handle_storage(e) {
if (!e) { e = window.event; }
}
В данном случае переменная e будет объектом StorageEvent, который обладает следующими полезными свойствами.
Свойство | Тип | Описание |
---|---|---|
key | string | Ключ может быть добавлен, удален или изменен. |
oldValue | любой | Предыдущее значение (если переписано) или null, если добавлено новое значение. |
newValue | любой | Новое значение или null, если удалено. |
url* | string | Страница, которая вызывает метод, приведший к изменению. |
* Примечание: свойство url изначально называлось uri и некоторые браузеры поддерживали это свойство перед изменением спецификации. Для обеспечения максимальной совместимости вы должны проверить существует ли свойство url, и если нет проверить вместо него свойство uri.
Событие storage нельзя отменить, внутри функции обратного вызова handle_storage нет возможности остановить изменение. Это просто способ браузеру сказать вам: «Эй, это только что случилось. Вы ничего не можете сделать, я просто хотел, чтобы вы знали».
Курсоры
Такие методы как возвращают массив ключей/значений.
Но хранилище объектов может быть огромным, больше, чем доступно памяти.
Тогда метод вернёт ошибку при попытке получить все записи в массиве.
Что делать?
Курсоры предоставляют возможности для работы в таких ситуациях.
Объект cursor идёт по хранилищу объектов с заданным запросом (query) и возвращает пары ключ/значение по очереди, а не все сразу. Это позволяет экономить память.
Так как хранилище объектов внутренне отсортировано по ключу, курсор проходит по хранилищу в порядке хранения ключей (по возрастанию по умолчанию).
Синтаксис:
- ключ или диапазон ключей, как для .
-
необязательный аргумент, доступные значения:
- – по умолчанию, курсор будет проходить от самого маленького ключа к большему.
- – обратный порядок: от самого большого ключа к меньшему.
- , – то же самое, но курсор пропускает записи с тем же ключом, что уже был (только для курсоров по индексам, например, для нескольких книг с price=5, будет возвращена только первая).
Основным отличием курсора является то, что генерируется многократно: один раз для каждого результата.
Вот пример того, как использовать курсор:
Основные методы курсора:
- – продвинуть курсор на позиций, пропустив значения.
- – продвинуть курсор к следующему значению в диапазоне соответствия (или до позиции сразу после ключа key, если указан).
Независимо от того, есть ли ещё значения, соответствующие курсору или нет – вызывается , затем в мы можем получить курсор, указывающий на следующую запись или равный .
В приведённом выше примере курсор был создан для хранилища объектов.
Но мы также можем создать курсор для индексов. Как мы помним, индексы позволяют искать по полю объекта. Курсоры для индексов работают так же, как для хранилищ объектов – они позволяют экономить память, возвращая одно значение в единицу времени.
Для курсоров по индексам является ключом индекса (например price), нам следует использовать свойство как ключ объекта:
Описание интерфейса
Интерфейс Storage, принадлежащий API веб-хранилища предоставляет доступ к локальному объекту хранения (localStorage), или объекту хранения текущего сеанса (sessionStorage) для определенного домена (создавшего объект хранения источника):
- sessionStorage — поддерживает отдельную область хранения для каждого заданного источника, доступную на время сеанса страницы (пока открыт браузер, включая перезагрузку и восстановление страницы).
- localStorage — делает то же самое, но сохраняется даже при закрытии и повторном открытии браузера.
Эти механизмы доступны через свойства объекта Window sessionStorage и localStorage (точнее говоря, в браузерах объект Window реализует объекты WindowLocalStorage и WindowSessionStorage, которые содержат свойства localStorage и sessionStorage). Вызов одного из этих свойств создаст экземпляр объекта Storage, с помощью которого можно устанавливать, извлекать и удалять элементы данных из хранилища.
Для localStorage и sessionStorage для каждого домена используется отдельный объект хранения — они функционируют и управляются отдельно друг от друга.
Обращаю Ваше внимание, что объем веб-хранилища ограничен размером, и может составлять от 5 до 10 мегабайт, в зависимости от производителя браузера. Это значительно больший объем места на диске в сравнении с cookie, которому доступно всего 4 Кбайта
Веб-хранилище. Назначение localStorage и sessionStorage
Веб-хранилище — это данные, хранящиеся локально в браузере пользователя. Существует 2 типа веб-хранилищ:
- LocalStorage;
- SessionStorage.
В них вы можете хранить информацию в формате ключ-значение. Ключ и значение – это всегда строки.
Если мы попытаемся сохранить в значение элемента хранилища другой тип значений, например, объект, то он будет, перед тем как туда записан, преобразован в строку. В данном случае посредством неявного у него вызова метода . Т.е. в значении элемента этих хранилищ кроме строкового типа данных никакого другого содержаться не может.
Отличие между этими хранилищами сводится только к периоду времени, в течение которого они могут хранить данные, помещенные в них:
- SessionStorage – выполняет это в течение определённого промежутка времени (сессии). Закрытие вкладки или браузера приводит их к удалению. При этом данные в SessionStorage сохраняются при обновлении страницы.
- LocalStorage – осуществляет это в течение неограниченного времени. Они сохраняются при перезагрузке браузера и компьютера. Их длительность хранения ничем не ограничена. Но, хоть эти данные могут храниться бесконечно в браузере, обычный пользователь может их очень просто удалить, например выполнив очистку истории (при включенной опции «файлы cookie и другие данные сайтов»).
Хранилище LocalStorage похоже на cookies. Оно также применяется для хранения данных на компьютере пользователя (в браузере). Но кроме общих сходств имеется также и много отличий.
Cookies vs. LocalStorage: В чём разница
Отличия между cookies и LocalStorage:
- по месту хранения (куки и данные LocalStorage хранятся на компьютере пользователя в браузере);
- по размеру (cookies ограничены 4 Кбайт, а размер LocalStorage — 5 Мбайт);
- по включению этих данных в HTTP-заголовок (куки в отличие от данных локального хранилища включаются в состав запроса при отправке его на сервер, а также сервер их может добавлять в ответ при отправке его клиенту; таким образом cookies являются частью HTTP-протокола, и увеличивают объём передаваемых данных от клиента серверу и обратно);
- по доступности данных (печеньки можно прочитать и установить как на сервере, так и на клиенте; на клиенте доступны все куки, кроме тех, у которых установлен флаг ; LocalStorage доступны только в браузере посредством JavaScript API);
- по времени хранения данных (куки хранятся ограниченное время (до конца сеанса или истечения указанной даты), нахождение данных в локальном хранилище не ограничено по времени);
- по удобству использования в JavaScript (работа с LocalStorage в JavaScript организовано намного удобнее чем с cookies);
- по необходимости информирования пользователей Евросоюза (при использовании cookies сайт в ЕС должен получать на это разрешение от пользователей; для данных локального хранилища это не требуется);
- по назначению (куки в основном используются для управления сеансом, персонализации и отслеживания действий пользователя, в то время как LocalStorage применяется в качестве обычного локального хранилища информации на компьютере пользователя).
Что использовать: LocalStorage или cookies? На самом деле, ответ на этот вопрос очень прост. Если вам не нужно отправлять данные с каждым HTTP-запросом на сервер, то в этом случае лучше использовать для хранения данных LocalStorage.
Безопасность данных
Хранилище LocalStorage привязана к источнику (домену, протоколу и порту). Данные, находящиеся в некотором источнике, доступны для всех сценариев страниц этого же источника. Из сценария, находящегося в одном источнике, нельзя получить доступ к данным, определяемым другим источником.
Хранилище SessionStorage ограничена только одной вкладкой браузера. Это означает, что в сценарии, находящемся в одной вкладке, нельзя получить информацию из сессионного хранилища другой вкладки даже у них одинаковые источники.
Итоги
Основные характеристики LocalStorage и SessionStorage:
- данные хранятся в виде пар «ключ-значение»;
- хранить можно только строки;
- если вам необходимо хранить в этих хранилищах массивы и объекты, то сначала вы должны их превратить в строки, например, используя метод . Для преобразования строки обратно в массив или объект, можно использовать . Подробнее об этом позже.
What is the Web Storage API?
The Web Storage API is a set of mechanisms that enable browsers to store key-value pairs. It is designed to be much more intuitive than using cookies.
The key-value pairs represent storage objects, which are similar to objects except they remain intact during page loads, and are always strings. You can access these values like an object or using the method (more on that later).
What is the difference between and ?
The Web Storage API consists of two mechanisms: and . Both and maintain a separate storage area for each available origin for the duration of the page session.
The main difference between and is that only maintains a storage area while the browser is open (including when the page reloads or restores) while continues to store data after the browser is closed. In other words, whereas data stored in is cleared when the page is closed, data stored in does not expire.
In this tutorial, we’ll focus on how to use in JavaScript.
Используем localStorage в React
Перевод How to use localStorage with React
Как использовать преимущества localStorage в React? Да легко! В этой статье вы узнаете об удобстве применения локального хранилища в React приложениях.
Сердцем каждого приложения на React является его стейт. Компоненты могут иметь свой собственный внутренний стейт и поверьте мне, несмотря на всю их простоту, вы можете делать с ними много невероятно крутых вещей. Но давайте представим, что вы создаёте приложение и в какой-то момент вам надо локально сохранить данные от пользователя или даже сохранить весь стейт для одного или нескольких других компонентов. И тут, возможно, вам захочется понять, а как же можно использовать в React приложении? Что же, начнем с того, что тут вам уже не помощник, но не переживайте, все будет довольно просто. Читаем дальше.
Веб хранилище
Оно создано для того, чтобы хранить данные в браузере и оно потерпело значительное количество позитивных улучшений в сравнении со своим предшественником — кукисами. Сначала оно было как HTML5 API, ну а потом переросло уже в независимую рабочую единицу. Хранилище поддерживается буквально каждым современным браузером и даже некоторыми старичками, например такими как IE8. Веб хранилище реализовано двумя способами: первый — , постоянное хранилище данных, которое можно сравнить с постоянными кукисами, второе —, хранилище существующее только на время определенной сессии и на определенный период времени. Хоть эта статья и работает с , но вы также можете применить все описанные методики и на sessionStorage.
Наш компонент для рабочего примера
Итак, нам нужен компонент на котором мы будем все испытывать. Тут я думаю, что страница логина с опцией “Remember me” подойдет идеально. Для простоты и понятности, мы не будем добавлять поле пароля. Давайте посмотрим на метод :
render() {
return (
<form onSubmit={this.handleFormSubmit}>
<label>
User: <input name=»user» value={this.state.user} onChange={this.handleChange}/>
</label>
<label>
<input name=»rememberMe» checked={this.state.rememberMe} onChange={this.handleChange} type=»checkbox»/> Remember me
</label>
<button type=»submit»>Sign In</button>
</form>
);
}
1 2 3 4 5 6 7 8 9 10 11 12 13 |
render(){ return( <form onSubmit={this.handleFormSubmit}> <label> User<input name=»user»value={this.state.user}onChange={this.handleChange}> <label> <label> <input name=»rememberMe»checked={this.state.rememberMe}onChange={this.handleChange}type=»checkbox»>Remember me <label> <button type=»submit»>Sign In<button> <form> ); } |
export default class SignIn extends Component {
state = {
user: »,
rememberMe: false
};
handleChange = (event) => {
const input = event.target;
const value = input.type === ‘checkbox’ ? input.checked : input.value;
this.setState({ : value });
};
handleFormSubmit = () => {};
render() { /*…*/ }
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
exportdefaultclassSignInextendsComponent{ state={ user», rememberMefalse }; handleChange=(event)=>{ constinput=event.target; constvalue=input.type===’checkbox’?input.checkedinput.value; this.setState({input.namevalue}); }; handleFormSubmit=()=>{}; render(){/*…*/} } |
Если вы заполните инпут для пользователя, а потом кликните на “Remember Me” чекбокс и под конец кликните на кнопку “Sign In”, то вы заметите, что форма снова опустеет:
Это вполне нормальное поведение. Теперь мы должны узнать как же нам использовать в React и заставить форму работать должным образом.
Автоматическая фиксация транзакций
В примере выше мы запустили транзакцию и выполнили запрос . Но, как говорилось ранее, транзакция может включать в себя несколько запросов, которые все вместе должны либо успешно завершиться, либо нет. Как нам закончить транзакцию, обозначить, что больше запросов в ней не будет?
Короткий ответ: этого не требуется.
В следующей 3.0 версии спецификации, вероятно, будет возможность вручную завершить транзакцию, но сейчас, в версии 2.0, такой возможности нет.
Когда все запросы завершены и очередь микрозадач пуста, тогда транзакция завершится автоматически.
Как правило, это означает, что транзакция автоматически завершается, когда выполнились все её запросы и завершился текущий код.
Таким образом, в приведённом выше примере не требуется никакой специальный вызов, чтобы завершить транзакцию.
Такое автозавершение транзакций имеет важный побочный эффект. Мы не можем вставить асинхронную операцию, такую как или в середину транзакции. IndexedDB никак не заставит транзакцию «висеть» и ждать их выполнения.
В приведённом ниже коде в запросе в строке с будет ошибка, потому что транзакция уже завершена, больше нельзя выполнить в ней запрос:
Всё потому, что является асинхронной операцией, макрозадачей. Транзакции завершаются раньше, чем браузер приступает к выполнению макрозадач.
Авторы спецификации IndexedDB из соображений производительности считают, что транзакции должны завершаться быстро.
В частности, транзакции «блокируют» хранилища от записи. Таким образом, если одна часть приложения инициирует транзакцию в хранилище объектов , то другая часть приложения, которая хочет сделать то же самое, должна ждать: новая транзакция «зависает» до завершения первой. Это может привести к странным задержкам, если транзакции слишком долго выполняются.
Что же делать?
В приведённом выше примере мы могли бы запустить новую транзакцию перед новым запросом .
Но ещё лучше выполнять операции вместе, в рамках одной транзакции: отделить транзакции IndexedDB от других асинхронных операций.
Сначала сделаем , подготовим данные, если нужно, затем создадим транзакцию и выполним все запросы к базе данных.
Чтобы поймать момент успешного выполнения, мы можем повесить обработчик на событие :
Только гарантирует, что транзакция сохранена целиком. По отдельности запросы могут выполниться, но при финальной записи что-то может пойти не так (ошибка ввода-вывода, проблема с диском, например).
Чтобы вручную отменить транзакцию, выполните:
Это отменит все изменения, сделанные запросами в транзакции, и сгенерирует событие .
Full Example
import React, { Fragment } from 'react'; import { render } from 'react-dom'; import { writeStorage, deleteFromStorage, useLocalStorage } from '@rehooks/local-storage'; const startingNum = ; const Clicker = () => ( <Fragment> <h4>Clicker<h4> <button onClick={_ => { writeStorage('num', localStorage.getItem('num') ? +(localStorage.getItem('num')) + 1 : startingNum ) }}> Increment From Outside <button> <button onClick={_ => deleteFromStorage('num')}> Delete From Outside <button> <Fragment> ); const IncrememterWithButtons = () => { const number, setNum, deleteNum = useLocalStorage('num'); return ( <Fragment> <p>{typeof(number) === 'number' ? number : 'Try incrementing the number!'}<p> <button onClick={_ => setNum(number !== null ? +(number) + 1 : startingNum)}>Increment<button> <button onClick={deleteNum}>Delete<button> <Fragment> ); }; const App = () => ( <Fragment> <h1> Demo <h1> <IncrememterWithButtons > <Clicker > <Fragment> ); // Assuming there is a div in index.html with an ID of 'root' render(<App >, document.getElementById('root'));
Поиск по индексированному полю
Для поиска по другим полям объекта нам нужно создать дополнительную структуру данных, называемую «индекс» (index).
Индекс является «расширением» к хранилищу, которое отслеживает данное поле объекта. Для каждого значения этого поля хранится список ключей для объектов, которые имеют это значение. Ниже будет более подробная картина.
Синтаксис:
- – название индекса,
- – путь к полю объекта, которое индекс должен отслеживать (мы собираемся сделать поиск по этому полю),
-
– необязательный объект со свойствами:
- – если true, тогда в хранилище может быть только один объект с заданным значением в . Если мы попытаемся добавить дубликат, то индекс сгенерирует ошибку.
- – используется только, если является массивом. В этом случае, по умолчанию, индекс обрабатывает весь массив как ключ. Но если мы укажем true в , тогда индекс будет хранить список объектов хранилища для каждого значения в этом массиве. Таким образом, элементы массива становятся ключами индекса.
В нашем примере мы храним книги с ключом .
Допустим, мы хотим сделать поиск по полю .
Сначала нам нужно создать индекс. Индексы должны создаваться в , как и хранилище объектов:
- Индекс будет отслеживать поле .
- Поле price не уникальное, у нас может быть несколько книг с одинаковой ценой, поэтому мы не устанавливаем опцию .
- Поле price не является массивом, поэтому флаг не применим.
Представим, что в нашем есть 4 книги. Вот картинка, которая показывает, что такое «индекс».
Как уже говорилось, индекс для каждого значения (второй аргумент) хранит список ключей, имеющих эту цену.
Индексы автоматически обновляются, нам не нужно об этом заботиться.
Мы также можем использовать , чтобы создать диапазон и найти дешёвые/дорогие книги:
Индексы внутренне отсортированы по полю отслеживаемого объекта, в нашем случае по . Поэтому результат поиска будет уже отсортированный по полю .
Builds
Choose which build is right for you!
List of default builds
- store.everything.min.js: All the plugins, all the storages. Source
- store.legacy.min.js: Full support for all tested browsers. Add plugins separately. Source
- store.modern.min.js: Full support for all modern browsers. Add plugins separately. Source
- store.v1-backcompat.min.js: Full backwards compatibility with store.js v1. Source
Make your own Build
If you’re using npm you can create your own build:
// Example custom build usage: var engine = require('store/src/store-engine') var storages = require('store/storages/localStorage'), require('store/storages/cookieStorage') var plugins = require('store/plugins/defaults'), require('store/plugins/expire') var store = engine.createStore(storages, plugins) store.set('foo', 'bar', new Date().getTime() + 3000) // Using expire plugin to expire in 3 seconds
Setting up JavaScript functionality
Before we integrate this into local storage, let’s just get the form and list working — we want anything we submit in the to appear in the .
First, I’m just going to set up some variables for the elements on the page — the form, the unordered list, the button, and the text input.
scripts.js
Next, I’m going to make a function that creates an element, since I’ll be doing that more than once. I’ll call the function . It just creates an element, sets the text of the element to the parameter, and appends the list item to the .
scripts.js
I’m going to add an event listener to the form that watches for a submit event — which will be any time you press enter on the form. The will prevent the form from the default submit action, which we don’t want, since we’re not sending any data to a server.
Instead, the form will submit the value of the . We’re going to call the function, which will create the item with the text of the value and append it to the DOM. Finally, we’ll set the value to an empty string so you don’t have to erase the last item entered manually.
scripts.js
Now with paltry few lines of code, we have a little app that adds to-do items to a list.
Since we’re not saving the items anywhere, when you close or refresh the browser, the items will be gone. The final step is to integrate it into local storage so that the data persists.