Esse post é um dos posts mais visualizados do blog, foi criado em 2013, mas darei uma atualizada no que aconteceu de lá para cá. Armazenamento local com localStorage é umas dos recursos mais úteis do HTML5, podemos utilizar para uma infinidade de ações, agora com Progressive Web Apps esse recurso voltou a ficar evidência.
LocalStorage
Ela permite armazenar strings
com chave e valor é considerado cookies é uma forma mais segura de armazenamento, mas ela não tem acesso por Service Worker. Mas é um recurso nativo no browser de implementação simples que não necessita de plugin ou biblioteca externa.
Para aplicações mais complexas temos a opção de utilizar o IndexedDB. Mas um dos pontos fortes do localStorage
é o suporte comparado a outras APIs, ele é suportado por 93% dos navegadores:
LocalStorage
é um dos recursos do DOM Storage
com ele podemos armazenar dados apenas em formato de texto, mas claro podemos contornar essa limitação. Vamos primeiro exemplo básico de armazenamento.
localStorage.setItem("key_da_propriedade","Valor armazenado");
Code language: JavaScript (javascript)
No código acima adicionamos uma variável com nome “key_da_propriedade” que irá armazenar “Valor armazenado”. Quando esse código for armazenado pelo browser o usuário pode sair da aplicação, continuar navegando em outras aplicações, quando ele voltar para nossa aplicação o dado continuará lá. Esse recurso será útil caso utilizarmos uma versão offline da nossa aplicação com PWA.
Como visualizar os dados do LocalStorage?
Para visualizar a informação que foi salva, no Google Chrome, para abrir o DevTools vamos em menu > View > developer > developer tools
, tecla de atalho ctrl+shift+i
ou simples, clique o com botão direito do mouse e selecionamos a opção inspect
, com DevTools aberto vamos à aba Application
, na sessão storage
vemos a opções disponíveis. Quando clicamos em Local Storage
vemos as aplicações separadas por URL, no meu teste, estou rodando em localhost, clicando no URL da nossa aplicação, vemos os dados armazenados:
Agora que sabemos que a informação foi salva vamos resgatar esse valor com o seguinte código:
const minha_propriedade = localStorage.getItem('key_da_propriedade');
alert("Valor:" + minha_propriedade);
Code language: JavaScript (javascript)
No código acima passamos a função getItem
e como parâmetro passamos a key
da informação que queremos resgatar, na linha seguinte apenas executamos um alerta para exibir a informação.
Caso queria remover essa informação do localStorage
utilizamos o seguinte código:
localStorage.removeItem('key_da_propriedade');
Code language: JavaScript (javascript)
Aplicando localStorage, na prática
Agora vamos para um exemplo prático aplicando essas três funções que virmos acima, no caso: salvar, ler e excluir os dados no localStorage.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocalStorage tutorial</title>
<script>
window.addEventListener('load',() => {
if(localStorage.getItem('name')){
sayMyName()
}else{
whatsYourName()
}
});
function whatsYourName(){
document.body.innerHTML = '';
// criando um input para cadastrar o nome;
const inputName = document.createElement('input');
inputName.type = 'text';
inputName.placeholder = 'Digite seu nome';
inputName.id = 'nome';
document.body.appendChild(inputName);
// criando saveButton
const saveButton = document.createElement('button');
saveButton.innerHTML = 'Salvar';
document.body.appendChild(saveButton);
// adicionando listener para salvar a informação
saveButton.addEventListener('click', saveName);
}
function sayMyName(){
document.body.innerHTML = '';
// criando mensagem
const welcomeMessage = document.createElement('h1');
welcomeMessage.innerText = 'Olá' + localStorage.getItem("name");
// criando removeButton
const removeButton = document.createElement('button');
removeButton.innerHTML = 'Excluir';
document.body.appendChild(removeButton);
// adicionando o listener para remover informação
removeButton.addEventListener('click',removeName);
}
function removeName(){
if(localStorage.getItem('name')){
localStorage.removeItem('name');
whatsYourName()
}
}
function saveName(){
var nome = document.getElementById('nome').value;
localStorage.setItem('name', nome)
sayMyName();
}
</script>
</head>
<body>
</body>
</html>
Code language: HTML, XML (xml)
O Exemplo acima resumindo rapidamente ele verifica se tem o dado com a key
“name” no localStorage, caso tenha, exibe o nome. Caso contrário adiciona um input
para cadastrar o dado. Quando o nome é exibido também adicionamos um button
para chamar a função de excluir os dados. Nos Exemplos anteriores apenas adicionamos e removemos algumas strings
, para trabalhar com objetos no localStorage
precisamos usar a Classe JSON, com ela é possível fazer a ponte entre textos e objetos.
window.addEventListener('load',() => {
if(localStorage.getItem('user')){
const texto = localStorage.getItem("user");
const objeto = JSON.parse(texto);
document.body.innerHTML = `nome: <strong>${objeto.name}</strong> email: <strong>${objeto.email}<strong>`;
}else{
const user = {
name: 'Fellyph',
email: 'fellyph@fellyph.com.br'
}
const userString = JSON.stringify(user);
localStorage.setItem('user',userString);
document.body.innerHTML = 'dados salvos';
}
});
Code language: JavaScript (javascript)
No código acima focamos apenas no JavaScript, verificamos se existe um dado com uma key
“user”, caso o exista resgata a informação na variável “texto” em seguida convertemos o texto em objeto utilizando a método parse
da classe JSON. Assim temos um objeto como retorno e adicionamos o conteúdo no body
do nosso arquivo, no código acima utilizamos string literals
para concatenar o nosso conteúdo.
Caso o usuário não tenha nenhuma informação salva com a key “user”, o código irá criar um objeto e em seguida converter em texto, assim temos a possibilidade de salvar os dados no nosso localStorage
. Esse exemplo não é muito funcional, apenas exemplifica como é salvar um objeto no nosso localStorage
.
Agora vamos partir para um exemplo mais funcional, vamos montar uma todo-list utilizando localStorage
, desta vez vamos separar o código no arquivo todo-list.html, js/app.js
e css/style.css. O exemplo a seguir utiliza ES2015
caso queira dar uma olhada no exemplo em EcmaScript 5 só dá uma olhada no gitHub no seguinte link: https://github.com/fellyph/Tutorial-bbUI/tree/master/localstorage
Nosso HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Todo List</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/app.js"></script>
</head>
<body>
<h1>todo-list</h1>
<div id="tasks-output"></div>
<form id="form-task">
<input type="text" name="descricao" placeholder="adicione uma nova task" required>
<input type="submit" value="Salvar">
</form>
</body>
</html>
Code language: HTML, XML (xml)
Nosso CSS:
#tasks-output li {
cursor: pointer;
}
#form-task {
border-top: 1px solid #ddd;
padding: 10px 0;
margin: 10px 0;
}
#tasks-output li[data-done="true"] {
text-decoration: line-through;
}
Code language: CSS (css)
Detalhe para o último seletor que trata quando o item da lista possui o atributo data-done
igual a true
, ele vai adicionar uma linha sobre o texto.
let todoList;
let todoOutput;
function formatDate(date) {
// formata a data para o formato DD/MM/YYYY
const time = new Date(date);
return `${time.getDate()}/${time.getMonth()}/${time.getFullYear()}`;
}
function showList() {
// mostra a lista de todo
if (todoList.length > 0) {
const htmlTemp = `<ul>
${todoList.map(todoItem => `<li data-id="${todoItem.id}" data-done="${todoItem.done}">${todoItem.descricao} - ${formatDate(todoItem.date)}</li>` )}
</ul><button>Limpar tarefas realizadas</button>`;
todoOutput.innerHTML = htmlTemp;
} else {
todoOutput.innerHTML = 'Nenhuma tarefa cadastrada';
}
}
function saveList() {
// converte os dados em string e salva no local storage
localStorage.setItem('tasks', JSON.stringify(todoList));
}
function clearList() {
// varre a lista a procura de tarefas realizadas
for (let i = 0; i < todoList.length; i += 1) {
if (todoList[i].done === 'true') {
// remove 1 elemento na posição i;
todoList.splice(i, 1);
// voltando o indice no array para validar novamente a lista
i = 0;
} else {
todoList[i].id = i;
}
}
showList();
saveList();
}
function clickList(e) {
// somente fazer algo quando clicar em um item li
if (e.target.localName === 'li') {
e.target.dataset.done = !e.target.dataset.done === 'true';
todoList[e.target.dataset.id].done = e.target.dataset.done;
saveList();
} else if (e.target.localName === 'button') {
clearList();
}
}
function onSubmit(e) {
const task = {};
// pego o valor cadastrado no primeiro input do meu form
task.descricao = e.target[0].value;
task.date = new Date();
task.id = todoList.length;
task.done = 'false';
// adicionando a task na lista
todoList.push(task);
saveList();
showList();
// utiliza o preventDefault para evitar do form realizar o reload da página
e.preventDefault();
}
window.addEventListener('load', () => {
// guarda em uma variável o elemento tasks-output
todoOutput = document.getElementById('tasks-output');
if (localStorage.getItem('tasks')) {
todoList = JSON.parse(localStorage.getItem('tasks'));
showList();
} else {
todoList = [];
}
if (todoList.length === 0) {
todoOutput.innerHTML = 'Nenhuma tarefa cadastrada';
}
// adiciona o listener para o evento submit, utilizei form para usar o required do input HTML
document.getElementById('form-task').addEventListener('submit', onSubmit);
todoOutput.addEventListener('click', clickList);
});
Code language: JavaScript (javascript)
Tentei comentar os pontos-chave do código, na listagem utilizo um map
para montar a nossa lista. Caso não esteja familiarizado só conferir a versão anterior desse código no GIT ou conferir os posts relacionados a ecmaScript 2015, mas o código acima o usuário pode cadastrar as tasks que serão vinculadas uma data, quando o usuário clica no item da lista a propriedade “data-done” muda entre true
ou false
. Caso o utilizador queira limpar as suas listas de task clica no botão “Limpar tarefas…” o código irá varrer da lista os itens com valor da propriedade data-done
igual a true
e retirar da lista.
Além do LocalStorage
temos o SessionStorage
, a diferença entre os dois é que o sessionStorage
como o nome sugere, ele guarda as informações apenas na seção, ou seja, quando a aplicação é finalizada a informação é removida.
Quando utilizar localStorage?
LocalStorage é ideal para armazenar pequenas strings, nos nossos exemplos fomos em algo mais complexo para ter uma ideal do potencial deste recurso. Mas os casos mais comuns para o uso da API são:
- Configurações do usuário: preferências de idioma, tema da interface, etc.
- Dados persistentes: informações que precisam ser mantidas mesmo após o fechamento do navegador, como itens favoritos, carrinho de compras, etc.
- Cache de dados: armazenar dados localmente para melhorar o desempenho, como resultados de API ou imagens.
Quais são os problemas de utilizar localStorage?
Quando trabalhamos com local storage devemos lembrar que os dados que salvamos no
- Segurança: os dados armazenados no localStorage não são criptografados, o que significa que podem ser acessados por qualquer pessoa com acesso ao navegador.
- Tamanho: o localStorage tem um limite de armazenamento de 5MB por domínio.
- Compatibilidade: o localStorage não é suportado por todos os navegadores antigos.
- Sincronização: os dados armazenados no localStorage não são sincronizados entre diferentes navegadores ou dispositivos.
IndexDB e LocalStorage: Qual é o melhor?
IndexDB:
- Banco de dados NoSQL com maior capacidade de armazenamento e estruturação de dados.
- Permite transações complexas e acesso assíncrono.
- Suporta chaves compostas e índices para otimizar consultas.
LocalStorage:
- Mais simples de usar e implementar.
- Ideal para armazenar pequenas quantidades de dados simples.
- Acesso mais rápido do que o IndexDB.
Melhor escolha:
- IndexDB: Se você precisa armazenar grandes quantidades de dados estruturados ou precisa de transações complexas.
- LocalStorage: Se você precisa armazenar pequenas quantidades de dados simples e precisa de um acesso rápido.
Outras considerações:
- Segurança: O IndexDB oferece criptografia de dados, enquanto o localStorage não.
- Compatibilidade: O IndexDB não é suportado por todos os navegadores antigos, enquanto o localStorage tem uma compatibilidade maior.
Em resumo, o localStorage é uma boa opção para armazenar pequenas quantidades de dados simples que precisam ser persistentes. Se você precisa de mais flexibilidade, segurança ou capacidade de armazenamento, o IndexDB é a melhor escolha.
Fechamos por aqui e até o próximo tutorial, para saber mais como acessar recursos do device confira a página da categoria PWA.
Deixe um comentário