Window.localstorage
Содержание:
- secStore.js
- Используем localStorage в React
- Веб хранилище
- Наш компонент для рабочего примера
- lz-string
- Examples #
- Summary
- Storage event
- Шаг 2: Получаем данные из localStorage
- И ещё совет
- Заключение
- Слежение за областью HTML5-хранилища
- cookie.isSupported
- Веб-хранилище. Назначение localStorage и sessionStorage
- isSupported
- Get Started
- Использование HTML5-хранилища
secStore.js
secStore.js is a data storage API that adds an optional layer of security by means of the Stanford Javascript Crypto Library. secStore.js lets you choose your storage method: localStorage, sessionStorage, or cookies. To use secStore.js, you have to also include the aforementioned sjcl.js library.
Here is an example demonstrating how to save some data with the option set to ‘true’:
Notice the method being used, which passes in the options you specify (including the custom data) along with a callback function that lets you test the results. We can then use the method to retrieve that data:
If you want to use session storage or cookies instead of local storage with secStore.js, you can define that in the options:
Используем 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 и заставить форму работать должным образом.
lz-string
The lz-string utility lets you store large amounts of data in localStorage by using compression and it’s pretty straightforward to use. After including the library on your page, you can do the following:
Notice the use of the and methods. The comments in the above code show the length values before and after compression. You can see how beneficial this would be seeing how client side storage always has limited space.
As explained in the library’s docs, there are options to compress data to Uint8Array (a new-ish data type in JavaScript) and even the ability to compress the data for storage outside of the client.
Examples #
The following sections demonstrate how to use to address some common use cases.
Synchronous response to storage updates
If you’re interested in tracking changes made to a data object, you can add a listener to its event. Whenever anything changes in storage, that event fires. Here’s sample code to listen for saved changes:
We can take this idea even further. In this example we have an options page that allows the user to toggle a «debug mode» in the extension (implementation not shown here). Changes to this setting are immediately saved to sync storage by the options page and the background script uses to apply the setting as soon as possible.
Asynchronous preload from storage
Since service workers are not always running, Manifest V3 extensions sometimes need to asynchronously load data from storage before they execute their event handlers. To do this, the below snippet uses an async event handler that waits for the global to be populated before executing its logic.
Summary
Web storage objects and allow to store key/value in the browser.
- Both and must be strings.
- The limit is 5mb+, depends on the browser.
- They do not expire.
- The data is bound to the origin (domain/port/protocol).
Shared between all tabs and windows with the same origin | Visible within a browser tab, including iframes from the same origin |
Survives browser restart | Survives page refresh (but not tab close) |
API:
- – store key/value pair.
- – get the value by key.
- – remove the key with its value.
- – delete everything.
- – get the key number .
- – the number of stored items.
- Use to get all keys.
- We access keys as object properties, in that case event isn’t triggered.
Storage event:
- Triggers on , , calls.
- Contains all the data about the operation (), the document and the storage object .
- Triggers on all objects that have access to the storage except the one that generated it (within a tab for , globally for ).
Storage event
When the data gets updated in or , event triggers, with properties:
- – the key that was changed ( if is called).
- – the old value ( if the key is newly added).
- – the new value ( if the key is removed).
- – the url of the document where the update happened.
- – either or object where the update happened.
The important thing is: the event triggers on all objects where the storage is accessible, except the one that caused it.
Let’s elaborate.
Imagine, you have two windows with the same site in each. So is shared between them.
You might want to open this page in two browser windows to test the code below.
If both windows are listening for , then each one will react on updates that happened in the other one.
Please note that the event also contains: – the url of the document where the data was updated.
Also, contains the storage object – the event is the same for both and , so references the one that was modified. We may even want to set something back in it, to “respond” to a change.
That allows different windows from the same origin to exchange messages.
Modern browsers also support Broadcast channel API, the special API for same-origin inter-window communication, it’s more full featured, but less supported. There are libraries that polyfill that API, based on , that make it available everywhere.
Шаг 2: Получаем данные из localStorage
Всё логику получения данных мы положим в , но вы можете спокойно положить её и в конструктор, если конечно захотите, так как её первоочередная цель — это выставление изначального стейта нашему компоненту.
Обратите внимание, что вы не можете вызывать перед тем, как компонент монтируется, так что, если вы предпочитаете подход с конструктором, то выставьте свойство стейта напрямую. Я же предпочитаю аккуратный подход к коснтуктору, настолько аккуратный насколько это возможно, но это дело предпочтений
componentDidMount() {
const rememberMe = localStorage.getItem(‘rememberMe’) === ‘true’;
const user = rememberMe ? localStorage.getItem(‘user’) : »;
this.setState({ user, rememberMe });
}
1 2 3 4 5 |
componentDidMount(){ constrememberMe=localStorage.getItem(‘rememberMe’)===’true’; constuser=rememberMe?localStorage.getItem(‘user’)»; this.setState({user,rememberMe}); } |
Теперь давайте углубимся в код:
Первым делом мы получаем значение “Remember me”
Уже обратили внимание, что сравнение идёт со строкой “true”? Это потому что хранит данные как строки. Таким образом нам надо получить хранящееся значение и запарсить его обратно в логический тип данных, перед его непосредственным использованием
Вы бы также могли использовать , если бы были точно уверены в том, что там всегда будет храниться булево значение в виде строки. Но сейчас это нам не подойдет, так как само значение не выставлено при инициализации страницы.
Далее мы получаем имя пользователя, но только в том случае, если имеет значение .
И под конец мы назначаем эти значения стейту компонента.
И вот она магия!
И ещё совет
Как я говорил выше, может хранить данные только в виде строк. Если вы имеете дело только с несколькими сохраненными значениями, то это не очень то и большая проблема. Но если вы хотите воспользоваться на полную катушку в вашем приложении, то я очень советую взять на вооружение библиотеку, которая облегчит сохранение и получение данных, обойдя стороной такие процессы, как парсинг и обращение в строку. В этом деле идеально может подойти проверенная в боях Store.js. Это моя личная рекомендация.
Заключение
В React очень просто использовать. Просто определите в каких случаях лучше сохранять и получать свои данные. Этот момент будет меняться от компонента к компоненту.
Вообще, вы можете давать данные компонентам, как и через конструктор, так и через . Но учтите, что если вы собираетесь использовать конструктор, то вам надо определять стейт заранее, напрямую указав его свойства, так как метод не сработает пока не смонтируется компонент.
Если вам нужна хорошая библиотека для работы со значениями , то рассмотрите использование Store.js.
Слежение за областью 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 нет возможности остановить изменение. Это просто способ браузеру сказать вам: «Эй, это только что случилось. Вы ничего не можете сделать, я просто хотел, чтобы вы знали».
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(); } });
Веб-хранилище. Назначение 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:
- данные хранятся в виде пар «ключ-значение»;
- хранить можно только строки;
- если вам необходимо хранить в этих хранилищах массивы и объекты, то сначала вы должны их превратить в строки, например, используя метод . Для преобразования строки обратно в массив или объект, можно использовать . Подробнее об этом позже.
isSupported
Checks if the browser support the current storage type(e.g: , ).
Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... if(localStorageService.isSupported) { //... } //... });
setPrefix
Change the local storage prefix during execution
Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... localStorageService.setPrefix('newPrefix'); //... });
getStorageType
Returns:
You can also dynamically change storage type by passing the storage type as the last parameter for any of the API calls. For example:
set
Directly adds a value to local storage.
If local storage is not supported, use cookies instead.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... function submit(key, val) { return localStorageService.set(key, val); } //... });
get
Directly get a value from local storage.
If local storage is not supported, use cookies instead.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... function getItem(key) { return localStorageService.get(key); } //... });
keys
Return array of keys for local storage, ignore keys that not owned.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... var lsKeys = localStorageService.keys(); //... });
remove
Remove an item(s) from local storage by key.
If local storage is not supported, use cookies instead.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... function removeItem(key) { return localStorageService.remove(key); } //... function removeItems(key1, key2, key3) { return localStorageService.remove(key1, key2, key3); } });
clearAll
Remove all data for this app from local storage.
If local storage is not supported, use cookies instead.Note: Optionally takes a regular expression string and removes matching.Returns:
myApp.controller('MainCtrl', function($scope, localStorageService) { //... function clearNumbers(key) { return localStorageService.clearAll(^\d+$); } //... function clearAll() { return localStorageService.clearAll(); } });
bind
Bind $scope key to localStorageService.
Usage:
key: The corresponding key used in local storage
Returns: deregistration function for this listener.
myApp.controller('MainCtrl', function($scope, localStorageService) { //... localStorageService.set('property', 'oldValue'); $scope.unbind = localStorageService.bind($scope, 'property'); //Test Changes $scope.update = function(val) { $scope.property = val; $timeout(function() { alert("localStorage value: " + localStorageService.get('property')); }); } //... });
<div ng-controller="MainCtrl"> <p>`property`</p> <input type="text" ng-model="lsValue"/> <button ng-click="update(lsValue)">update</button> <button ng-click="unbind()">unbind</button> </div>
deriveKey
Return the derive key
Returns
myApp.controller('MainCtrl', function($scope, localStorageService) { //... localStorageService.set('property', 'oldValue'); //Test Result console.log(localStorageService.deriveKey('property')); // ls.property //... });
length
Return localStorageService.length, ignore keys that not owned.
Returns
myApp.controller('MainCtrl', function($scope, localStorageService) { //... var lsLength = localStorageService.length(); // e.g: 7 //... });
Get Started
(1) You can install angular-local-storage using 3 different ways:Git:
clone & build this repositoryBower:
$ bower install angular-local-storage --save
npm:
$ npm install angular-local-storage
(2) Include (or ) from the dist directory in your , after including Angular itself.
(3) Add to your main module’s list of dependencies.
When you’re done, your setup should look similar to the following:
<!doctype html> <html ng-app="myApp"> <head> </head> <body> ... <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script> <script src="bower_components/js/angular-local-storage.min.js"></script> ... <script> var myApp = angular.module('myApp', 'LocalStorageModule'); </script> ... </body> </html>
Использование HTML5-хранилища
HTML5-хранилище базируется на именах пар ключ/значение. Вы сохраняете информацию, основываясь на имени ключа, а затем можете получить эти данные с тем же ключом. Имя ключа это строка. Данные могут быть любого типа, который поддерживает JavaScript, включая строки, логические, целые числа или числа с плавающей запятой. Однако в действительности данные хранятся в виде строки. Если вы сохраняете и извлекаете не строки, то надо будет использовать такие функции как parseInt() или parseFloat(), чтобы перевести полученные данные в корректные типы JavaScript.
Интерфейс хранилища {
Получить через getItem(ключ);
Установить через setItem(ключ, данные);
};
Вызов setItem() с существующим именем ключа молча перепишет предыдущее значение. Вызов getItem() с несуществующим ключом вернет NULL, а не вызовет исключение.
Подобно другим объектам JavaScript вы можете обращаться к объекту localStorage как к ассоциативному массиву. Вместо использования методов getItem() и setItem(), вы можете просто указать квадратные скобки. Например, этот фрагмент кода
var foo = localStorage.getItem(«bar»);
// …
localStorage.setItem(«bar», foo);
может быть переписан с использованием синтаксиса квадратных скобок:
var foo = localStorage;
// …
localStorage = foo;
Есть также методы для удаления значений по имени ключа, а также очистки всего хранилища (то есть удаление всех ключей и значений одновременно).
Интерфейс хранилища {
Удалить через removeItem(ключ);
clear();
}
Вызов removeItem() с несуществующим ключом ничего не вернет.
Наконец, есть свойство для получения общего количества значений в области хранения и для перебора всех ключей по индексу (получает имя каждого ключа).
Интерфейс хранилища {
length
Получить key(целое неотрицательное число);
}
Если при вызове key() индекс лежит не в диапазоне от 0 до (length-1), то функция вернет null.